From 395f42d36d37a81ce1c11918bfded0a2afaa6195 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Wed, 20 Dec 2017 18:49:01 -0800 Subject: Add ability to read jit gdb data. Changes: - New JitDebug class to handle all of the jit gdb interface. - Add unit tests for all, along with new offline test using debug data. - Add new Memory type called MemoryOfflineParts that has multiple MemoryOffline objects to support the offline test. - Update the tools to use the JitDebug object. - Modify libbacktrace to use the JitDebug, but only looking in libart.so and libartd.so. - Change the Format32Bits to Is32Bit since it's more accurate and I use it in a different context where original name didn't make sense. - Add a new function to find global variables in an elf file (GetGlobalVariable). - Add a new function to determine if a pc is valid for this elf (IsValidPc). Bug: 68396769 Test: Ran new unit tests. Added new offline test that uses jit debug data. Test: Ran art test that generates jit data and verified a crash unwinds Test: through the jit data. Change-Id: I6e7ee2f5bab2242028a06feece156dff21c0a974 --- libunwindstack/Elf.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'libunwindstack/Elf.cpp') diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp index 5ec4a3d..220e549 100644 --- a/libunwindstack/Elf.cpp +++ b/libunwindstack/Elf.cpp @@ -103,6 +103,37 @@ bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offse addr, load_bias_, name, func_offset))); } +bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) { + if (!valid_) { + return false; + } + + if (!interface_->GetGlobalVariable(name, memory_address) && + (gnu_debugdata_interface_ == nullptr || + !gnu_debugdata_interface_->GetGlobalVariable(name, memory_address))) { + return false; + } + + // Adjust by the load bias. + if (*memory_address < load_bias_) { + return false; + } + + *memory_address -= load_bias_; + + // If this winds up in the dynamic section, then we might need to adjust + // the address. + uint64_t dynamic_end = interface_->dynamic_vaddr() + interface_->dynamic_size(); + if (*memory_address >= interface_->dynamic_vaddr() && *memory_address < dynamic_end) { + if (interface_->dynamic_vaddr() > interface_->dynamic_offset()) { + *memory_address -= interface_->dynamic_vaddr() - interface_->dynamic_offset(); + } else { + *memory_address += interface_->dynamic_offset() - interface_->dynamic_vaddr(); + } + } + return true; +} + // The relative pc is always relative to the start of the map from which it comes. bool Elf::Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, uint64_t elf_offset, Regs* regs, Memory* process_memory, bool* finished) { @@ -160,6 +191,23 @@ void Elf::GetInfo(Memory* memory, bool* valid, uint64_t* size) { } } +bool Elf::IsValidPc(uint64_t pc) { + if (!valid_ || pc < load_bias_) { + return false; + } + pc -= load_bias_; + + if (interface_->IsValidPc(pc)) { + return true; + } + + if (gnu_debugdata_interface_ != nullptr && gnu_debugdata_interface_->IsValidPc(pc)) { + return true; + } + + return false; +} + ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) { if (!IsValidElf(memory)) { return nullptr; -- cgit v1.2.3