• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/profiler/native_unwinder_android.h"
6 
7 #include <sys/mman.h>
8 
9 #include <string>
10 #include <vector>
11 
12 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Elf.h"
13 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Maps.h"
14 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Memory.h"
15 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Regs.h"
16 
17 #include "base/memory/ptr_util.h"
18 #include "base/notreached.h"
19 #include "base/profiler/module_cache.h"
20 #include "base/profiler/native_unwinder_android_map_delegate.h"
21 #include "base/profiler/native_unwinder_android_memory_regions_map.h"
22 #include "base/profiler/profile_builder.h"
23 #include "build/build_config.h"
24 
25 #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
26 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/MachineArm.h"
27 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/RegsArm.h"
28 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
29 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/MachineArm64.h"
30 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/RegsArm64.h"
31 #endif  // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
32 
33 namespace base {
34 namespace {
35 
36 class NonElfModule : public ModuleCache::Module {
37  public:
NonElfModule(unwindstack::MapInfo * map_info)38   explicit NonElfModule(unwindstack::MapInfo* map_info)
39       : start_(map_info->start()),
40         size_(map_info->end() - start_),
41         map_info_name_(map_info->name()) {}
42   ~NonElfModule() override = default;
43 
GetBaseAddress() const44   uintptr_t GetBaseAddress() const override { return start_; }
45 
GetId() const46   std::string GetId() const override { return std::string(); }
47 
GetDebugBasename() const48   FilePath GetDebugBasename() const override {
49     return FilePath(map_info_name_);
50   }
51 
52   // Gets the size of the module.
GetSize() const53   size_t GetSize() const override { return size_; }
54 
55   // True if this is a native module.
IsNative() const56   bool IsNative() const override { return true; }
57 
58  private:
59   const uintptr_t start_;
60   const size_t size_;
61   const std::string map_info_name_;
62 };
63 
CreateFromRegisterContext(RegisterContext * thread_context)64 std::unique_ptr<unwindstack::Regs> CreateFromRegisterContext(
65     RegisterContext* thread_context) {
66 #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
67   return WrapUnique<unwindstack::Regs>(unwindstack::RegsArm::Read(
68       reinterpret_cast<void*>(&thread_context->arm_r0)));
69 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
70   return WrapUnique<unwindstack::Regs>(unwindstack::RegsArm64::Read(
71       reinterpret_cast<void*>(&thread_context->regs[0])));
72 #else   // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
73   NOTREACHED();
74   return nullptr;
75 #endif  // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
76 }
77 
CopyToRegisterContext(unwindstack::Regs * regs,RegisterContext * thread_context)78 void CopyToRegisterContext(unwindstack::Regs* regs,
79                            RegisterContext* thread_context) {
80 #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
81   memcpy(reinterpret_cast<void*>(&thread_context->arm_r0), regs->RawData(),
82          unwindstack::ARM_REG_LAST * sizeof(uintptr_t));
83 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
84   memcpy(reinterpret_cast<void*>(&thread_context->regs[0]), regs->RawData(),
85          unwindstack::ARM64_REG_LAST * sizeof(uintptr_t));
86 #else   // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
87   NOTREACHED();
88 #endif  // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
89 }
90 
91 // The wrapper class exists to avoid the reference of concrete libunwindstack
92 // types in chrome code. Only code in the stack unwinder DFM has the access to
93 // third_party/libunwindstack/src/libunwindstack. Files within the stack
94 // unwinder DFM can be found by searching `native_unwinder_android` source set
95 // in `base/BUILD.gn`.
96 class MemoryRegionsMap : public base::NativeUnwinderAndroidMemoryRegionsMap {
97  public:
MemoryRegionsMap(std::unique_ptr<unwindstack::Maps> maps,std::unique_ptr<unwindstack::Memory> memory)98   MemoryRegionsMap(std::unique_ptr<unwindstack::Maps> maps,
99                    std::unique_ptr<unwindstack::Memory> memory)
100       : maps_(std::move(maps)), memory_(std::move(memory)) {}
101 
GetMaps()102   unwindstack::Maps* GetMaps() override { return maps_.get(); }
GetMemory()103   unwindstack::Memory* GetMemory() override { return memory_.get(); }
TakeMemory()104   std::unique_ptr<unwindstack::Memory> TakeMemory() override {
105     return std::move(memory_);
106   }
107 
108  private:
109   std::unique_ptr<unwindstack::Maps> maps_;
110   std::unique_ptr<unwindstack::Memory> memory_;
111 };
112 
113 }  // namespace
114 
UnwindStackMemoryAndroid(uintptr_t stack_ptr,uintptr_t stack_top)115 UnwindStackMemoryAndroid::UnwindStackMemoryAndroid(uintptr_t stack_ptr,
116                                                    uintptr_t stack_top)
117     : stack_ptr_(stack_ptr), stack_top_(stack_top) {
118   DCHECK_LE(stack_ptr_, stack_top_);
119 }
120 
121 UnwindStackMemoryAndroid::~UnwindStackMemoryAndroid() = default;
122 
Read(uint64_t addr,void * dst,size_t size)123 size_t UnwindStackMemoryAndroid::Read(uint64_t addr, void* dst, size_t size) {
124   if (addr < stack_ptr_)
125     return 0;
126   if (size >= stack_top_ || addr > stack_top_ - size)
127     return 0;
128   memcpy(dst, reinterpret_cast<void*>(addr), size);
129   return size;
130 }
131 
132 // static
133 std::unique_ptr<NativeUnwinderAndroidMemoryRegionsMap>
CreateMemoryRegionsMap(bool use_updatable_maps)134 NativeUnwinderAndroid::CreateMemoryRegionsMap(bool use_updatable_maps) {
135   std::unique_ptr<unwindstack::Maps> maps;
136   if (use_updatable_maps) {
137     maps = std::make_unique<unwindstack::LocalUpdatableMaps>();
138   } else {
139     maps = std::make_unique<unwindstack::LocalMaps>();
140   }
141   const bool success = maps->Parse();
142   DCHECK(success);
143 
144   return std::make_unique<MemoryRegionsMap>(
145       std::move(maps), unwindstack::Memory::CreateLocalProcessMemory());
146 }
147 
NativeUnwinderAndroid(uintptr_t exclude_module_with_base_address,NativeUnwinderAndroidMapDelegate * map_delegate)148 NativeUnwinderAndroid::NativeUnwinderAndroid(
149     uintptr_t exclude_module_with_base_address,
150     NativeUnwinderAndroidMapDelegate* map_delegate)
151     : exclude_module_with_base_address_(exclude_module_with_base_address),
152       map_delegate_(map_delegate),
153       memory_regions_map_(map_delegate->GetMapReference()) {
154   DCHECK(map_delegate_);
155   DCHECK(memory_regions_map_);
156 }
157 
~NativeUnwinderAndroid()158 NativeUnwinderAndroid::~NativeUnwinderAndroid() {
159   if (module_cache())
160     module_cache()->UnregisterAuxiliaryModuleProvider(this);
161 
162   map_delegate_->ReleaseMapReference();
163 }
164 
InitializeModules()165 void NativeUnwinderAndroid::InitializeModules() {
166   module_cache()->RegisterAuxiliaryModuleProvider(this);
167 }
168 
CanUnwindFrom(const Frame & current_frame) const169 bool NativeUnwinderAndroid::CanUnwindFrom(const Frame& current_frame) const {
170   return current_frame.module && current_frame.module->IsNative() &&
171          current_frame.module->GetBaseAddress() !=
172              exclude_module_with_base_address_;
173 }
174 
TryUnwind(RegisterContext * thread_context,uintptr_t stack_top,std::vector<Frame> * stack)175 UnwindResult NativeUnwinderAndroid::TryUnwind(RegisterContext* thread_context,
176                                               uintptr_t stack_top,
177                                               std::vector<Frame>* stack) {
178   auto regs = CreateFromRegisterContext(thread_context);
179   DCHECK(regs);
180   unwindstack::ArchEnum arch = regs->Arch();
181 
182   do {
183     uint64_t cur_pc = regs->pc();
184     uint64_t cur_sp = regs->sp();
185     unwindstack::MapInfo* map_info =
186         memory_regions_map_->GetMaps()->Find(cur_pc).get();
187     if (map_info == nullptr ||
188         map_info->flags() & unwindstack::MAPS_FLAGS_DEVICE_MAP) {
189       break;
190     }
191 
192     unwindstack::Elf* elf = map_info->GetElf(
193         {memory_regions_map_->GetMemory(), [](unwindstack::Memory*) {}}, arch);
194     if (!elf->valid())
195       break;
196 
197     UnwindStackMemoryAndroid stack_memory(cur_sp, stack_top);
198     uintptr_t rel_pc = elf->GetRelPc(cur_pc, map_info);
199     bool is_signal_frame = false;
200     bool finished = false;
201     bool stepped =
202         elf->StepIfSignalHandler(rel_pc, regs.get(), &stack_memory) ||
203         elf->Step(rel_pc, regs.get(), &stack_memory, &finished,
204                   &is_signal_frame);
205     if (stepped && finished)
206       return UnwindResult::kCompleted;
207 
208     if (!stepped) {
209       // Stepping failed. Try unwinding using return address.
210       if (stack->size() == 1) {
211         if (!regs->SetPcFromReturnAddress(&stack_memory))
212           return UnwindResult::kAborted;
213       } else {
214         break;
215       }
216     }
217 
218     // If the pc and sp didn't change, then consider everything stopped.
219     if (cur_pc == regs->pc() && cur_sp == regs->sp())
220       return UnwindResult::kAborted;
221 
222     // Exclusive range of expected stack pointer values after the unwind.
223     struct {
224       uintptr_t start;
225       uintptr_t end;
226     } expected_stack_pointer_range = {static_cast<uintptr_t>(cur_sp),
227                                       stack_top};
228     if (regs->sp() < expected_stack_pointer_range.start ||
229         regs->sp() >= expected_stack_pointer_range.end) {
230       return UnwindResult::kAborted;
231     }
232 
233     if (regs->dex_pc() != 0) {
234       // Add a frame to represent the dex file.
235       EmitDexFrame(regs->dex_pc(), stack);
236 
237       // Clear the dex pc so that we don't repeat this frame later.
238       regs->set_dex_pc(0);
239     }
240 
241     // Add the frame to |stack|. Must use GetModuleForAddress rather than
242     // GetExistingModuleForAddress because the unwound-to address may be in a
243     // module associated with a different unwinder.
244     const ModuleCache::Module* module =
245         module_cache()->GetModuleForAddress(regs->pc());
246     stack->emplace_back(regs->pc(), module);
247   } while (CanUnwindFrom(stack->back()));
248 
249   // Restore registers necessary for further unwinding in |thread_context|.
250   CopyToRegisterContext(regs.get(), thread_context);
251   return UnwindResult::kUnrecognizedFrame;
252 }
253 
254 std::unique_ptr<const ModuleCache::Module>
TryCreateModuleForAddress(uintptr_t address)255 NativeUnwinderAndroid::TryCreateModuleForAddress(uintptr_t address) {
256   unwindstack::MapInfo* map_info =
257       memory_regions_map_->GetMaps()->Find(address).get();
258   if (map_info == nullptr || !(map_info->flags() & PROT_EXEC) ||
259       map_info->flags() & unwindstack::MAPS_FLAGS_DEVICE_MAP) {
260     return nullptr;
261   }
262   return std::make_unique<NonElfModule>(map_info);
263 }
264 
EmitDexFrame(uintptr_t dex_pc,std::vector<Frame> * stack) const265 void NativeUnwinderAndroid::EmitDexFrame(uintptr_t dex_pc,
266                                          std::vector<Frame>* stack) const {
267   const ModuleCache::Module* module =
268       module_cache()->GetExistingModuleForAddress(dex_pc);
269   if (!module) {
270     // The region containing |dex_pc| may not be in module_cache() since it's
271     // usually not executable (.dex file). Since non-executable regions
272     // are used much less commonly, it's lazily added here instead of from
273     // AddInitialModulesFromMaps().
274     unwindstack::MapInfo* map_info =
275         memory_regions_map_->GetMaps()->Find(dex_pc).get();
276     if (map_info) {
277       auto new_module = std::make_unique<NonElfModule>(map_info);
278       module = new_module.get();
279       module_cache()->AddCustomNativeModule(std::move(new_module));
280     }
281   }
282   stack->emplace_back(dex_pc, module);
283 }
284 
285 }  // namespace base
286