On Mon, Oct 31, 2011 at 11:03:42AM -0700, Roland McGrath wrote:
> I'm not entirely sure about having this as a new public interface.  It
> might make more sense to return the Elf_Scn of the symtab or something like
> that.  My inclination is to start out by only using the information
> internally, and think about a public interface for it later when there is
> actual demand for that.

The patch started out with just that dwfl_module_symtab_global function,
to make a more efficient version of dwfl_module_addrsym that searched
the globals first. Then I realized I should just make dwfl_module_addrsym
be more efficient itself.

I only wanted to expose the index where the globals started (if known)
since that is all you need to use it together with dwfl_module_getsymtab
and dwfl_module_getsym. The symbols don't actually have to come from an
actual Elf_Scn, they could come from the dynamic symbol table via phdrs.

I removed the public interface for now and just access the field directly
in dwfl_module_addrsym. Any preference on a public interface?

> I think "symglobals" is an unnatural name for fields and variables for
> this.  It looks like a count, and what it's the count of is the locals.
> So something like "nlocals" or "first_global" makes more sense to me.

first_global does sound better. I changed it in the attached patch.
OK, to commit this version for now, while we discuss whether or not
and how the public interface should look?

Thanks,

Mark
>From ef5d02a5f6fec14f294c7c3f1e8569d2a1b99ef0 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <[email protected]>
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  <[email protected]>
 
+       * 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  <[email protected]>
+
        * 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

_______________________________________________
elfutils-devel mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/elfutils-devel

Reply via email to