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