xref: /aosp_15_r20/external/cronet/base/profiler/native_unwinder_android.h (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 #ifndef BASE_PROFILER_NATIVE_UNWINDER_ANDROID_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_PROFILER_NATIVE_UNWINDER_ANDROID_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <memory>
9*6777b538SAndroid Build Coastguard Worker #include <vector>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/profiler/unwinder.h"
13*6777b538SAndroid Build Coastguard Worker #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/DexFiles.h"
14*6777b538SAndroid Build Coastguard Worker #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Memory.h"
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker namespace base {
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker class NativeUnwinderAndroidMapDelegate;
19*6777b538SAndroid Build Coastguard Worker class NativeUnwinderAndroidMemoryRegionsMap;
20*6777b538SAndroid Build Coastguard Worker class NativeUnwinderAndroidMemoryRegionsMapImpl;
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker // Implementation of unwindstack::Memory that restricts memory access to a stack
23*6777b538SAndroid Build Coastguard Worker // buffer, used by NativeUnwinderAndroid. While unwinding, only memory accesses
24*6777b538SAndroid Build Coastguard Worker // within the stack should be performed to restore registers.
25*6777b538SAndroid Build Coastguard Worker class UnwindStackMemoryAndroid : public unwindstack::Memory {
26*6777b538SAndroid Build Coastguard Worker  public:
27*6777b538SAndroid Build Coastguard Worker   UnwindStackMemoryAndroid(uintptr_t stack_ptr, uintptr_t stack_top);
28*6777b538SAndroid Build Coastguard Worker   ~UnwindStackMemoryAndroid() override;
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker   size_t Read(uint64_t addr, void* dst, size_t size) override;
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker  private:
33*6777b538SAndroid Build Coastguard Worker   const uintptr_t stack_ptr_;
34*6777b538SAndroid Build Coastguard Worker   const uintptr_t stack_top_;
35*6777b538SAndroid Build Coastguard Worker };
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker // Native unwinder implementation for Android, using libunwindstack.
38*6777b538SAndroid Build Coastguard Worker class NativeUnwinderAndroid : public Unwinder,
39*6777b538SAndroid Build Coastguard Worker                               public ModuleCache::AuxiliaryModuleProvider {
40*6777b538SAndroid Build Coastguard Worker  public:
41*6777b538SAndroid Build Coastguard Worker   // Creates maps object from /proc/self/maps for use by NativeUnwinderAndroid.
42*6777b538SAndroid Build Coastguard Worker   // Since this is an expensive call, the maps object should be re-used across
43*6777b538SAndroid Build Coastguard Worker   // all profiles in a process.
44*6777b538SAndroid Build Coastguard Worker   // Set |use_updatable_maps| to true to use unwindstack::LocalUpdatableMaps,
45*6777b538SAndroid Build Coastguard Worker   // instead of unwindstack::LocalMaps. LocalUpdatableMaps might be preferable
46*6777b538SAndroid Build Coastguard Worker   // when the frames come from dynamically added ELFs like JITed ELFs, or
47*6777b538SAndroid Build Coastguard Worker   // dynamically loaded libraries. With LocalMaps the frames corresponding to
48*6777b538SAndroid Build Coastguard Worker   // newly loaded ELFs don't get unwound since the existing maps structure
49*6777b538SAndroid Build Coastguard Worker   // fails to find a map for the given pc while LocalUpdatableMaps reparses
50*6777b538SAndroid Build Coastguard Worker   // /proc/self/maps when it fails to find a map for the given pc and then can
51*6777b538SAndroid Build Coastguard Worker   // successfully unwind through newly loaded ELFs as well.
52*6777b538SAndroid Build Coastguard Worker   static std::unique_ptr<NativeUnwinderAndroidMemoryRegionsMap>
53*6777b538SAndroid Build Coastguard Worker   CreateMemoryRegionsMap(bool use_updatable_maps = false);
54*6777b538SAndroid Build Coastguard Worker 
55*6777b538SAndroid Build Coastguard Worker   // |exclude_module_with_base_address| is used to exclude a specific module and
56*6777b538SAndroid Build Coastguard Worker   // let another unwinder take control. TryUnwind() will exit with
57*6777b538SAndroid Build Coastguard Worker   // UNRECOGNIZED_FRAME and CanUnwindFrom() will return false when a frame is
58*6777b538SAndroid Build Coastguard Worker   // encountered in that module.
59*6777b538SAndroid Build Coastguard Worker   // |map_delegate| is used to manage memory used by libunwindstack. It must
60*6777b538SAndroid Build Coastguard Worker   // outlives this object.
61*6777b538SAndroid Build Coastguard Worker   NativeUnwinderAndroid(uintptr_t exclude_module_with_base_address,
62*6777b538SAndroid Build Coastguard Worker                         NativeUnwinderAndroidMapDelegate* map_delegate,
63*6777b538SAndroid Build Coastguard Worker                         bool is_java_name_hashing_enabled);
64*6777b538SAndroid Build Coastguard Worker   ~NativeUnwinderAndroid() override;
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker   NativeUnwinderAndroid(const NativeUnwinderAndroid&) = delete;
67*6777b538SAndroid Build Coastguard Worker   NativeUnwinderAndroid& operator=(const NativeUnwinderAndroid&) = delete;
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker   // Unwinder
70*6777b538SAndroid Build Coastguard Worker   void InitializeModules() override;
71*6777b538SAndroid Build Coastguard Worker   bool CanUnwindFrom(const Frame& current_frame) const override;
72*6777b538SAndroid Build Coastguard Worker   UnwindResult TryUnwind(RegisterContext* thread_context,
73*6777b538SAndroid Build Coastguard Worker                          uintptr_t stack_top,
74*6777b538SAndroid Build Coastguard Worker                          std::vector<Frame>* stack) override;
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker   // ModuleCache::AuxiliaryModuleProvider
77*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<const ModuleCache::Module> TryCreateModuleForAddress(
78*6777b538SAndroid Build Coastguard Worker       uintptr_t address) override;
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker  private:
81*6777b538SAndroid Build Coastguard Worker   unwindstack::DexFiles* GetOrCreateDexFiles(unwindstack::ArchEnum arch);
82*6777b538SAndroid Build Coastguard Worker 
83*6777b538SAndroid Build Coastguard Worker   void EmitDexFrame(uintptr_t dex_pc,
84*6777b538SAndroid Build Coastguard Worker                     unwindstack::ArchEnum,
85*6777b538SAndroid Build Coastguard Worker                     std::vector<Frame>* stack);
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker   const bool is_java_name_hashing_enabled_;
88*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<unwindstack::DexFiles> dex_files_;
89*6777b538SAndroid Build Coastguard Worker 
90*6777b538SAndroid Build Coastguard Worker   const uintptr_t exclude_module_with_base_address_;
91*6777b538SAndroid Build Coastguard Worker   raw_ptr<NativeUnwinderAndroidMapDelegate> map_delegate_;
92*6777b538SAndroid Build Coastguard Worker   const raw_ptr<NativeUnwinderAndroidMemoryRegionsMapImpl> memory_regions_map_;
93*6777b538SAndroid Build Coastguard Worker   // This is a vector (rather than an array) because it gets used in functions
94*6777b538SAndroid Build Coastguard Worker   // from libunwindstack.
95*6777b538SAndroid Build Coastguard Worker   const std::vector<std::string> search_libs_ = {"libart.so", "libartd.so"};
96*6777b538SAndroid Build Coastguard Worker };
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker }  // namespace base
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker #endif  // BASE_PROFILER_NATIVE_UNWINDER_ANDROID_H_
101