• 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 "base/memory/ptr_util.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/metrics/metrics_hashes.h"
15 #include "base/notreached.h"
16 #include "base/profiler/module_cache.h"
17 #include "base/profiler/native_unwinder_android_map_delegate.h"
18 #include "base/profiler/native_unwinder_android_memory_regions_map_impl.h"
19 #include "base/profiler/profile_builder.h"
20 #include "build/build_config.h"
21 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Elf.h"
22 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Maps.h"
23 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Memory.h"
24 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Regs.h"
25 
26 #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
27 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/MachineArm.h"
28 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/RegsArm.h"
29 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
30 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/MachineArm64.h"
31 #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/RegsArm64.h"
32 #endif  // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
33 
34 namespace base {
35 namespace {
36 
37 class NonElfModule : public ModuleCache::Module {
38  public:
NonElfModule(unwindstack::MapInfo * map_info)39   explicit NonElfModule(unwindstack::MapInfo* map_info)
40       : start_(map_info->start()),
41         size_(map_info->end() - start_),
42         map_info_name_(map_info->name()) {}
43   ~NonElfModule() override = default;
44 
GetBaseAddress() const45   uintptr_t GetBaseAddress() const override { return start_; }
46 
GetId() const47   std::string GetId() const override { return ""; }
48 
GetDebugBasename() const49   FilePath GetDebugBasename() const override {
50     return FilePath(map_info_name_);
51   }
52 
53   // Gets the size of the module.
GetSize() const54   size_t GetSize() const override { return size_; }
55 
56   // True if this is a native module.
IsNative() const57   bool IsNative() const override { return true; }
58 
59  private:
60   const uintptr_t start_;
61   const size_t size_;
62   const std::string map_info_name_;
63 };
64 
CreateFromRegisterContext(RegisterContext * thread_context)65 std::unique_ptr<unwindstack::Regs> CreateFromRegisterContext(
66     RegisterContext* thread_context) {
67 #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
68   return WrapUnique<unwindstack::Regs>(unwindstack::RegsArm::Read(
69       reinterpret_cast<void*>(&thread_context->arm_r0)));
70 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
71   return WrapUnique<unwindstack::Regs>(unwindstack::RegsArm64::Read(
72       reinterpret_cast<void*>(&thread_context->regs[0])));
73 #else   // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
74   NOTREACHED();
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 }  // namespace
92 
UnwindStackMemoryAndroid(uintptr_t stack_ptr,uintptr_t stack_top)93 UnwindStackMemoryAndroid::UnwindStackMemoryAndroid(uintptr_t stack_ptr,
94                                                    uintptr_t stack_top)
95     : stack_ptr_(stack_ptr), stack_top_(stack_top) {
96   DCHECK_LE(stack_ptr_, stack_top_);
97 }
98 
99 UnwindStackMemoryAndroid::~UnwindStackMemoryAndroid() = default;
100 
Read(uint64_t addr,void * dst,size_t size)101 size_t UnwindStackMemoryAndroid::Read(uint64_t addr, void* dst, size_t size) {
102   if (addr < stack_ptr_)
103     return 0;
104   if (size >= stack_top_ || addr > stack_top_ - size)
105     return 0;
106   memcpy(dst, reinterpret_cast<void*>(addr), size);
107   return size;
108 }
109 
110 // static
111 std::unique_ptr<NativeUnwinderAndroidMemoryRegionsMap>
CreateMemoryRegionsMap(bool use_updatable_maps)112 NativeUnwinderAndroid::CreateMemoryRegionsMap(bool use_updatable_maps) {
113   std::unique_ptr<unwindstack::Maps> maps;
114   if (use_updatable_maps) {
115     maps = std::make_unique<unwindstack::LocalUpdatableMaps>();
116   } else {
117     maps = std::make_unique<unwindstack::LocalMaps>();
118   }
119   const bool success = maps->Parse();
120   DCHECK(success);
121 
122   return std::make_unique<NativeUnwinderAndroidMemoryRegionsMapImpl>(
123       std::move(maps), unwindstack::Memory::CreateLocalProcessMemory());
124 }
125 
NativeUnwinderAndroid(uintptr_t exclude_module_with_base_address,NativeUnwinderAndroidMapDelegate * map_delegate)126 NativeUnwinderAndroid::NativeUnwinderAndroid(
127     uintptr_t exclude_module_with_base_address,
128     NativeUnwinderAndroidMapDelegate* map_delegate)
129     : exclude_module_with_base_address_(exclude_module_with_base_address),
130       map_delegate_(map_delegate),
131       memory_regions_map_(
132           static_cast<NativeUnwinderAndroidMemoryRegionsMapImpl*>(
133               map_delegate->GetMapReference())) {
134   DCHECK(map_delegate_);
135   DCHECK(memory_regions_map_);
136 }
137 
~NativeUnwinderAndroid()138 NativeUnwinderAndroid::~NativeUnwinderAndroid() {
139   if (module_cache())
140     module_cache()->UnregisterAuxiliaryModuleProvider(this);
141 
142   map_delegate_->ReleaseMapReference();
143 }
144 
InitializeModules()145 void NativeUnwinderAndroid::InitializeModules() {
146   module_cache()->RegisterAuxiliaryModuleProvider(this);
147 }
148 
CanUnwindFrom(const Frame & current_frame) const149 bool NativeUnwinderAndroid::CanUnwindFrom(const Frame& current_frame) const {
150   return current_frame.module && current_frame.module->IsNative() &&
151          current_frame.module->GetBaseAddress() !=
152              exclude_module_with_base_address_;
153 }
154 
TryUnwind(UnwinderStateCapture * capture_state,RegisterContext * thread_context,uintptr_t stack_top,std::vector<Frame> * stack)155 UnwindResult NativeUnwinderAndroid::TryUnwind(
156     UnwinderStateCapture* capture_state,
157     RegisterContext* thread_context,
158     uintptr_t stack_top,
159     std::vector<Frame>* stack) {
160   auto regs = CreateFromRegisterContext(thread_context);
161   DCHECK(regs);
162   unwindstack::ArchEnum arch = regs->Arch();
163 
164   do {
165     uint64_t cur_pc = regs->pc();
166     uint64_t cur_sp = regs->sp();
167     unwindstack::MapInfo* map_info =
168         memory_regions_map_->maps()->Find(cur_pc).get();
169     if (map_info == nullptr ||
170         map_info->flags() & unwindstack::MAPS_FLAGS_DEVICE_MAP) {
171       break;
172     }
173 
174     unwindstack::Elf* elf =
175         map_info->GetElf(memory_regions_map_->memory(), arch);
176     if (!elf->valid())
177       break;
178 
179     UnwindStackMemoryAndroid stack_memory(cur_sp, stack_top);
180     uintptr_t rel_pc = elf->GetRelPc(cur_pc, map_info);
181     bool is_signal_frame = false;
182     bool finished = false;
183     // map_info->GetElf() may return a valid elf whose memory() is nullptr.
184     // In the case, elf->StepIfSignalHandler() and elf->Step() are not
185     // available, because the method depends on elf->memory().
186     // (Regarding Step(), EvalRegister() needs memory.)
187     bool stepped =
188         elf->memory() &&
189         (elf->StepIfSignalHandler(rel_pc, regs.get(), &stack_memory) ||
190          elf->Step(rel_pc, regs.get(), &stack_memory, &finished,
191                    &is_signal_frame));
192     if (stepped && finished)
193       return UnwindResult::kCompleted;
194 
195     if (!stepped) {
196       // Stepping failed. Try unwinding using return address.
197       if (stack->size() == 1) {
198         if (!regs->SetPcFromReturnAddress(&stack_memory))
199           return UnwindResult::kAborted;
200       } else {
201         break;
202       }
203     }
204 
205     // If the pc and sp didn't change, then consider everything stopped.
206     if (cur_pc == regs->pc() && cur_sp == regs->sp())
207       return UnwindResult::kAborted;
208 
209     // Exclusive range of expected stack pointer values after the unwind.
210     struct {
211       uintptr_t start;
212       uintptr_t end;
213     } expected_stack_pointer_range = {static_cast<uintptr_t>(cur_sp),
214                                       stack_top};
215     if (regs->sp() < expected_stack_pointer_range.start ||
216         regs->sp() >= expected_stack_pointer_range.end) {
217       return UnwindResult::kAborted;
218     }
219 
220     if (regs->dex_pc() != 0) {
221       // Add a frame to represent the dex file.
222       EmitDexFrame(regs->dex_pc(), arch, stack);
223 
224       // Clear the dex pc so that we don't repeat this frame later.
225       regs->set_dex_pc(0);
226     }
227 
228     // Add the frame to |stack|. Must use GetModuleForAddress rather than
229     // GetExistingModuleForAddress because the unwound-to address may be in a
230     // module associated with a different unwinder.
231     const ModuleCache::Module* module =
232         module_cache()->GetModuleForAddress(regs->pc());
233     stack->emplace_back(regs->pc(), module);
234   } while (CanUnwindFrom(stack->back()));
235 
236   // Restore registers necessary for further unwinding in |thread_context|.
237   CopyToRegisterContext(regs.get(), thread_context);
238   return UnwindResult::kUnrecognizedFrame;
239 }
240 
241 std::unique_ptr<const ModuleCache::Module>
TryCreateModuleForAddress(uintptr_t address)242 NativeUnwinderAndroid::TryCreateModuleForAddress(uintptr_t address) {
243   unwindstack::MapInfo* map_info =
244       memory_regions_map_->maps()->Find(address).get();
245   if (map_info == nullptr || !(map_info->flags() & PROT_EXEC) ||
246       map_info->flags() & unwindstack::MAPS_FLAGS_DEVICE_MAP) {
247     return nullptr;
248   }
249   return std::make_unique<NonElfModule>(map_info);
250 }
251 
GetOrCreateDexFiles(unwindstack::ArchEnum arch)252 unwindstack::DexFiles* NativeUnwinderAndroid::GetOrCreateDexFiles(
253     unwindstack::ArchEnum arch) {
254   if (!dex_files_) {
255     dex_files_ = unwindstack::CreateDexFiles(
256         arch, memory_regions_map_->memory(), search_libs_);
257   }
258   return dex_files_.get();
259 }
260 
EmitDexFrame(uintptr_t dex_pc,unwindstack::ArchEnum arch,std::vector<Frame> * stack)261 void NativeUnwinderAndroid::EmitDexFrame(uintptr_t dex_pc,
262                                          unwindstack::ArchEnum arch,
263                                          std::vector<Frame>* stack) {
264   const ModuleCache::Module* module =
265       module_cache()->GetExistingModuleForAddress(dex_pc);
266   if (!module) {
267     // The region containing |dex_pc| may not be in module_cache() since it's
268     // usually not executable (.dex file). Since non-executable regions
269     // are used much less commonly, it's lazily added here instead of from
270     // AddInitialModulesFromMaps().
271     unwindstack::MapInfo* map_info =
272         memory_regions_map_->maps()->Find(dex_pc).get();
273     if (map_info) {
274       auto new_module = std::make_unique<NonElfModule>(map_info);
275       module = new_module.get();
276       module_cache()->AddCustomNativeModule(std::move(new_module));
277     }
278   }
279 
280     stack->emplace_back(dex_pc, module);
281 }
282 
283 }  // namespace base
284