123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "base/profiler/native_unwinder_android.h"
- #include <sys/mman.h>
- #include <string>
- #include <vector>
- #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Elf.h"
- #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Memory.h"
- #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Regs.h"
- #include "base/memory/ptr_util.h"
- #include "base/notreached.h"
- #include "base/profiler/module_cache.h"
- #include "base/profiler/profile_builder.h"
- #include "build/build_config.h"
- #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
- #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/MachineArm.h"
- #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/RegsArm.h"
- #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
- #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/MachineArm64.h"
- #include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/RegsArm64.h"
- #endif // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
- namespace base {
- namespace {
- class NonElfModule : public ModuleCache::Module {
- public:
- NonElfModule(unwindstack::MapInfo* map_info)
- : start_(map_info->start),
- size_(map_info->end - start_),
- map_info_name_(map_info->name) {}
- ~NonElfModule() override = default;
- uintptr_t GetBaseAddress() const override { return start_; }
- std::string GetId() const override { return std::string(); }
- FilePath GetDebugBasename() const override {
- return FilePath(map_info_name_);
- }
- // Gets the size of the module.
- size_t GetSize() const override { return size_; }
- // True if this is a native module.
- bool IsNative() const override { return true; }
- private:
- const uintptr_t start_;
- const size_t size_;
- const std::string map_info_name_;
- };
- std::unique_ptr<unwindstack::Regs> CreateFromRegisterContext(
- RegisterContext* thread_context) {
- #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
- return WrapUnique<unwindstack::Regs>(unwindstack::RegsArm::Read(
- reinterpret_cast<void*>(&thread_context->arm_r0)));
- #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
- return WrapUnique<unwindstack::Regs>(unwindstack::RegsArm64::Read(
- reinterpret_cast<void*>(&thread_context->regs[0])));
- #else // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
- NOTREACHED();
- return nullptr;
- #endif // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
- }
- void CopyToRegisterContext(unwindstack::Regs* regs,
- RegisterContext* thread_context) {
- #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
- memcpy(reinterpret_cast<void*>(&thread_context->arm_r0), regs->RawData(),
- unwindstack::ARM_REG_LAST * sizeof(uintptr_t));
- #elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
- memcpy(reinterpret_cast<void*>(&thread_context->regs[0]), regs->RawData(),
- unwindstack::ARM64_REG_LAST * sizeof(uintptr_t));
- #else // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
- NOTREACHED();
- #endif // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
- }
- } // namespace
- UnwindStackMemoryAndroid::UnwindStackMemoryAndroid(uintptr_t stack_ptr,
- uintptr_t stack_top)
- : stack_ptr_(stack_ptr), stack_top_(stack_top) {
- DCHECK_LE(stack_ptr_, stack_top_);
- }
- UnwindStackMemoryAndroid::~UnwindStackMemoryAndroid() = default;
- size_t UnwindStackMemoryAndroid::Read(uint64_t addr, void* dst, size_t size) {
- if (addr < stack_ptr_)
- return 0;
- if (size >= stack_top_ || addr > stack_top_ - size)
- return 0;
- memcpy(dst, reinterpret_cast<void*>(addr), size);
- return size;
- }
- // static
- std::unique_ptr<unwindstack::Maps> NativeUnwinderAndroid::CreateMaps() {
- auto maps = std::make_unique<unwindstack::LocalMaps>();
- if (maps->Parse())
- return maps;
- return nullptr;
- }
- // static
- std::unique_ptr<unwindstack::Memory>
- NativeUnwinderAndroid::CreateProcessMemory() {
- return unwindstack::Memory::CreateLocalProcessMemory();
- }
- NativeUnwinderAndroid::NativeUnwinderAndroid(
- unwindstack::Maps* memory_regions_map,
- unwindstack::Memory* process_memory,
- uintptr_t exclude_module_with_base_address)
- : memory_regions_map_(memory_regions_map),
- process_memory_(process_memory),
- exclude_module_with_base_address_(exclude_module_with_base_address) {}
- NativeUnwinderAndroid::~NativeUnwinderAndroid() {
- if (module_cache())
- module_cache()->UnregisterAuxiliaryModuleProvider(this);
- }
- void NativeUnwinderAndroid::InitializeModules() {
- module_cache()->RegisterAuxiliaryModuleProvider(this);
- }
- bool NativeUnwinderAndroid::CanUnwindFrom(const Frame& current_frame) const {
- return current_frame.module && current_frame.module->IsNative() &&
- current_frame.module->GetBaseAddress() !=
- exclude_module_with_base_address_;
- }
- UnwindResult NativeUnwinderAndroid::TryUnwind(RegisterContext* thread_context,
- uintptr_t stack_top,
- std::vector<Frame>* stack) const {
- auto regs = CreateFromRegisterContext(thread_context);
- DCHECK(regs);
- unwindstack::ArchEnum arch = regs->Arch();
- do {
- uint64_t cur_pc = regs->pc();
- uint64_t cur_sp = regs->sp();
- unwindstack::MapInfo* map_info = memory_regions_map_->Find(cur_pc);
- if (map_info == nullptr ||
- map_info->flags & unwindstack::MAPS_FLAGS_DEVICE_MAP) {
- break;
- }
- unwindstack::Elf* elf = map_info->GetElf(
- {process_memory_.get(), [](unwindstack::Memory*) {}}, arch);
- if (!elf->valid())
- break;
- UnwindStackMemoryAndroid stack_memory(cur_sp, stack_top);
- uintptr_t rel_pc = elf->GetRelPc(cur_pc, map_info);
- bool finished = false;
- bool stepped =
- elf->StepIfSignalHandler(rel_pc, regs.get(), &stack_memory) ||
- elf->Step(rel_pc, regs.get(), &stack_memory, &finished);
- if (stepped && finished)
- return UnwindResult::kCompleted;
- if (!stepped) {
- // Stepping failed. Try unwinding using return address.
- if (stack->size() == 1) {
- if (!regs->SetPcFromReturnAddress(&stack_memory))
- return UnwindResult::kAborted;
- } else {
- break;
- }
- }
- // If the pc and sp didn't change, then consider everything stopped.
- if (cur_pc == regs->pc() && cur_sp == regs->sp())
- return UnwindResult::kAborted;
- // Exclusive range of expected stack pointer values after the unwind.
- struct {
- uintptr_t start;
- uintptr_t end;
- } expected_stack_pointer_range = {static_cast<uintptr_t>(cur_sp),
- stack_top};
- if (regs->sp() < expected_stack_pointer_range.start ||
- regs->sp() >= expected_stack_pointer_range.end) {
- return UnwindResult::kAborted;
- }
- if (regs->dex_pc() != 0) {
- // Add a frame to represent the dex file.
- EmitDexFrame(regs->dex_pc(), stack);
- // Clear the dex pc so that we don't repeat this frame later.
- regs->set_dex_pc(0);
- }
- // Add the frame to |stack|. Must use GetModuleForAddress rather than
- // GetExistingModuleForAddress because the unwound-to address may be in a
- // module associated with a different unwinder.
- const ModuleCache::Module* module =
- module_cache()->GetModuleForAddress(regs->pc());
- stack->emplace_back(regs->pc(), module);
- } while (CanUnwindFrom(stack->back()));
- // Restore registers necessary for further unwinding in |thread_context|.
- CopyToRegisterContext(regs.get(), thread_context);
- return UnwindResult::kUnrecognizedFrame;
- }
- std::unique_ptr<const ModuleCache::Module>
- NativeUnwinderAndroid::TryCreateModuleForAddress(uintptr_t address) {
- unwindstack::MapInfo* map_info = memory_regions_map_->Find(address);
- if (map_info == nullptr || !(map_info->flags & PROT_EXEC) ||
- map_info->flags & unwindstack::MAPS_FLAGS_DEVICE_MAP) {
- return nullptr;
- }
- return std::make_unique<NonElfModule>(map_info);
- }
- void NativeUnwinderAndroid::EmitDexFrame(uintptr_t dex_pc,
- std::vector<Frame>* stack) const {
- const ModuleCache::Module* module =
- module_cache()->GetExistingModuleForAddress(dex_pc);
- if (!module) {
- // The region containing |dex_pc| may not be in module_cache() since it's
- // usually not executable (.dex file). Since non-executable regions
- // are used much less commonly, it's lazily added here instead of from
- // AddInitialModulesFromMaps().
- unwindstack::MapInfo* map_info = memory_regions_map_->Find(dex_pc);
- if (map_info) {
- auto new_module = std::make_unique<NonElfModule>(map_info);
- module = new_module.get();
- module_cache()->AddCustomNativeModule(std::move(new_module));
- }
- }
- stack->emplace_back(dex_pc, module);
- }
- } // namespace base
|