1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _LIBUNWINDSTACK_UNWINDER_H 18 #define _LIBUNWINDSTACK_UNWINDER_H 19 20 #include <stdint.h> 21 #include <sys/types.h> 22 23 #include <memory> 24 #include <string> 25 #include <vector> 26 27 #include <unwindstack/Arch.h> 28 #include <unwindstack/DexFiles.h> 29 #include <unwindstack/Error.h> 30 #include <unwindstack/JitDebug.h> 31 #include <unwindstack/Maps.h> 32 #include <unwindstack/Memory.h> 33 #include <unwindstack/Regs.h> 34 #include <unwindstack/SharedString.h> 35 36 namespace unwindstack { 37 38 // Forward declarations. 39 class Elf; 40 class ThreadEntry; 41 42 struct FrameData { 43 size_t num; 44 45 uint64_t rel_pc; 46 uint64_t pc; 47 uint64_t sp; 48 49 SharedString function_name; 50 uint64_t function_offset = 0; 51 52 SharedString map_name; 53 // The offset from the first map representing the frame. When there are 54 // two maps (read-only and read-execute) this will be the offset from 55 // the read-only map. When there is only one map, this will be the 56 // same as the actual offset of the map and match map_exact_offset. 57 uint64_t map_elf_start_offset = 0; 58 // The actual offset from the map where the pc lies. 59 uint64_t map_exact_offset = 0; 60 uint64_t map_start = 0; 61 uint64_t map_end = 0; 62 uint64_t map_load_bias = 0; 63 int map_flags = 0; 64 }; 65 66 class Unwinder { 67 public: Unwinder(size_t max_frames,Maps * maps,Regs * regs,std::shared_ptr<Memory> process_memory)68 Unwinder(size_t max_frames, Maps* maps, Regs* regs, std::shared_ptr<Memory> process_memory) 69 : max_frames_(max_frames), 70 maps_(maps), 71 regs_(regs), 72 process_memory_(process_memory), 73 arch_(regs->Arch()) {} Unwinder(size_t max_frames,Maps * maps,std::shared_ptr<Memory> process_memory)74 Unwinder(size_t max_frames, Maps* maps, std::shared_ptr<Memory> process_memory) 75 : max_frames_(max_frames), maps_(maps), process_memory_(process_memory) {} 76 77 virtual ~Unwinder() = default; 78 79 virtual void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr, 80 const std::vector<std::string>* map_suffixes_to_ignore = nullptr); 81 NumFrames()82 size_t NumFrames() const { return frames_.size(); } 83 84 // Returns frames after unwinding. 85 // Intentionally mutable (which can be used to swap in reserved memory before unwinding). frames()86 std::vector<FrameData>& frames() { return frames_; } 87 ConsumeFrames()88 std::vector<FrameData> ConsumeFrames() { 89 std::vector<FrameData> frames = std::move(frames_); 90 frames_.clear(); 91 return frames; 92 } 93 94 std::string FormatFrame(size_t frame_num) const; 95 std::string FormatFrame(const FrameData& frame) const; 96 SetArch(ArchEnum arch)97 void SetArch(ArchEnum arch) { arch_ = arch; }; 98 99 void SetJitDebug(JitDebug* jit_debug); 100 SetRegs(Regs * regs)101 void SetRegs(Regs* regs) { 102 regs_ = regs; 103 arch_ = regs_ != nullptr ? regs->Arch() : ARCH_UNKNOWN; 104 } GetMaps()105 Maps* GetMaps() { return maps_; } GetProcessMemory()106 std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; } 107 108 // Disabling the resolving of names results in the function name being 109 // set to an empty string and the function offset being set to zero. SetResolveNames(bool resolve)110 void SetResolveNames(bool resolve) { resolve_names_ = resolve; } 111 112 // Enable/disable soname printing the soname for a map name if the elf is 113 // embedded in a file. This is enabled by default. 114 // NOTE: This does nothing unless resolving names is enabled. SetEmbeddedSoname(bool embedded_soname)115 void SetEmbeddedSoname(bool embedded_soname) { embedded_soname_ = embedded_soname; } 116 SetDisplayBuildID(bool display_build_id)117 void SetDisplayBuildID(bool display_build_id) { display_build_id_ = display_build_id; } 118 119 void SetDexFiles(DexFiles* dex_files); 120 elf_from_memory_not_file()121 bool elf_from_memory_not_file() { return elf_from_memory_not_file_; } 122 LastErrorCode()123 ErrorCode LastErrorCode() { return last_error_.code; } LastErrorCodeString()124 const char* LastErrorCodeString() { return GetErrorCodeString(last_error_.code); } LastErrorAddress()125 uint64_t LastErrorAddress() { return last_error_.address; } warnings()126 uint64_t warnings() { return warnings_; } 127 128 // Builds a frame for symbolization using the maps from this unwinder. The 129 // constructed frame contains just enough information to be used to symbolize 130 // frames collected by frame-pointer unwinding that's done outside of 131 // libunwindstack. This is used by tombstoned to symbolize frame pointer-based 132 // stack traces that are collected by tools such as GWP-ASan and MTE. 133 static FrameData BuildFrameFromPcOnly(uint64_t pc, ArchEnum arch, Maps* maps, JitDebug* jit_debug, 134 std::shared_ptr<Memory> process_memory, bool resolve_names); 135 FrameData BuildFrameFromPcOnly(uint64_t pc); 136 137 protected: max_frames_(max_frames)138 Unwinder(size_t max_frames, Maps* maps = nullptr) : max_frames_(max_frames), maps_(maps) {} 139 Unwinder(size_t max_frames, ArchEnum arch, Maps* maps = nullptr) max_frames_(max_frames)140 : max_frames_(max_frames), maps_(maps), arch_(arch) {} 141 ClearErrors()142 void ClearErrors() { 143 warnings_ = WARNING_NONE; 144 last_error_.code = ERROR_NONE; 145 last_error_.address = 0; 146 } 147 148 void FillInDexFrame(); 149 FrameData* FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t pc_adjustment); 150 151 size_t max_frames_; 152 Maps* maps_; 153 Regs* regs_; 154 std::vector<FrameData> frames_; 155 std::shared_ptr<Memory> process_memory_; 156 JitDebug* jit_debug_ = nullptr; 157 DexFiles* dex_files_ = nullptr; 158 bool resolve_names_ = true; 159 bool embedded_soname_ = true; 160 bool display_build_id_ = false; 161 // True if at least one elf file is coming from memory and not the related 162 // file. This is only true if there is an actual file backing up the elf. 163 bool elf_from_memory_not_file_ = false; 164 ErrorData last_error_; 165 uint64_t warnings_; 166 ArchEnum arch_ = ARCH_UNKNOWN; 167 }; 168 169 class UnwinderFromPid : public Unwinder { 170 public: 171 UnwinderFromPid(size_t max_frames, pid_t pid, Maps* maps = nullptr) Unwinder(max_frames,maps)172 : Unwinder(max_frames, maps), pid_(pid) {} 173 UnwinderFromPid(size_t max_frames, pid_t pid, ArchEnum arch, Maps* maps = nullptr) Unwinder(max_frames,arch,maps)174 : Unwinder(max_frames, arch, maps), pid_(pid) {} 175 virtual ~UnwinderFromPid() = default; 176 SetProcessMemory(std::shared_ptr<Memory> & process_memory)177 void SetProcessMemory(std::shared_ptr<Memory>& process_memory) { 178 process_memory_ = process_memory; 179 } 180 181 bool Init(); 182 183 void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr, 184 const std::vector<std::string>* map_suffixes_to_ignore = nullptr) override; 185 186 protected: 187 pid_t pid_; 188 std::unique_ptr<Maps> maps_ptr_; 189 std::unique_ptr<JitDebug> jit_debug_ptr_; 190 std::unique_ptr<DexFiles> dex_files_ptr_; 191 bool initted_ = false; 192 }; 193 194 class ThreadUnwinder : public UnwinderFromPid { 195 public: 196 ThreadUnwinder(size_t max_frames, Maps* maps = nullptr); 197 ThreadUnwinder(size_t max_frames, const ThreadUnwinder* unwinder); 198 virtual ~ThreadUnwinder() = default; 199 200 void SetObjects(ThreadUnwinder* unwinder); 201 Unwind(const std::vector<std::string> *,const std::vector<std::string> *)202 void Unwind(const std::vector<std::string>*, const std::vector<std::string>*) override {} 203 204 void UnwindWithSignal(int signal, pid_t tid, 205 const std::vector<std::string>* initial_map_names_to_skip = nullptr, 206 const std::vector<std::string>* map_suffixes_to_ignore = nullptr); 207 208 protected: 209 ThreadEntry* SendSignalToThread(int signal, pid_t tid); 210 }; 211 212 } // namespace unwindstack 213 214 #endif // _LIBUNWINDSTACK_UNWINDER_H 215