summaryrefslogtreecommitdiffstats
path: root/libdwfl/dwfl_module_addrsym.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdwfl/dwfl_module_addrsym.c')
-rw-r--r--libdwfl/dwfl_module_addrsym.c31
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. */