summaryrefslogtreecommitdiff
path: root/libunwindstack/Elf.cpp
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2017-12-20 18:49:01 -0800
committerChristopher Ferris <cferris@google.com>2018-01-12 11:18:42 -0800
commit395f42d36d37a81ce1c11918bfded0a2afaa6195 (patch)
treebb93f9254cc8a9757efcb30381777c887e061aea /libunwindstack/Elf.cpp
parent25b928937f95e7cee042350993700f0c6d67bb5c (diff)
downloadunwinding-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.cpp48
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;