summaryrefslogtreecommitdiff
path: root/tests/dwflsyms.c
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2013-11-27 16:45:44 +0100
committerMark Wielaard <mjw@redhat.com>2013-11-27 16:45:44 +0100
commit819c349f6339512d6961a6172c539fdf2c2f1328 (patch)
treec7be311a37ac6ebae7d27b10f401d131d7d8be0d /tests/dwflsyms.c
parent16bc4569a9d4c86aac4de749ccf27fa7b1ae24d5 (diff)
downloadelfutils-819c349f6339512d6961a6172c539fdf2c2f1328.tar.gz
libdwfl: Add dwfl_module_addrsym_elf and dwfl_module_getsym_elf.
Introduce two new functions that also return the elf associated with a symbol to make symbol section indexing work for non-special sections. Simplify code by removing dwfl_file where appropriate and just track Elf directly. Document limitations of shndx with existing dwfl_module_addrsym and dwfl_module_getsym. Extend dwflsyms testcase to check some more symbol and section (index) properties. Signed-off-by: Mark Wielaard <mjw@redhat.com>
Diffstat (limited to 'tests/dwflsyms.c')
-rw-r--r--tests/dwflsyms.c66
1 files changed, 62 insertions, 4 deletions
diff --git a/tests/dwflsyms.c b/tests/dwflsyms.c
index 55f2653c..10c01f1f 100644
--- a/tests/dwflsyms.c
+++ b/tests/dwflsyms.c
@@ -69,6 +69,42 @@ gelf_bind (GElf_Sym *sym)
}
static int
+gelf_bind_order (GElf_Sym *sym)
+{
+ switch (GELF_ST_BIND (sym->st_info))
+ {
+ case STB_LOCAL:
+ return 1;
+ case STB_WEAK:
+ return 2;
+ case STB_GLOBAL:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
+static const char *
+elf_section_name (Elf *elf, GElf_Word shndx)
+{
+ GElf_Ehdr ehdr;
+ GElf_Shdr shdr;
+ Elf_Scn *scn = elf_getscn (elf, shndx);
+ gelf_getshdr (scn, &shdr);
+ gelf_getehdr (elf, &ehdr);
+ return elf_strptr (elf, ehdr.e_shstrndx, shdr.sh_name);
+}
+
+bool
+addr_in_section (Elf *elf, GElf_Word shndx, GElf_Addr addr)
+{
+ GElf_Shdr shdr;
+ Elf_Scn *scn = elf_getscn (elf, shndx);
+ gelf_getshdr (scn, &shdr);
+ return addr >= shdr.sh_addr && addr < shdr.sh_addr + shdr.sh_size;
+}
+
+static int
list_syms (struct Dwfl_Module *mod,
void **user __attribute__ ((unused)),
const char *mod_name __attribute__ ((unused)),
@@ -82,7 +118,10 @@ list_syms (struct Dwfl_Module *mod,
{
GElf_Sym sym;
GElf_Word shndxp;
- const char *name = dwfl_module_getsym (mod, ndx, &sym, &shndxp);
+ Elf *elf;
+ Dwarf_Addr bias;
+ const char *name = dwfl_module_getsym_elf (mod, ndx, &sym, &shndxp,
+ &elf, &bias);
printf("%4d: %s\t%s\t%s (%" PRIu64 ") %#" PRIx64,
ndx, gelf_type (&sym), gelf_bind (&sym), name,
sym.st_size, sym.st_value);
@@ -92,15 +131,34 @@ list_syms (struct Dwfl_Module *mod,
dwfl_module_getsym (). */
if (GELF_ST_TYPE (sym.st_info) == STT_FUNC && shndxp != SHN_UNDEF)
{
+ /* Make sure the adjusted value really falls in the elf section. */
+ assert (addr_in_section (elf, shndxp, sym.st_value - bias));
+
GElf_Addr addr = sym.st_value;
GElf_Sym asym;
GElf_Word ashndxp;
- const char *aname = dwfl_module_addrsym (mod, addr, &asym, &ashndxp);
- assert (strcmp (name, aname) == 0);
+ Elf *aelf;
+ Dwarf_Addr abias;
+ const char *aname = dwfl_module_addrsym_elf (mod, addr, &asym,
+ &ashndxp, &aelf, &abias);
+
+ /* Make sure the adjusted value really falls in the elf section. */
+ assert (addr_in_section (aelf, ashndxp, asym.st_value - abias));
+
+ /* Either they are the same symbol (name), the binding of
+ asym is "stronger" (or equal) to sym or asym is more specific
+ (has a lower address) than sym. */
+ assert ((strcmp (name, aname) == 0
+ || gelf_bind_order (&asym) >= gelf_bind_order (&sym))
+ && asym.st_value <= sym.st_value);
int res = dwfl_module_relocate_address (mod, &addr);
assert (res != -1);
- printf(", rel: %#" PRIx64 "", addr);
+ if (shndxp < SHN_LORESERVE)
+ printf(", rel: %#" PRIx64 " (%s)", addr,
+ elf_section_name (elf, shndxp));
+ else
+ printf(", rel: %#" PRIx64 "", addr);
}
printf ("\n");
}