• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 UNWINDER_H
16 #define UNWINDER_H
17 
18 #include <memory>
19 #include <unordered_map>
20 #include <vector>
21 #include "dfx_accessors.h"
22 #include "dfx_errors.h"
23 #include "dfx_frame.h"
24 #include "dfx_memory.h"
25 #include "dfx_maps.h"
26 #include "dfx_regs.h"
27 #if defined(__arm__)
28 #include "arm_exidx.h"
29 #endif
30 #include "dwarf_section.h"
31 #include "unwind_context.h"
32 
33 namespace OHOS {
34 namespace HiviewDFX {
35 class Unwinder {
36 public:
37     // for local
Unwinder()38     Unwinder() : pid_(UNWIND_TYPE_LOCAL)
39     {
40         acc_ = std::make_shared<DfxAccessorsLocal>();
41         enableFpCheckMapExec_ = true;
42         Init();
43     };
44     // for remote
Unwinder(int pid)45     Unwinder(int pid) : pid_(pid)
46     {
47         acc_ = std::make_shared<DfxAccessorsRemote>();
48         enableFpCheckMapExec_ = true;
49         Init();
50     };
51     // for customized
Unwinder(std::shared_ptr<UnwindAccessors> accessors)52     Unwinder(std::shared_ptr<UnwindAccessors> accessors) : pid_(UNWIND_TYPE_CUSTOMIZE)
53     {
54         acc_ = std::make_shared<DfxAccessorsCustomize>(accessors);
55         enableFpCheckMapExec_ = false;
56 #if defined(__aarch64__)
57         pacMask_ = pacMaskDefault_;
58 #endif
59         Init();
60     };
~Unwinder()61     ~Unwinder() { Destroy(); }
62 
SetTargetPid(int pid)63     inline void SetTargetPid(int pid) { pid_ = pid; }
GetTargetPid()64     inline int32_t GetTargetPid() { return pid_; }
SetPacMask(uintptr_t mask)65     inline void SetPacMask(uintptr_t mask) { pacMask_ = mask; }
66 
EnableUnwindCache(bool enableCache)67     inline void EnableUnwindCache(bool enableCache) { enableCache_ = enableCache; }
EnableLrFallback(bool enableLrFallback)68     inline void EnableLrFallback(bool enableLrFallback) { enableLrFallback_ = enableLrFallback; }
EnableFpFallback(bool enableFpFallback)69     inline void EnableFpFallback(bool enableFpFallback) { enableFpFallback_ = enableFpFallback; }
EnableFpCheckMapExec(bool enableFpCheckMapExec)70     inline void EnableFpCheckMapExec(bool enableFpCheckMapExec) { enableFpCheckMapExec_ = enableFpCheckMapExec; }
EnableFillFrames(bool enableFillFrames)71     inline void EnableFillFrames(bool enableFillFrames) { enableFillFrames_ = enableFillFrames; }
72 
SetRegs(const std::shared_ptr<DfxRegs> regs)73     inline void SetRegs(const std::shared_ptr<DfxRegs> regs) { regs_ = regs; }
GetRegs()74     inline const std::shared_ptr<DfxRegs>& GetRegs() { return regs_; }
SetMaps(const std::shared_ptr<DfxMaps> maps)75     inline void SetMaps(const std::shared_ptr<DfxMaps> maps) { maps_ = maps; }
GetMaps()76     inline const std::shared_ptr<DfxMaps>& GetMaps() { return maps_; }
77 
GetLastErrorCode()78     inline const uint16_t& GetLastErrorCode() { return lastErrorData_.GetCode(); }
GetLastErrorAddr()79     inline const uint64_t& GetLastErrorAddr() { return lastErrorData_.GetAddr(); }
80 
81     bool GetStackRange(uintptr_t& stackBottom, uintptr_t& stackTop);
82 
83     bool UnwindLocalWithContext(const ucontext_t& context, size_t maxFrameNum = 256, size_t skipFrameNum = 0);
84     bool UnwindLocal(bool withRegs = false, size_t maxFrameNum = 256, size_t skipFrameNum = 0);
85     bool UnwindRemote(pid_t tid = 0, bool withRegs = false, size_t maxFrameNum = 256, size_t skipFrameNum = 0);
86     bool Unwind(void *ctx, size_t maxFrameNum = 256, size_t skipFrameNum = 0);
87     bool UnwindByFp(void *ctx, size_t maxFrameNum = 256, size_t skipFrameNum = 0);
88     bool Step(uintptr_t& pc, uintptr_t& sp, void *ctx);
89     bool FpStep(uintptr_t& fp, uintptr_t& pc, void *ctx);
90 
GetPcs()91     inline const std::vector<uintptr_t>& GetPcs() { return pcs_; }
92     void AddFrame(DfxFrame& frame);
93     void FillFrames(std::vector<DfxFrame>& frames);
94     std::vector<DfxFrame>& GetFrames();
95     static bool GetSymbolByPc(uintptr_t pc, std::shared_ptr<DfxMaps> maps,
96         std::string& funcName, uint64_t& funcOffset);
97     static void GetFramesByPcs(std::vector<DfxFrame>& frames, std::vector<uintptr_t> pcs,
98         std::shared_ptr<DfxMaps> maps);
99     static void FillFrame(DfxFrame& frame);
100     static std::string GetFramesStr(const std::vector<DfxFrame>& frames);
101 
102 private:
103     void Init();
104     void Clear();
105     void Destroy();
106     void DoPcAdjust(uintptr_t& pc);
107     bool GetMapByPc(uintptr_t pc, void *ctx, std::shared_ptr<DfxMap>& map);
108     void AddFrame(uintptr_t pc, uintptr_t sp, std::shared_ptr<DfxMap> map, size_t& index);
109     bool Apply(std::shared_ptr<DfxRegs> regs, std::shared_ptr<RegLocState> rs);
110     void SetFrames(std::vector<DfxFrame>& frames);
111 #if defined(ENABLE_MIXSTACK)
112     bool StepArkJsFrame(size_t& curIdx);
113 #endif
114     static uintptr_t StripPac(uintptr_t inAddr, uintptr_t pacMask);
SetLocalStackCheck(void * ctx,bool check)115     inline void SetLocalStackCheck(void* ctx, bool check)
116     {
117         if (pid_ == UNWIND_TYPE_LOCAL) {
118             UnwindContext* uctx = reinterpret_cast<UnwindContext *>(ctx);
119             uctx->stackCheck = check;
120         }
121     }
122 
123 private:
124 #if defined(__aarch64__)
125     MAYBE_UNUSED const uintptr_t pacMaskDefault_ = static_cast<uintptr_t>(0xFFFFFF8000000000);
126 #endif
127     bool enableCache_ = true;
128     bool enableFillFrames_ = true;
129     bool enableLrFallback_ = true;
130     bool enableFpFallback_ = true;
131     bool enableFpCheckMapExec_ = false;
132     bool isFpStep_ = false;
133 
134     int32_t pid_ = 0;
135     uintptr_t pacMask_ = 0;
136     std::shared_ptr<DfxAccessors> acc_ = nullptr;
137     std::shared_ptr<DfxMemory> memory_ = nullptr;
138     std::unordered_map<uintptr_t, std::shared_ptr<RegLocState>> rsCache_ {};
139     std::shared_ptr<DfxRegs> regs_ = nullptr;
140     std::shared_ptr<DfxMaps> maps_ = nullptr;
141     std::vector<uintptr_t> pcs_ {};
142     std::vector<DfxFrame> frames_ {};
143     UnwindErrorData lastErrorData_ {};
144 #if defined(__arm__)
145     std::shared_ptr<ArmExidx> armExidx_ = nullptr;
146 #endif
147     std::shared_ptr<DwarfSection> dwarfSection_ = nullptr;
148 };
149 } // namespace HiviewDFX
150 } // namespace OHOS
151 #endif
152