summaryrefslogtreecommitdiff
path: root/libdwfl/dwfl_module_addrsym.c
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2013-01-16 15:19:32 +0100
committerMark Wielaard <mjw@redhat.com>2013-01-22 16:09:18 +0100
commit5083a70d3b64946fa47ea5766943a15a3ecc6891 (patch)
treef819878e1fade1faf29ac7c9fe0288df529760ec /libdwfl/dwfl_module_addrsym.c
parent6d258ceb8dbf41e255397ed0db7d7635f398134c (diff)
downloadelfutils-5083a70d3b64946fa47ea5766943a15a3ecc6891.tar.gz
libdwfl: Add minisymtab support.
Add an auxiliary symbol table dwfl_file aux_sym to Dwfl_Module if all we have is the dynsym table. The main file might contain a .gnu_debugdata section. The .gnu_debugdata section is a compressed embedded ELF file that contains the text (code) section symbols from the symtab table that are not in the main file dynsym table. dwfl_module_getsymtab (), dwfl_module_addrsym () and dwfl_module_getsym () will use the auxiliary symbol table when available (and no full symtab is available from the debug file). * libdwflP.h (struct Dwfl_Module): Add aux_sym, aux_symdata, aux_syments, aux_symstrdata, aux_symxndxdata and aux_first_global. (dwfl_adjusted_aux_sym_addr): New function. (dwfl_deadjust_aux_sym_addr): Likewise. (dwfl_adjusted_st_value): Take and check symfile argument. (dwfl_deadjust_st_value): Likewise. * dwfl_module_getdwarf.c (find_prelink_address_sync): Take and use dwfl_file as argument to set address_sync. (find_debuginfo): Call find_prelink_address_sync with debug file. (find_aux_sym): New function. (find_symtab): Use find_aux_sym if all we have is the dynsym table and fill in aux DwflModule fields. (dwfl_module_getsymtab): Return syments plus aux_syments. (load_symtab): Always set first_global. * dwfl_module_addrsym.c (dwfl_module_addrsym): Check symfile when using same_section. Calculate first_global based on both mod->first_global and mod->aux_first_global. * dwfl_module.c (__libdwfl_module_free): Free aux_sym. * dwfl_module_getsym.c (dwfl_module_getsym): Use auxsym table to retrieve symbol and name if necessary, making sure all locals from any table come before any globals. * dwfl_module_info.c (dwfl_module_info): Call dwfl_adjusted_st_value with symfile. * relocate.c (resolve_symbol): Likewise. https://fedoraproject.org/wiki/Features/MiniDebugInfo Signed-off-by: Mark Wielaard <mjw@redhat.com>
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. */