diff options
author | Christopher Ferris <cferris@google.com> | 2013-11-04 14:38:07 -0800 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2013-11-04 14:50:36 -0800 |
commit | 923b5369202b0fbcd5d482fefe8de1c9fe2148a1 (patch) | |
tree | fd5d9bf66a7df6d1f99e5aa97a070aef5d965ead /libbacktrace | |
parent | 8c58086c54a23d33e915852a1355a171b09679cc (diff) | |
download | system_core-923b5369202b0fbcd5d482fefe8de1c9fe2148a1.zip system_core-923b5369202b0fbcd5d482fefe8de1c9fe2148a1.tar.gz system_core-923b5369202b0fbcd5d482fefe8de1c9fe2148a1.tar.bz2 |
Add corkscrew support for finding static symbols.
Change-Id: Ie557a9b0efadece75e1accaa7e214fb559eb19e1
Diffstat (limited to 'libbacktrace')
-rw-r--r-- | libbacktrace/Corkscrew.cpp | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/libbacktrace/Corkscrew.cpp b/libbacktrace/Corkscrew.cpp index 9daa752..2be5930 100644 --- a/libbacktrace/Corkscrew.cpp +++ b/libbacktrace/Corkscrew.cpp @@ -86,15 +86,33 @@ bool CorkscrewCurrent::Unwind(size_t num_ignore_frames) { std::string CorkscrewCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) { *offset = 0; - // Get information about the current thread. Dl_info info; const backtrace_map_info_t* map_info = backtrace_obj_->FindMapInfo(pc); - const char* symbol_name = NULL; - if (map_info && dladdr((const void*)pc, &info) && info.dli_sname) { - *offset = pc - map_info->start - (uintptr_t)info.dli_saddr + (uintptr_t)info.dli_fbase; - symbol_name = info.dli_sname; - - return symbol_name; + if (map_info) { + if (dladdr((const void*)pc, &info)) { + if (info.dli_sname) { + *offset = pc - map_info->start - (uintptr_t)info.dli_saddr + (uintptr_t)info.dli_fbase; + return info.dli_sname; + } + } else { + // dladdr(3) didn't find a symbol; maybe it's static? Look in the ELF file... + symbol_table_t* symbol_table = load_symbol_table(map_info->name); + if (symbol_table) { + // First check if we can find the symbol using a relative pc. + std::string name; + const symbol_t* elf_symbol = find_symbol(symbol_table, pc - map_info->start); + if (elf_symbol) { + name = elf_symbol->name; + *offset = pc - map_info->start - elf_symbol->start; + } else if ((elf_symbol = find_symbol(symbol_table, pc)) != NULL) { + // Found the symbol using the absolute pc. + name = elf_symbol->name; + *offset = pc - elf_symbol->start; + } + free_symbol_table(symbol_table); + return name; + } + } } return ""; } |