diff options
author | Mark Wielaard <mjw@redhat.com> | 2013-01-16 15:19:32 +0100 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2013-01-22 16:09:18 +0100 |
commit | 5083a70d3b64946fa47ea5766943a15a3ecc6891 (patch) | |
tree | f819878e1fade1faf29ac7c9fe0288df529760ec /libdwfl/dwfl_module_addrsym.c | |
parent | 6d258ceb8dbf41e255397ed0db7d7635f398134c (diff) | |
download | elfutils-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.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. */ |