• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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