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