diff options
author | Christopher Ferris <cferris@google.com> | 2017-12-20 18:49:01 -0800 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2018-01-12 11:18:42 -0800 |
commit | 395f42d36d37a81ce1c11918bfded0a2afaa6195 (patch) | |
tree | bb93f9254cc8a9757efcb30381777c887e061aea /libunwindstack/Elf.cpp | |
parent | 25b928937f95e7cee042350993700f0c6d67bb5c (diff) | |
download | unwinding-395f42d36d37a81ce1c11918bfded0a2afaa6195.tar.gz |
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
Diffstat (limited to 'libunwindstack/Elf.cpp')
-rw-r--r-- | libunwindstack/Elf.cpp | 48 |
1 files changed, 48 insertions, 0 deletions
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; |