summaryrefslogtreecommitdiffstats
path: root/libbacktrace
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2013-11-04 14:38:07 -0800
committerChristopher Ferris <cferris@google.com>2013-11-04 14:50:36 -0800
commit923b5369202b0fbcd5d482fefe8de1c9fe2148a1 (patch)
treefd5d9bf66a7df6d1f99e5aa97a070aef5d965ead /libbacktrace
parent8c58086c54a23d33e915852a1355a171b09679cc (diff)
downloadsystem_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.cpp32
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 "";
}