xref: /aosp_15_r20/external/cronet/base/profiler/native_unwinder_android.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2019 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/profiler/native_unwinder_android.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <sys/mman.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <string>
10*6777b538SAndroid Build Coastguard Worker #include <vector>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/metrics/metrics_hashes.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/profiler/module_cache.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/profiler/native_unwinder_android_map_delegate.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/profiler/native_unwinder_android_memory_regions_map_impl.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/profiler/profile_builder.h"
20*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
21*6777b538SAndroid Build Coastguard Worker #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Elf.h"
22*6777b538SAndroid Build Coastguard Worker #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Maps.h"
23*6777b538SAndroid Build Coastguard Worker #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Memory.h"
24*6777b538SAndroid Build Coastguard Worker #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Regs.h"
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
27*6777b538SAndroid Build Coastguard Worker #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/MachineArm.h"
28*6777b538SAndroid Build Coastguard Worker #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/RegsArm.h"
29*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
30*6777b538SAndroid Build Coastguard Worker #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/MachineArm64.h"
31*6777b538SAndroid Build Coastguard Worker #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/RegsArm64.h"
32*6777b538SAndroid Build Coastguard Worker #endif  // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
33*6777b538SAndroid Build Coastguard Worker 
34*6777b538SAndroid Build Coastguard Worker namespace base {
35*6777b538SAndroid Build Coastguard Worker namespace {
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker class NonElfModule : public ModuleCache::Module {
38*6777b538SAndroid Build Coastguard Worker  public:
NonElfModule(unwindstack::MapInfo * map_info,bool is_java_name_hashing_enabled)39*6777b538SAndroid Build Coastguard Worker   explicit NonElfModule(unwindstack::MapInfo* map_info,
40*6777b538SAndroid Build Coastguard Worker                         bool is_java_name_hashing_enabled)
41*6777b538SAndroid Build Coastguard Worker       : start_(map_info->start()),
42*6777b538SAndroid Build Coastguard Worker         size_(map_info->end() - start_),
43*6777b538SAndroid Build Coastguard Worker         map_info_name_(map_info->name()),
44*6777b538SAndroid Build Coastguard Worker         is_java_name_hashing_enabled_(is_java_name_hashing_enabled) {}
45*6777b538SAndroid Build Coastguard Worker   ~NonElfModule() override = default;
46*6777b538SAndroid Build Coastguard Worker 
GetBaseAddress() const47*6777b538SAndroid Build Coastguard Worker   uintptr_t GetBaseAddress() const override { return start_; }
48*6777b538SAndroid Build Coastguard Worker 
GetId() const49*6777b538SAndroid Build Coastguard Worker   std::string GetId() const override {
50*6777b538SAndroid Build Coastguard Worker     // We provide a non-empty string only if Java name hashing is enabled, to
51*6777b538SAndroid Build Coastguard Worker     // allow us to easily filter out the results from outside the experiment.
52*6777b538SAndroid Build Coastguard Worker     if (is_java_name_hashing_enabled_) {
53*6777b538SAndroid Build Coastguard Worker       // Synthetic build id to use for DEX files that provide hashed function
54*6777b538SAndroid Build Coastguard Worker       // names rather than instruction pointers.
55*6777b538SAndroid Build Coastguard Worker       return "44444444BC18564712E780518FB3032B999";
56*6777b538SAndroid Build Coastguard Worker     } else {
57*6777b538SAndroid Build Coastguard Worker       return "";
58*6777b538SAndroid Build Coastguard Worker     }
59*6777b538SAndroid Build Coastguard Worker   }
60*6777b538SAndroid Build Coastguard Worker 
GetDebugBasename() const61*6777b538SAndroid Build Coastguard Worker   FilePath GetDebugBasename() const override {
62*6777b538SAndroid Build Coastguard Worker     return FilePath(map_info_name_);
63*6777b538SAndroid Build Coastguard Worker   }
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker   // Gets the size of the module.
GetSize() const66*6777b538SAndroid Build Coastguard Worker   size_t GetSize() const override { return size_; }
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker   // True if this is a native module.
IsNative() const69*6777b538SAndroid Build Coastguard Worker   bool IsNative() const override { return true; }
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker  private:
72*6777b538SAndroid Build Coastguard Worker   const uintptr_t start_;
73*6777b538SAndroid Build Coastguard Worker   const size_t size_;
74*6777b538SAndroid Build Coastguard Worker   const std::string map_info_name_;
75*6777b538SAndroid Build Coastguard Worker   const bool is_java_name_hashing_enabled_;
76*6777b538SAndroid Build Coastguard Worker };
77*6777b538SAndroid Build Coastguard Worker 
CreateFromRegisterContext(RegisterContext * thread_context)78*6777b538SAndroid Build Coastguard Worker std::unique_ptr<unwindstack::Regs> CreateFromRegisterContext(
79*6777b538SAndroid Build Coastguard Worker     RegisterContext* thread_context) {
80*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
81*6777b538SAndroid Build Coastguard Worker   return WrapUnique<unwindstack::Regs>(unwindstack::RegsArm::Read(
82*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<void*>(&thread_context->arm_r0)));
83*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
84*6777b538SAndroid Build Coastguard Worker   return WrapUnique<unwindstack::Regs>(unwindstack::RegsArm64::Read(
85*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<void*>(&thread_context->regs[0])));
86*6777b538SAndroid Build Coastguard Worker #else   // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
87*6777b538SAndroid Build Coastguard Worker   NOTREACHED();
88*6777b538SAndroid Build Coastguard Worker   return nullptr;
89*6777b538SAndroid Build Coastguard Worker #endif  // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
90*6777b538SAndroid Build Coastguard Worker }
91*6777b538SAndroid Build Coastguard Worker 
CopyToRegisterContext(unwindstack::Regs * regs,RegisterContext * thread_context)92*6777b538SAndroid Build Coastguard Worker void CopyToRegisterContext(unwindstack::Regs* regs,
93*6777b538SAndroid Build Coastguard Worker                            RegisterContext* thread_context) {
94*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
95*6777b538SAndroid Build Coastguard Worker   memcpy(reinterpret_cast<void*>(&thread_context->arm_r0), regs->RawData(),
96*6777b538SAndroid Build Coastguard Worker          unwindstack::ARM_REG_LAST * sizeof(uintptr_t));
97*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
98*6777b538SAndroid Build Coastguard Worker   memcpy(reinterpret_cast<void*>(&thread_context->regs[0]), regs->RawData(),
99*6777b538SAndroid Build Coastguard Worker          unwindstack::ARM64_REG_LAST * sizeof(uintptr_t));
100*6777b538SAndroid Build Coastguard Worker #else   // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
101*6777b538SAndroid Build Coastguard Worker   NOTREACHED();
102*6777b538SAndroid Build Coastguard Worker #endif  // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker }  // namespace
106*6777b538SAndroid Build Coastguard Worker 
UnwindStackMemoryAndroid(uintptr_t stack_ptr,uintptr_t stack_top)107*6777b538SAndroid Build Coastguard Worker UnwindStackMemoryAndroid::UnwindStackMemoryAndroid(uintptr_t stack_ptr,
108*6777b538SAndroid Build Coastguard Worker                                                    uintptr_t stack_top)
109*6777b538SAndroid Build Coastguard Worker     : stack_ptr_(stack_ptr), stack_top_(stack_top) {
110*6777b538SAndroid Build Coastguard Worker   DCHECK_LE(stack_ptr_, stack_top_);
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker UnwindStackMemoryAndroid::~UnwindStackMemoryAndroid() = default;
114*6777b538SAndroid Build Coastguard Worker 
Read(uint64_t addr,void * dst,size_t size)115*6777b538SAndroid Build Coastguard Worker size_t UnwindStackMemoryAndroid::Read(uint64_t addr, void* dst, size_t size) {
116*6777b538SAndroid Build Coastguard Worker   if (addr < stack_ptr_)
117*6777b538SAndroid Build Coastguard Worker     return 0;
118*6777b538SAndroid Build Coastguard Worker   if (size >= stack_top_ || addr > stack_top_ - size)
119*6777b538SAndroid Build Coastguard Worker     return 0;
120*6777b538SAndroid Build Coastguard Worker   memcpy(dst, reinterpret_cast<void*>(addr), size);
121*6777b538SAndroid Build Coastguard Worker   return size;
122*6777b538SAndroid Build Coastguard Worker }
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker // static
125*6777b538SAndroid Build Coastguard Worker std::unique_ptr<NativeUnwinderAndroidMemoryRegionsMap>
CreateMemoryRegionsMap(bool use_updatable_maps)126*6777b538SAndroid Build Coastguard Worker NativeUnwinderAndroid::CreateMemoryRegionsMap(bool use_updatable_maps) {
127*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<unwindstack::Maps> maps;
128*6777b538SAndroid Build Coastguard Worker   if (use_updatable_maps) {
129*6777b538SAndroid Build Coastguard Worker     maps = std::make_unique<unwindstack::LocalUpdatableMaps>();
130*6777b538SAndroid Build Coastguard Worker   } else {
131*6777b538SAndroid Build Coastguard Worker     maps = std::make_unique<unwindstack::LocalMaps>();
132*6777b538SAndroid Build Coastguard Worker   }
133*6777b538SAndroid Build Coastguard Worker   const bool success = maps->Parse();
134*6777b538SAndroid Build Coastguard Worker   DCHECK(success);
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker   return std::make_unique<NativeUnwinderAndroidMemoryRegionsMapImpl>(
137*6777b538SAndroid Build Coastguard Worker       std::move(maps), unwindstack::Memory::CreateLocalProcessMemory());
138*6777b538SAndroid Build Coastguard Worker }
139*6777b538SAndroid Build Coastguard Worker 
NativeUnwinderAndroid(uintptr_t exclude_module_with_base_address,NativeUnwinderAndroidMapDelegate * map_delegate,bool is_java_name_hashing_enabled)140*6777b538SAndroid Build Coastguard Worker NativeUnwinderAndroid::NativeUnwinderAndroid(
141*6777b538SAndroid Build Coastguard Worker     uintptr_t exclude_module_with_base_address,
142*6777b538SAndroid Build Coastguard Worker     NativeUnwinderAndroidMapDelegate* map_delegate,
143*6777b538SAndroid Build Coastguard Worker     bool is_java_name_hashing_enabled)
144*6777b538SAndroid Build Coastguard Worker     : is_java_name_hashing_enabled_(is_java_name_hashing_enabled),
145*6777b538SAndroid Build Coastguard Worker       exclude_module_with_base_address_(exclude_module_with_base_address),
146*6777b538SAndroid Build Coastguard Worker       map_delegate_(map_delegate),
147*6777b538SAndroid Build Coastguard Worker       memory_regions_map_(
148*6777b538SAndroid Build Coastguard Worker           static_cast<NativeUnwinderAndroidMemoryRegionsMapImpl*>(
149*6777b538SAndroid Build Coastguard Worker               map_delegate->GetMapReference())) {
150*6777b538SAndroid Build Coastguard Worker   DCHECK(map_delegate_);
151*6777b538SAndroid Build Coastguard Worker   DCHECK(memory_regions_map_);
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker 
~NativeUnwinderAndroid()154*6777b538SAndroid Build Coastguard Worker NativeUnwinderAndroid::~NativeUnwinderAndroid() {
155*6777b538SAndroid Build Coastguard Worker   if (module_cache())
156*6777b538SAndroid Build Coastguard Worker     module_cache()->UnregisterAuxiliaryModuleProvider(this);
157*6777b538SAndroid Build Coastguard Worker 
158*6777b538SAndroid Build Coastguard Worker   map_delegate_->ReleaseMapReference();
159*6777b538SAndroid Build Coastguard Worker }
160*6777b538SAndroid Build Coastguard Worker 
InitializeModules()161*6777b538SAndroid Build Coastguard Worker void NativeUnwinderAndroid::InitializeModules() {
162*6777b538SAndroid Build Coastguard Worker   module_cache()->RegisterAuxiliaryModuleProvider(this);
163*6777b538SAndroid Build Coastguard Worker }
164*6777b538SAndroid Build Coastguard Worker 
CanUnwindFrom(const Frame & current_frame) const165*6777b538SAndroid Build Coastguard Worker bool NativeUnwinderAndroid::CanUnwindFrom(const Frame& current_frame) const {
166*6777b538SAndroid Build Coastguard Worker   return current_frame.module && current_frame.module->IsNative() &&
167*6777b538SAndroid Build Coastguard Worker          current_frame.module->GetBaseAddress() !=
168*6777b538SAndroid Build Coastguard Worker              exclude_module_with_base_address_;
169*6777b538SAndroid Build Coastguard Worker }
170*6777b538SAndroid Build Coastguard Worker 
TryUnwind(RegisterContext * thread_context,uintptr_t stack_top,std::vector<Frame> * stack)171*6777b538SAndroid Build Coastguard Worker UnwindResult NativeUnwinderAndroid::TryUnwind(RegisterContext* thread_context,
172*6777b538SAndroid Build Coastguard Worker                                               uintptr_t stack_top,
173*6777b538SAndroid Build Coastguard Worker                                               std::vector<Frame>* stack) {
174*6777b538SAndroid Build Coastguard Worker   auto regs = CreateFromRegisterContext(thread_context);
175*6777b538SAndroid Build Coastguard Worker   DCHECK(regs);
176*6777b538SAndroid Build Coastguard Worker   unwindstack::ArchEnum arch = regs->Arch();
177*6777b538SAndroid Build Coastguard Worker 
178*6777b538SAndroid Build Coastguard Worker   do {
179*6777b538SAndroid Build Coastguard Worker     uint64_t cur_pc = regs->pc();
180*6777b538SAndroid Build Coastguard Worker     uint64_t cur_sp = regs->sp();
181*6777b538SAndroid Build Coastguard Worker     unwindstack::MapInfo* map_info =
182*6777b538SAndroid Build Coastguard Worker         memory_regions_map_->maps()->Find(cur_pc).get();
183*6777b538SAndroid Build Coastguard Worker     if (map_info == nullptr ||
184*6777b538SAndroid Build Coastguard Worker         map_info->flags() & unwindstack::MAPS_FLAGS_DEVICE_MAP) {
185*6777b538SAndroid Build Coastguard Worker       break;
186*6777b538SAndroid Build Coastguard Worker     }
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker     unwindstack::Elf* elf =
189*6777b538SAndroid Build Coastguard Worker         map_info->GetElf(memory_regions_map_->memory(), arch);
190*6777b538SAndroid Build Coastguard Worker     if (!elf->valid())
191*6777b538SAndroid Build Coastguard Worker       break;
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker     UnwindStackMemoryAndroid stack_memory(cur_sp, stack_top);
194*6777b538SAndroid Build Coastguard Worker     uintptr_t rel_pc = elf->GetRelPc(cur_pc, map_info);
195*6777b538SAndroid Build Coastguard Worker     bool is_signal_frame = false;
196*6777b538SAndroid Build Coastguard Worker     bool finished = false;
197*6777b538SAndroid Build Coastguard Worker     // map_info->GetElf() may return a valid elf whose memory() is nullptr.
198*6777b538SAndroid Build Coastguard Worker     // In the case, elf->StepIfSignalHandler() and elf->Step() are not
199*6777b538SAndroid Build Coastguard Worker     // available, because the method depends on elf->memory().
200*6777b538SAndroid Build Coastguard Worker     // (Regarding Step(), EvalRegister() needs memory.)
201*6777b538SAndroid Build Coastguard Worker     bool stepped =
202*6777b538SAndroid Build Coastguard Worker         elf->memory() &&
203*6777b538SAndroid Build Coastguard Worker         (elf->StepIfSignalHandler(rel_pc, regs.get(), &stack_memory) ||
204*6777b538SAndroid Build Coastguard Worker          elf->Step(rel_pc, regs.get(), &stack_memory, &finished,
205*6777b538SAndroid Build Coastguard Worker                    &is_signal_frame));
206*6777b538SAndroid Build Coastguard Worker     if (stepped && finished)
207*6777b538SAndroid Build Coastguard Worker       return UnwindResult::kCompleted;
208*6777b538SAndroid Build Coastguard Worker 
209*6777b538SAndroid Build Coastguard Worker     if (!stepped) {
210*6777b538SAndroid Build Coastguard Worker       // Stepping failed. Try unwinding using return address.
211*6777b538SAndroid Build Coastguard Worker       if (stack->size() == 1) {
212*6777b538SAndroid Build Coastguard Worker         if (!regs->SetPcFromReturnAddress(&stack_memory))
213*6777b538SAndroid Build Coastguard Worker           return UnwindResult::kAborted;
214*6777b538SAndroid Build Coastguard Worker       } else {
215*6777b538SAndroid Build Coastguard Worker         break;
216*6777b538SAndroid Build Coastguard Worker       }
217*6777b538SAndroid Build Coastguard Worker     }
218*6777b538SAndroid Build Coastguard Worker 
219*6777b538SAndroid Build Coastguard Worker     // If the pc and sp didn't change, then consider everything stopped.
220*6777b538SAndroid Build Coastguard Worker     if (cur_pc == regs->pc() && cur_sp == regs->sp())
221*6777b538SAndroid Build Coastguard Worker       return UnwindResult::kAborted;
222*6777b538SAndroid Build Coastguard Worker 
223*6777b538SAndroid Build Coastguard Worker     // Exclusive range of expected stack pointer values after the unwind.
224*6777b538SAndroid Build Coastguard Worker     struct {
225*6777b538SAndroid Build Coastguard Worker       uintptr_t start;
226*6777b538SAndroid Build Coastguard Worker       uintptr_t end;
227*6777b538SAndroid Build Coastguard Worker     } expected_stack_pointer_range = {static_cast<uintptr_t>(cur_sp),
228*6777b538SAndroid Build Coastguard Worker                                       stack_top};
229*6777b538SAndroid Build Coastguard Worker     if (regs->sp() < expected_stack_pointer_range.start ||
230*6777b538SAndroid Build Coastguard Worker         regs->sp() >= expected_stack_pointer_range.end) {
231*6777b538SAndroid Build Coastguard Worker       return UnwindResult::kAborted;
232*6777b538SAndroid Build Coastguard Worker     }
233*6777b538SAndroid Build Coastguard Worker 
234*6777b538SAndroid Build Coastguard Worker     if (regs->dex_pc() != 0) {
235*6777b538SAndroid Build Coastguard Worker       // Add a frame to represent the dex file.
236*6777b538SAndroid Build Coastguard Worker       EmitDexFrame(regs->dex_pc(), arch, stack);
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker       // Clear the dex pc so that we don't repeat this frame later.
239*6777b538SAndroid Build Coastguard Worker       regs->set_dex_pc(0);
240*6777b538SAndroid Build Coastguard Worker     }
241*6777b538SAndroid Build Coastguard Worker 
242*6777b538SAndroid Build Coastguard Worker     // Add the frame to |stack|. Must use GetModuleForAddress rather than
243*6777b538SAndroid Build Coastguard Worker     // GetExistingModuleForAddress because the unwound-to address may be in a
244*6777b538SAndroid Build Coastguard Worker     // module associated with a different unwinder.
245*6777b538SAndroid Build Coastguard Worker     const ModuleCache::Module* module =
246*6777b538SAndroid Build Coastguard Worker         module_cache()->GetModuleForAddress(regs->pc());
247*6777b538SAndroid Build Coastguard Worker     stack->emplace_back(regs->pc(), module);
248*6777b538SAndroid Build Coastguard Worker   } while (CanUnwindFrom(stack->back()));
249*6777b538SAndroid Build Coastguard Worker 
250*6777b538SAndroid Build Coastguard Worker   // Restore registers necessary for further unwinding in |thread_context|.
251*6777b538SAndroid Build Coastguard Worker   CopyToRegisterContext(regs.get(), thread_context);
252*6777b538SAndroid Build Coastguard Worker   return UnwindResult::kUnrecognizedFrame;
253*6777b538SAndroid Build Coastguard Worker }
254*6777b538SAndroid Build Coastguard Worker 
255*6777b538SAndroid Build Coastguard Worker std::unique_ptr<const ModuleCache::Module>
TryCreateModuleForAddress(uintptr_t address)256*6777b538SAndroid Build Coastguard Worker NativeUnwinderAndroid::TryCreateModuleForAddress(uintptr_t address) {
257*6777b538SAndroid Build Coastguard Worker   unwindstack::MapInfo* map_info =
258*6777b538SAndroid Build Coastguard Worker       memory_regions_map_->maps()->Find(address).get();
259*6777b538SAndroid Build Coastguard Worker   if (map_info == nullptr || !(map_info->flags() & PROT_EXEC) ||
260*6777b538SAndroid Build Coastguard Worker       map_info->flags() & unwindstack::MAPS_FLAGS_DEVICE_MAP) {
261*6777b538SAndroid Build Coastguard Worker     return nullptr;
262*6777b538SAndroid Build Coastguard Worker   }
263*6777b538SAndroid Build Coastguard Worker   return std::make_unique<NonElfModule>(map_info,
264*6777b538SAndroid Build Coastguard Worker                                         is_java_name_hashing_enabled_);
265*6777b538SAndroid Build Coastguard Worker }
266*6777b538SAndroid Build Coastguard Worker 
GetOrCreateDexFiles(unwindstack::ArchEnum arch)267*6777b538SAndroid Build Coastguard Worker unwindstack::DexFiles* NativeUnwinderAndroid::GetOrCreateDexFiles(
268*6777b538SAndroid Build Coastguard Worker     unwindstack::ArchEnum arch) {
269*6777b538SAndroid Build Coastguard Worker   if (!dex_files_) {
270*6777b538SAndroid Build Coastguard Worker     dex_files_ = unwindstack::CreateDexFiles(
271*6777b538SAndroid Build Coastguard Worker         arch, memory_regions_map_->memory(), search_libs_);
272*6777b538SAndroid Build Coastguard Worker   }
273*6777b538SAndroid Build Coastguard Worker   return dex_files_.get();
274*6777b538SAndroid Build Coastguard Worker }
275*6777b538SAndroid Build Coastguard Worker 
EmitDexFrame(uintptr_t dex_pc,unwindstack::ArchEnum arch,std::vector<Frame> * stack)276*6777b538SAndroid Build Coastguard Worker void NativeUnwinderAndroid::EmitDexFrame(uintptr_t dex_pc,
277*6777b538SAndroid Build Coastguard Worker                                          unwindstack::ArchEnum arch,
278*6777b538SAndroid Build Coastguard Worker                                          std::vector<Frame>* stack) {
279*6777b538SAndroid Build Coastguard Worker   const ModuleCache::Module* module =
280*6777b538SAndroid Build Coastguard Worker       module_cache()->GetExistingModuleForAddress(dex_pc);
281*6777b538SAndroid Build Coastguard Worker   if (!module) {
282*6777b538SAndroid Build Coastguard Worker     // The region containing |dex_pc| may not be in module_cache() since it's
283*6777b538SAndroid Build Coastguard Worker     // usually not executable (.dex file). Since non-executable regions
284*6777b538SAndroid Build Coastguard Worker     // are used much less commonly, it's lazily added here instead of from
285*6777b538SAndroid Build Coastguard Worker     // AddInitialModulesFromMaps().
286*6777b538SAndroid Build Coastguard Worker     unwindstack::MapInfo* map_info =
287*6777b538SAndroid Build Coastguard Worker         memory_regions_map_->maps()->Find(dex_pc).get();
288*6777b538SAndroid Build Coastguard Worker     if (map_info) {
289*6777b538SAndroid Build Coastguard Worker       auto new_module = std::make_unique<NonElfModule>(
290*6777b538SAndroid Build Coastguard Worker           map_info, is_java_name_hashing_enabled_);
291*6777b538SAndroid Build Coastguard Worker       module = new_module.get();
292*6777b538SAndroid Build Coastguard Worker       module_cache()->AddCustomNativeModule(std::move(new_module));
293*6777b538SAndroid Build Coastguard Worker     }
294*6777b538SAndroid Build Coastguard Worker   }
295*6777b538SAndroid Build Coastguard Worker 
296*6777b538SAndroid Build Coastguard Worker   if (is_java_name_hashing_enabled_) {
297*6777b538SAndroid Build Coastguard Worker     unwindstack::SharedString function_name;
298*6777b538SAndroid Build Coastguard Worker     uint64_t function_offset = 0;
299*6777b538SAndroid Build Coastguard Worker     GetOrCreateDexFiles(arch)->GetFunctionName(
300*6777b538SAndroid Build Coastguard Worker         memory_regions_map_->maps(), dex_pc, &function_name, &function_offset);
301*6777b538SAndroid Build Coastguard Worker     stack->emplace_back(
302*6777b538SAndroid Build Coastguard Worker         HashMetricNameAs32Bits(static_cast<const std::string&>(function_name)),
303*6777b538SAndroid Build Coastguard Worker         module);
304*6777b538SAndroid Build Coastguard Worker     UMA_HISTOGRAM_COUNTS_1000(
305*6777b538SAndroid Build Coastguard Worker         "UMA.StackProfiler.JavaNameLength",
306*6777b538SAndroid Build Coastguard Worker         static_cast<const std::string&>(function_name).size());
307*6777b538SAndroid Build Coastguard Worker   } else {
308*6777b538SAndroid Build Coastguard Worker     stack->emplace_back(dex_pc, module);
309*6777b538SAndroid Build Coastguard Worker   }
310*6777b538SAndroid Build Coastguard Worker }
311*6777b538SAndroid Build Coastguard Worker 
312*6777b538SAndroid Build Coastguard Worker }  // namespace base
313