This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] choose symbol from given block's objfile first.


Hello,

This patch is a prototype for an issue very briefly discussed on IRC.
Quick description of the problem:

    We have a program which is linked against two shared libraries.
    Both libraries define a global symbol with the same name. In my
    example, I used an int called this_library_version.  When trying
    to print the value of this global, GDB just randomly selects
    the first one it finds, and I couldn't find a way (that worked)
    which allowed me to print the value of the other global.

The idea behind this patch is to reduce a little bit the randomness.
If one is debugging code inside one of the shared libraries, then
the variable that the user probably wants is the one that is defined
inside that shared library.

It's a bit of a poor man's answer to this issue. On the one hand,
you do not always get the same symbol every single time. But on
the other hand, the selection process is implicit and not always
work-able for the user.  Eventually, what we thought we needed was
extend the expression parser to allow the user to qualify his
variable name with the name of the objfile, such as for instance:

        (gdb) print libsomething.so::this_library_version

This is something that can be done in parallel to this effort.
But I also believe that this is a useful patch, because I think
that the answer yielded by GDB using this algorithm has more chances
of returning the symbol that the user actually meant. A typical
scenario is that he's debugging code in some DSO, and then sees that
his code is referencing some variable which just happens to be
a global variable, and that the same variable is defined elsewhere.
Trying to figure out what's going on, he naively does:

        (gdb) print this_library_version

With this patch, he'll get the variable whose value corresponds to
his current context. Without this patch, and with enough bad luck,
the user gets an unrelated value, and gets confused because the
program does not behave as expected based on the global's value
printed by GDB.

This is only a prototype at the moment. It fixes the problem while
not causing any regression with the testsuite.  I am wondering about
the loop over all objfiles callling lookup_symbol_aux_quick. I think
I would need to apply the same treatment, in case
lookup_symbol_aux_symtabs doesn't return any match.  But I'm not sure
why I'd need that...

I also have a feeling that these are not the only locations where
we'll need to make this sort of change if we want to make this type
of behavior consistent across all our searches. Perhaps it make
make sense to introduce a new macro that iterates over all objfiles
starting with a specific objfile first. I can't propose a name for
that macro though...

        ALL_OBJFILES_STARTING_WITH

? Long-ish, but the best I've got so far. I thought about
ALL_OBJFILES_FROM, but I think the name is misleading. Another
option is to just extend ALL_OBJFILES to accept an objfile as
a second argument. But I think we'd be impacting too much code
just for a handle of places that might need it...


gdb/ChangeLog:

        * findvar.c (default_read_var_value): For LOC_UNRESOLVED symbols,
        try locating the symbol in the symbol's own objfile first, before
        extending the search to all objfiles.
        * symtab.c (lookup_symbol_aux_objfile): New function, extracted
        out of lookup_symbol_aux_symtabs.
        (lookup_symbol_aux_symtabs): Add new parameter "context_objfile".
        Replace extracted-out code by call to lookup_symbol_aux_objfile.
        if CONTEXT_OBJFILE is not NULL, then search this objfile first,
        before searching the other objfiles.

Thoughts?

Thank you!
-- 
Joel

---
 gdb/findvar.c |   10 ++++++-
 gdb/symtab.c  |   90 ++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 70 insertions(+), 30 deletions(-)

diff --git a/gdb/findvar.c b/gdb/findvar.c
index 9009e6f..ed7903c 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -562,7 +562,15 @@ default_read_var_value (struct symbol *var, struct frame_info *frame)
 	struct minimal_symbol *msym;
 	struct obj_section *obj_section;
 
-	msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (var), NULL, NULL);
+	/* First, try locating the associated minimal symbol within
+	   the same objfile.  This prevents us from selecting another
+	   symbol with the same name but located in a different objfile.  */
+	msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (var), NULL,
+				      SYMBOL_SYMTAB (var)->objfile);
+	/* If the lookup failed, try expanding the search to all
+	   objfiles.  */
+	if (msym == NULL)
+	  msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (var), NULL, NULL);
 	if (msym == NULL)
 	  error (_("No global symbol \"%s\"."), SYMBOL_LINKAGE_NAME (var));
 	if (overlay_debugging)
diff --git a/gdb/symtab.c b/gdb/symtab.c
index d68e542..8542beb 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -95,7 +95,8 @@ struct symbol *lookup_symbol_aux_local (const char *name,
 static
 struct symbol *lookup_symbol_aux_symtabs (int block_index,
 					  const char *name,
-					  const domain_enum domain);
+					  const domain_enum domain,
+					  struct objfile *context_objfile);
 
 static
 struct symbol *lookup_symbol_aux_quick (struct objfile *objfile,
@@ -1361,7 +1362,7 @@ lookup_static_symbol_aux (const char *name, const domain_enum domain)
   struct objfile *objfile;
   struct symbol *sym;
 
-  sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, domain);
+  sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, domain, NULL);
   if (sym != NULL)
     return sym;
 
@@ -1500,40 +1501,70 @@ lookup_global_symbol_from_objfile (const struct objfile *main_objfile,
   return NULL;
 }
 
-/* Check to see if the symbol is defined in one of the symtabs.
-   BLOCK_INDEX should be either GLOBAL_BLOCK or STATIC_BLOCK,
+/* Check to see if the symbol is defined in one of the OBJFILE's
+   symtabs.  BLOCK_INDEX should be either GLOBAL_BLOCK or STATIC_BLOCK,
    depending on whether or not we want to search global symbols or
    static symbols.  */
 
 static struct symbol *
-lookup_symbol_aux_symtabs (int block_index, const char *name,
-			   const domain_enum domain)
+lookup_symbol_aux_objfile (struct objfile *objfile, int block_index,
+			   const char *name, const domain_enum domain)
 {
-  struct symbol *sym;
-  struct objfile *objfile;
+  struct symbol *sym = NULL;
   struct blockvector *bv;
   const struct block *block;
   struct symtab *s;
 
+  if (objfile->sf)
+    objfile->sf->qf->pre_expand_symtabs_matching (objfile, block_index,
+						  name, domain);
+
+  ALL_OBJFILE_SYMTABS (objfile, s)
+    if (s->primary)
+      {
+	bv = BLOCKVECTOR (s);
+	block = BLOCKVECTOR_BLOCK (bv, block_index);
+	sym = lookup_block_symbol (block, name, domain);
+	if (sym)
+	  {
+	    block_found = block;
+	    return fixup_symbol_section (sym, objfile);
+	  }
+      }
+
+  return NULL;
+}
+
+/* Same as lookup_symbol_aux_objfile, except that it searches all
+   objfiles, stating with CONTEXT_OBJFILE first.  Return the first
+   match found.
+
+   If CONTEXT_OBJFILE is NULL, then start the search with any objfile.  */
+
+static struct symbol *
+lookup_symbol_aux_symtabs (int block_index, const char *name,
+			   const domain_enum domain,
+			   struct objfile *context_objfile)
+{
+  struct symbol *sym;
+  struct objfile *objfile;
+
+  if (context_objfile != NULL)
+    {
+      sym = lookup_symbol_aux_objfile (context_objfile, block_index,
+				       name, domain);
+      if (sym)
+	return sym;
+    }
+
   ALL_OBJFILES (objfile)
   {
-    if (objfile->sf)
-      objfile->sf->qf->pre_expand_symtabs_matching (objfile,
-						    block_index,
-						    name, domain);
-
-    ALL_OBJFILE_SYMTABS (objfile, s)
-      if (s->primary)
-	{
-	  bv = BLOCKVECTOR (s);
-	  block = BLOCKVECTOR_BLOCK (bv, block_index);
-	  sym = lookup_block_symbol (block, name, domain);
-	  if (sym)
-	    {
-	      block_found = block;
-	      return fixup_symbol_section (sym, objfile);
-	    }
-	}
+    if (objfile != context_objfile)
+      {
+	sym = lookup_symbol_aux_objfile (objfile, block_index, name, domain);
+	if (sym)
+	  return sym;
+      }
   }
 
   return NULL;
@@ -1659,16 +1690,17 @@ lookup_symbol_global (const char *name,
 		      const domain_enum domain)
 {
   struct symbol *sym = NULL;
+  struct objfile *block_objfile = NULL;
   struct objfile *objfile = NULL;
 
   /* Call library-specific lookup procedure.  */
-  objfile = lookup_objfile_from_block (block);
-  if (objfile != NULL)
-    sym = solib_global_lookup (objfile, name, domain);
+  block_objfile = lookup_objfile_from_block (block);
+  if (block_objfile != NULL)
+    sym = solib_global_lookup (block_objfile, name, domain);
   if (sym != NULL)
     return sym;
 
-  sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, domain);
+  sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, domain, block_objfile);
   if (sym != NULL)
     return sym;
 
-- 
1.7.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]