>From ef5d02a5f6fec14f294c7c3f1e8569d2a1b99ef0 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 31 Oct 2011 23:17:06 +0100 Subject: [PATCH] Use index of first global symbol to speed up dwfl_module_addrsym search. Cache 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 before the global symbols. Use this information to speed up dwfl_module_addrsym search. --- libdwfl/ChangeLog | 10 ++++++++++ libdwfl/dwfl_module_addrsym.c | 20 +++++++++++++++++++- libdwfl/dwfl_module_getdwarf.c | 13 +++++++++---- libdwfl/libdwflP.h | 1 + 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 97caf0b..0cfa462 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,5 +1,15 @@ 2011-11-31 Mark Wielaard + * dwfl_module_addrsym.c (dwfl_module_addrsym): First search all + global symbols. Then only when that doesn't provide a match search + all local symbols too. + * dwfl_module_getdwarf.c (load_symtab): Take first_global int arg + and fill it in. + (find_symtab): Initialize mod->first_global and pass it to load_symtab. + * libdwfl/libdwflP.h (Dwfl_Module): Add first_global field. + +2011-11-31 Mark Wielaard + * dwfl_module_addrsym.c (dwfl_module_addrsym): Only update sizeless_sym if needed and closer to desired addr. diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c index 41ff465..eda1457 100644 --- a/libdwfl/dwfl_module_addrsym.c +++ b/libdwfl/dwfl_module_addrsym.c @@ -104,8 +104,16 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, /* Keep track of the lowest address a relevant sizeless symbol could have. */ GElf_Addr min_label = 0; + /* 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. */ + int start = mod->first_global < 0 ? 1 : mod->first_global; + int end = syments; + /* Look through the symbol table for a matching symbol. */ - for (int i = 1; i < syments; ++i) + search_table: + for (int i = start; i < end; ++i) { GElf_Sym sym; GElf_Word shndx; @@ -168,6 +176,16 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, } } + /* 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 && start != 1 && mod->first_global > 1 + && (sizeless_name == NULL || sizeless_sym.st_value != addr)) + { + start = 1; + end = mod->first_global; + goto search_table; + } + /* If we found no proper sized symbol to use, fall back to the best candidate sizeless symbol we found, if any. */ if (closest_name == NULL diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index 9c67713..14fcd55 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -568,7 +568,7 @@ find_debuginfo (Dwfl_Module *mod) static Dwfl_Error load_symtab (struct dwfl_file *file, struct dwfl_file **symfile, Elf_Scn **symscn, Elf_Scn **xndxscn, - size_t *syments, GElf_Word *strshndx) + size_t *syments, int *first_global, GElf_Word *strshndx) { bool symtab = false; Elf_Scn *scn = NULL; @@ -584,6 +584,7 @@ load_symtab (struct dwfl_file *file, struct dwfl_file **symfile, *symfile = file; *strshndx = shdr->sh_link; *syments = shdr->sh_size / shdr->sh_entsize; + *first_global = shdr->sh_info; if (*xndxscn != NULL) return DWFL_E_NOERROR; break; @@ -844,11 +845,14 @@ find_symtab (Dwfl_Module *mod) if (mod->symerr != DWFL_E_NOERROR) return; + mod->first_global = -1; /* Unknown, unless explicitly set by load_symtab. */ + /* First see if the main ELF file has the debugging information. */ Elf_Scn *symscn = NULL, *xndxscn = NULL; GElf_Word strshndx; mod->symerr = load_symtab (&mod->main, &mod->symfile, &symscn, - &xndxscn, &mod->syments, &strshndx); + &xndxscn, &mod->syments, &mod->first_global, + &strshndx); switch (mod->symerr) { default: @@ -867,7 +871,8 @@ find_symtab (Dwfl_Module *mod) case DWFL_E_NOERROR: mod->symerr = load_symtab (&mod->debug, &mod->symfile, &symscn, - &xndxscn, &mod->syments, &strshndx); + &xndxscn, &mod->syments, + &mod->first_global, &strshndx); break; case DWFL_E_CB: /* The find_debuginfo hook failed. */ @@ -906,7 +911,7 @@ find_symtab (Dwfl_Module *mod) return; } - /* Cache the data; MOD->syments was set above. */ + /* Cache the data; MOD->syments and MOD->first_global were set above. */ mod->symstrdata = elf_getdata (elf_getscn (mod->symfile->elf, strshndx), NULL); diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index 1f7532b..bca82d2 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -172,6 +172,7 @@ struct Dwfl_Module struct dwfl_file *symfile; /* Either main or debug. */ Elf_Data *symdata; /* Data in the ELF symbol table section. */ size_t syments; /* sh_size / sh_entsize of that section. */ + int first_global; /* Index of first global symbol of table. */ Elf_Data *symstrdata; /* Data for its string table. */ Elf_Data *symxndxdata; /* Data in the extended section index table. */ -- 1.7.4.4