From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3730 invoked by alias); 7 May 2012 22:43:26 -0000 Received: (qmail 3722 invoked by uid 22791); 7 May 2012 22:43:24 -0000 X-SWARE-Spam-Status: No, hits=-1.2 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,RCVD_IN_HOSTKARMA_NO,TW_BJ,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 07 May 2012 22:43:08 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 4891D1C6A9E; Mon, 7 May 2012 18:43:07 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id pcCw9gA+j3Yv; Mon, 7 May 2012 18:43:07 -0400 (EDT) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id E36E91C6A9C; Mon, 7 May 2012 18:43:06 -0400 (EDT) Received: by joel.gnat.com (Postfix, from userid 1000) id DF9C4145616; Mon, 7 May 2012 15:43:01 -0700 (PDT) From: Joel Brobecker To: gdb-patches@sourceware.org Cc: Joel Brobecker Subject: [RFC] choose symbol from given block's objfile first. Date: Mon, 07 May 2012 22:43:00 -0000 Message-Id: <1336430581-11262-1-git-send-email-brobecker@adacore.com> Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-05/txt/msg00204.txt.bz2 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