diff options
Diffstat (limited to 'libdwfl/dwfl_module_addrsym.c')
-rw-r--r-- | libdwfl/dwfl_module_addrsym.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c index fdc95fc0..d2059ea4 100644 --- a/libdwfl/dwfl_module_addrsym.c +++ b/libdwfl/dwfl_module_addrsym.c @@ -1,5 +1,5 @@ /* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2005-2011 Red Hat, Inc. + Copyright (C) 2005-2012 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -41,7 +41,8 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, /* Return true iff we consider ADDR to lie in the same section as SYM. */ GElf_Word addr_shndx = SHN_UNDEF; - inline bool same_section (const GElf_Sym *sym, GElf_Word shndx) + inline bool same_section (const GElf_Sym *sym, struct dwfl_file *symfile, + GElf_Word shndx) { /* For absolute symbols and the like, only match exactly. */ if (shndx >= SHN_LORESERVE) @@ -50,10 +51,10 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, /* Figure out what section ADDR lies in. */ if (addr_shndx == SHN_UNDEF) { - GElf_Addr mod_addr = dwfl_deadjust_st_value (mod, addr); + GElf_Addr mod_addr = dwfl_deadjust_st_value (mod, symfile, addr); Elf_Scn *scn = NULL; addr_shndx = SHN_ABS; - while ((scn = elf_nextscn (mod->symfile->elf, scn)) != NULL) + while ((scn = elf_nextscn (symfile->elf, scn)) != NULL) { GElf_Shdr shdr_mem; GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); @@ -135,7 +136,11 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, } else if (closest_name == NULL && sym.st_value >= min_label - && same_section (&sym, shndx)) + && same_section (&sym, + ((size_t) i < mod->syments + ? mod->symfile + : &mod->aux_sym), + shndx)) { /* Handwritten assembly symbols sometimes have no st_size. If no symbol with proper size includes @@ -168,17 +173,19 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, } } - /* First go through global symbols. mod->first_global is setup by - dwfl_module_getsymtab to the index of the first global symbol in - the module's symbol table, or -1 when unknown. All symbols with - local binding come first in the symbol table, then all globals. */ - search_table (mod->first_global < 0 ? 1 : mod->first_global, syments); + /* First go through global symbols. mod->first_global and + mod->aux_first_global are setup by dwfl_module_getsymtab to the + index of the first global symbol in the module's symbol table. Both + are zero when unknown. All symbols with local binding come first in + the symbol table, then all globals. */ + int first_global = mod->first_global + mod->aux_first_global - 1; + search_table (first_global < 0 ? 1 : first_global, syments); /* If we found nothing searching the global symbols, then try the locals. Unless we have a global sizeless symbol that matches exactly. */ - if (closest_name == NULL && mod->first_global > 1 + if (closest_name == NULL && first_global > 1 && (sizeless_name == NULL || sizeless_sym.st_value != addr)) - search_table (1, mod->first_global); + search_table (1, first_global); /* If we found no proper sized symbol to use, fall back to the best candidate sizeless symbol we found, if any. */ |