From 0dd7ddbea74f09ae483ceaaf657a44df1a8ddbc4 Mon Sep 17 00:00:00 2001 From: Guinevere Larsen Date: Thu, 27 Mar 2025 11:43:58 -0300 Subject: [PATCH] gdb: Make the parser recognize the [[N]] syntax for variables This commit adds a couple new rules to the YACC parser, that will allow GDB to recognize expressions like [[N]]::var. Notably, a block equivalent has not been added yet, so an expression like [[N]]::foo::var will not work yet. This is accomplished by introducing a new function, lookup_symbol_in_linker_namespace, that will only perform the symbol lookup in the objfiles that belong to the requested namespace. This function should probably also be used in the generic lookup_symbol function, as if "var" exists in several namespaces, it is probably more natural to the user to get the var in the current namespace, if it exists. This will be done in a future patch. --- gdb/c-exp.y | 48 ++++++++++++++++++++++++++++++++++++++++-------- gdb/solib.c | 1 + gdb/symtab.c | 38 ++++++++++++++++++++++++++++++++++++++ gdb/symtab.h | 8 ++++++++ 4 files changed, 87 insertions(+), 8 deletions(-) diff --git a/gdb/c-exp.y b/gdb/c-exp.y index f53a1383b72..ea94dad54a5 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -145,6 +145,11 @@ using namespace expr; struct symtoken ssym; int voidval; const struct block *bval; + struct scope_val_type_i_guess { + bool has_namespace; + const struct block *bval; + LONGEST namespace_val; + } scope_val; enum exp_opcode opcode; struct stoken_vector svec; @@ -265,7 +270,8 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); %right ARROW ARROW_STAR '.' DOT_STAR '[' OBJC_LBRAC '(' %token BLOCKNAME %token FILENAME -%type block +%type namespace +%type block %left COLONCOLON %token DOTDOTDOT @@ -1067,17 +1073,22 @@ exp : FALSEKEYWORD /* end of C++. */ +namespace: '[' '[' INT ']' ']' + { + $$ = $3; + } + ; + block : BLOCKNAME { - if ($1.sym.symbol) - $$ = $1.sym.symbol->value_block (); - else + if (!$1.sym.symbol) error (_("No file or function \"%s\"."), copy_name ($1.stoken).c_str ()); + $$.bval = $1.sym.symbol->value_block (); } | FILENAME { - $$ = $1; + $$.bval = $1; } ; @@ -1085,14 +1096,17 @@ block : block COLONCOLON name { std::string copy = copy_name ($3); struct symbol *tem - = lookup_symbol (copy.c_str (), $1, + = lookup_symbol (copy.c_str (), $1.bval, SEARCH_FUNCTION_DOMAIN, nullptr).symbol; if (tem == nullptr) error (_("No function \"%s\" in specified context."), copy.c_str ()); - $$ = tem->value_block (); } + $$.bval = tem->value_block (); + $$.has_namespace = $1.has_namespace; + $$.namespace_val = $1.namespace_val; + } ; variable: name_not_typename ENTRY @@ -1112,7 +1126,7 @@ variable: block COLONCOLON name { std::string copy = copy_name ($3); struct block_symbol sym - = lookup_symbol (copy.c_str (), $1, + = lookup_symbol (copy.c_str (), $1.bval, SEARCH_VFT, NULL); if (sym.symbol == 0) @@ -1123,6 +1137,24 @@ variable: block COLONCOLON name pstate->push_new (sym); } + | namespace COLONCOLON name + { + std::string sym_name = copy_name ($3); + + struct block_symbol bsym + = lookup_symbol_in_linker_namespace + (sym_name.c_str (), $1.val, SEARCH_VFT); + + if (bsym.symbol == NULL) + error (_("Symbol %s not found in" + " namespace [[%ld]]"), + sym_name.c_str (), $1.val); + + if (symbol_read_needs_frame (bsym.symbol)) + pstate->block_tracker->update (bsym); + + pstate->push_new (bsym); + } ; qualified_name: TYPENAME COLONCOLON name diff --git a/gdb/solib.c b/gdb/solib.c index 85ec6bb2f1e..4e2cc3d1aa5 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -48,6 +48,7 @@ #include "gdbsupport/scoped_fd.h" #include "source.h" #include "cli/cli-style.h" +#include "block.h" /* See solib.h. */ diff --git a/gdb/symtab.c b/gdb/symtab.c index 5147aee55d5..939751613a9 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -2691,6 +2691,44 @@ lookup_static_symbol (const char *name, const domain_search_flags domain) /* See symtab.h. */ +struct block_symbol +lookup_symbol_in_linker_namespace (const char *name, int nsid, + const domain_search_flags domain) +{ + struct gdbarch *gdbarch = current_inferior ()->arch (); + const solib_ops *ops = gdbarch_so_ops (gdbarch); + + if (ops->get_solibs_in_ns == nullptr) + error (_("Namespaces are not supported by the inferior.")); + + std::vector sos_in_namespace = ops->get_solibs_in_ns (nsid); + if (sos_in_namespace.size() == 0) + error (_("Namespace [[%d]] is inactive"), nsid); + + symbol_lookup_debug_printf ("lookup_symbol_in_linker_namespace (%d, %s, %s)", + nsid, name, domain_name (domain).c_str ()); + + /* We look for both global and static symbols in here. There is no reason + to pick one over the other to my knowledge, so we go alphabetical. */ + for (const solib *so : sos_in_namespace) + { + struct block_symbol bsym + = lookup_global_symbol_from_objfile (so->objfile, GLOBAL_BLOCK, + name, domain); + if (bsym.symbol != nullptr) + return bsym; + + bsym = lookup_global_symbol_from_objfile (so->objfile, STATIC_BLOCK, + name, domain); + if (bsym.symbol != nullptr) + return bsym; + } + + return {}; +} + +/* See symtab.h. */ + struct block_symbol lookup_global_symbol (const char *name, const struct block *block, diff --git a/gdb/symtab.h b/gdb/symtab.h index e547d109f35..d06c00929fe 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -2750,6 +2750,14 @@ extern struct block_symbol const char *name, const domain_search_flags domain); +/* Lookup symbol NAME from DOMAIN in the linker namespace NSID. + This generates a list of all objfiles in NSID, then searches + those objfiles for the given symbol. Searches for both global or + static symbols. */ +extern struct block_symbol + lookup_symbol_in_linker_namespace (const char *name, int nsid, + const domain_search_flags domain); + extern unsigned int symtab_create_debug; /* Print a "symtab-create" debug statement. */ -- 2.47.2