• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef HIPERF_CALLSTACK_H
16 #define HIPERF_CALLSTACK_H
17 
18 #include <map>
19 #include <optional>
20 #include <string>
21 #include <vector>
22 
23 #if !is_mingw
24 #include <sys/mman.h>
25 #endif
26 
27 #include "hashlist.h"
28 #include "register.h"
29 #include "utilities.h"
30 #include "unwinder.h"
31 #include "virtual_thread.h"
32 
33 using ADDR_TYPE = uintptr_t;
34 
35 namespace OHOS {
36 namespace Developtools {
37 namespace HiPerf {
38 using namespace OHOS::HiviewDFX;
39 const int MAX_CALL_FRAME_EXPAND_CYCLE = 10;
40 const size_t MAX_CALL_FRAME_EXPAND_CACHE_SIZE = 10;
41 const size_t MAX_CALL_FRAME_UNWIND_SIZE = 256;
42 
43 struct UnwindInfo;
44 
45 class CallStack {
46 public:
47     CallStack();
48     ~CallStack() = default;
49     void ClearCache();
50     bool UnwindCallStack(const VirtualThread &thread, bool abi32, u64 *regs, u64 regsNum,
51                          const u8 *stack, u64 stackSize, std::vector<DfxFrame> &,
52                          size_t maxStackLevel = MAX_CALL_FRAME_UNWIND_SIZE);
53     size_t ExpandCallStack(pid_t tid, std::vector<DfxFrame> &callFrames, size_t expandLimit = 1u);
54 
55 private:
56     pid_t lastPid_ = -1;
57     ADDR_TYPE lastAddr_ = 0;
58     ADDR_TYPE lastData_ = 0;
59     uint64_t stackPoint_ = 0;
60     uint64_t stackEnd_ = 0;
61     u64 *regs_ = nullptr; // not const , be cause we will fix it for arm64 cpu in UpdateRegForABI
62     u64 regsNum_ = 0;
63     const u8 *stack_ = nullptr;
64     u64 stackSize_ = 0;
65 
66     void LogFrame(const std::string msg, const std::vector<DfxFrame> &frames);
67     size_t DoExpandCallStack(std::vector<DfxFrame> &newCallFrames,
68                            const std::vector<DfxFrame> &cachedCallFrames, size_t expandLimit);
69 
70     // we have a cache for all thread
71     std::map<pid_t, HashList<uint64_t, std::vector<DfxFrame>>> cachedCallFramesMap_;
72     bool GetIpSP(uint64_t &ip, uint64_t &sp, const u64 *regs, size_t regNum) const;
73     ArchType arch_ = ArchType::ARCH_UNKNOWN;
74 
75     static bool ReadVirtualThreadMemory(UnwindInfo &unwindInfoPtr, ADDR_TYPE addr, ADDR_TYPE *data);
76 #if defined(HAVE_LIBUNWINDER) && HAVE_LIBUNWINDER
77     bool DoUnwind2(const VirtualThread &thread, std::vector<DfxFrame> &callStack, size_t maxStackLevel);
78     static void DumpTableInfo(UnwindTableInfo &outTableInfo);
79     static int FillUnwindTable(SymbolsFile *symbolsFile, std::shared_ptr<DfxMap> map, UnwindInfo *unwindInfoPtr,
80                                uintptr_t pc, UnwindTableInfo& outTableInfo);
81     static int FindUnwindTable(uintptr_t pc, UnwindTableInfo& outTableInfo, void *arg);
82     static int AccessMem2(uintptr_t addr, uintptr_t *val, void *arg);
83     static int GetMapByPc(uintptr_t pc, std::shared_ptr<DfxMap>& map, void *arg);
84 
85     // pid->unwinder(acc/regs/maps) cache
86     std::unordered_map<pid_t, std::shared_ptr<Unwinder>> pidUnwinder_;
87     // pid->elf->unwindtable cache
88     using DsoUnwindTableInfoMap = std::unordered_map<std::string, UnwindTableInfo>;
89     std::unordered_map<pid_t, DsoUnwindTableInfoMap> unwindTableInfoMap_;
90 
91     std::shared_ptr<UnwindAccessors> accessor_;
92 #endif
93 };
94 
95 struct UnwindInfo {
96     const VirtualThread &thread;
97     const u64 *regs;
98     size_t regNumber;
99     ArchType arch;
100     CallStack &callStack;
101 };
102 } // namespace HiPerf
103 } // namespace Developtools
104 } // namespace OHOS
105 #endif // HIPERF_CALLSTACK_H
106