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