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/DexFiles.h>
28 #include <unwindstack/Error.h>
29 #include <unwindstack/JitDebug.h>
30 #include <unwindstack/Maps.h>
31 #include <unwindstack/Memory.h>
32 #include <unwindstack/Regs.h>
33 
34 namespace unwindstack {
35 
36 // Forward declarations.
37 class Elf;
38 enum ArchEnum : uint8_t;
39 
40 struct FrameData {
41   size_t num;
42 
43   uint64_t rel_pc;
44   uint64_t pc;
45   uint64_t sp;
46 
47   std::string function_name;
48   uint64_t function_offset = 0;
49 
50   std::string map_name;
51   // The offset from the first map representing the frame. When there are
52   // two maps (read-only and read-execute) this will be the offset from
53   // the read-only map. When there is only one map, this will be the
54   // same as the actual offset of the map and match map_exact_offset.
55   uint64_t map_elf_start_offset = 0;
56   // The actual offset from the map where the pc lies.
57   uint64_t map_exact_offset = 0;
58   uint64_t map_start = 0;
59   uint64_t map_end = 0;
60   uint64_t map_load_bias = 0;
61   int map_flags = 0;
62 };
63 
64 class Unwinder {
65  public:
Unwinder(size_t max_frames,Maps * maps,Regs * regs,std::shared_ptr<Memory> process_memory)66   Unwinder(size_t max_frames, Maps* maps, Regs* regs, std::shared_ptr<Memory> process_memory)
67       : max_frames_(max_frames), maps_(maps), regs_(regs), process_memory_(process_memory) {
68     frames_.reserve(max_frames);
69   }
Unwinder(size_t max_frames,Maps * maps,std::shared_ptr<Memory> process_memory)70   Unwinder(size_t max_frames, Maps* maps, std::shared_ptr<Memory> process_memory)
71       : max_frames_(max_frames), maps_(maps), process_memory_(process_memory) {
72     frames_.reserve(max_frames);
73   }
74 
75   virtual ~Unwinder() = default;
76 
77   void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
78               const std::vector<std::string>* map_suffixes_to_ignore = nullptr);
79 
NumFrames()80   size_t NumFrames() const { return frames_.size(); }
81 
frames()82   const std::vector<FrameData>& frames() { return frames_; }
83 
ConsumeFrames()84   std::vector<FrameData> ConsumeFrames() {
85     std::vector<FrameData> frames = std::move(frames_);
86     frames_.clear();
87     return frames;
88   }
89 
90   std::string FormatFrame(size_t frame_num) const;
91   std::string FormatFrame(const FrameData& frame) const;
92 
93   void SetJitDebug(JitDebug* jit_debug, ArchEnum arch);
94 
SetRegs(Regs * regs)95   void SetRegs(Regs* regs) { regs_ = regs; }
GetMaps()96   Maps* GetMaps() { return maps_; }
GetProcessMemory()97   std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; }
98 
99   // Disabling the resolving of names results in the function name being
100   // set to an empty string and the function offset being set to zero.
SetResolveNames(bool resolve)101   void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
102 
103   // Enable/disable soname printing the soname for a map name if the elf is
104   // embedded in a file. This is enabled by default.
105   // NOTE: This does nothing unless resolving names is enabled.
SetEmbeddedSoname(bool embedded_soname)106   void SetEmbeddedSoname(bool embedded_soname) { embedded_soname_ = embedded_soname; }
107 
SetDisplayBuildID(bool display_build_id)108   void SetDisplayBuildID(bool display_build_id) { display_build_id_ = display_build_id; }
109 
110 #if !defined(NO_LIBDEXFILE_SUPPORT)
111   void SetDexFiles(DexFiles* dex_files, ArchEnum arch);
112 #endif
113 
elf_from_memory_not_file()114   bool elf_from_memory_not_file() { return elf_from_memory_not_file_; }
115 
LastErrorCode()116   ErrorCode LastErrorCode() { return last_error_.code; }
LastErrorAddress()117   uint64_t LastErrorAddress() { return last_error_.address; }
118 
119  protected:
Unwinder(size_t max_frames)120   Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); }
121 
122   void FillInDexFrame();
123   FrameData* FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t pc_adjustment);
124 
125   size_t max_frames_;
126   Maps* maps_;
127   Regs* regs_;
128   std::vector<FrameData> frames_;
129   std::shared_ptr<Memory> process_memory_;
130   JitDebug* jit_debug_ = nullptr;
131 #if !defined(NO_LIBDEXFILE_SUPPORT)
132   DexFiles* dex_files_ = nullptr;
133 #endif
134   bool resolve_names_ = true;
135   bool embedded_soname_ = true;
136   bool display_build_id_ = false;
137   // True if at least one elf file is coming from memory and not the related
138   // file. This is only true if there is an actual file backing up the elf.
139   bool elf_from_memory_not_file_ = false;
140   ErrorData last_error_;
141 };
142 
143 class UnwinderFromPid : public Unwinder {
144  public:
UnwinderFromPid(size_t max_frames,pid_t pid)145   UnwinderFromPid(size_t max_frames, pid_t pid) : Unwinder(max_frames), pid_(pid) {}
146   virtual ~UnwinderFromPid() = default;
147 
148   bool Init(ArchEnum arch);
149 
150  private:
151   pid_t pid_;
152   std::unique_ptr<Maps> maps_ptr_;
153   std::unique_ptr<JitDebug> jit_debug_ptr_;
154 #if !defined(NO_LIBDEXFILE_SUPPORT)
155   std::unique_ptr<DexFiles> dex_files_ptr_;
156 #endif
157 };
158 
159 }  // namespace unwindstack
160 
161 #endif  // _LIBUNWINDSTACK_UNWINDER_H
162