From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id HOlzA1Ux5mmipSwAWB0awg (envelope-from ) for ; Mon, 20 Apr 2026 09:59:49 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=W5mcAoQ7; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id EE38C1E067; Mon, 20 Apr 2026 09:59:48 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 031161E067 for ; Mon, 20 Apr 2026 09:59:47 -0400 (EDT) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 7A5B84D108C8 for ; Mon, 20 Apr 2026 13:59:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7A5B84D108C8 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=W5mcAoQ7 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 7BFA84BC0577 for ; Mon, 20 Apr 2026 13:59:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7BFA84BC0577 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 7BFA84BC0577 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776693554; cv=none; b=xG755ns4+/YdW1N4PUoDkNTaLdYjqxamLWJoT/jtTicAkOVW2VrG21khPOlJfEsUYzWb+trk8G7x5qP5nA7udWo9uWl1GNEy0wb+SbOOlynCy04h7pcZyaV115OAv5bX1543qs5zRB0pU5Q1wzSTfvsZE3QbjNZ2fWIrEa1bTgI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776693554; c=relaxed/simple; bh=IC3i5RAzt2zUX5XIMA61S/MFD8An7gmMX256I4JG/5w=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=DYJmvDi19kiXahIIYALkA0C5XwUbL4h1k3BxafTQ92L7HVKT74jRyufVLFbVKfuVyGAt8X8RaTkHNyEeNbCSOMeuhFG2Hd9CNxWUCslfAKhgNRQI5aFE+WxJPWxu86KZrJHY4C+fiaHMz+zGLqI4ji93bVzJLZpKp1WqEHurdAc= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7BFA84BC0577 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776693554; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=wdLbKvCN08zQplSoYv168rXn1vjC5o+DT4EXXF98xpY=; b=W5mcAoQ7Vma045OFJGA+j1pKj99HOXISlNPNULPk0pA5YN+pP3F8rPVG39jGJ34ROzvkUY ib7IcTnG7y1oP9wW+EM0MSOXlKS7/wJI1aVtGw7M7Pqc+CygUnCw/TWlWZu9KWjm2QQpQO jxUPwNCefZrnY5pQychp/lRqoT4/n0Y= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-156-aVfBUXC8Ms-sQ2XGvQ2MLw-1; Mon, 20 Apr 2026 09:59:11 -0400 X-MC-Unique: aVfBUXC8Ms-sQ2XGvQ2MLw-1 X-Mimecast-MFC-AGG-ID: aVfBUXC8Ms-sQ2XGvQ2MLw_1776693550 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-488c16958e9so23279105e9.1 for ; Mon, 20 Apr 2026 06:59:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776693549; x=1777298349; h=mime-version:message-id:date:references:in-reply-to:subject:cc:to :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=wdLbKvCN08zQplSoYv168rXn1vjC5o+DT4EXXF98xpY=; b=f/fImnOtf9KeJFu4T5/ys80tfZUbJafk+4kcCaMPWg/cZE/iFlHbXeWx6JGNhds2Fc l8HT5zdel3fpb5WGiBWcHyNpOV/e9Z5fB7jyVTmiSk9ulHJLdjVlLJoF3Ak9TjtSLtNM rLkKgoO66kuq0aaLXW81iAxU5ZPJM9hoj7qYINOWu3oO36cV6ynNIrW7wB8UpozyjQ45 2sxybkXqF8CTDXuymQw0+/ez/T4Hz9ufxKxPAKq7kGS1YmFCpQDtll8UvXcUfvqxMi3K 3N6ELLc15B/d5arIOntbRqmx3FfMU2zqfxp/E8skXA0RvPdnpAaqc/4zywPLbK1m4k/X ut9w== X-Forwarded-Encrypted: i=1; AFNElJ+VotRSXkx2UYLf0BvWjC9mEVOdna0jAU0ruWpFGikIEtTZjNNwUV5Brx2oi63b6gDn0WwV9gNuwp1adw==@sourceware.org X-Gm-Message-State: AOJu0YwaD9nEjdulB58Pp3H3u/aToYC84w9B5FRlAMrfJzJh6Kv4N6Gc ZrSEt9LyQOiuNGnG0YDClSEZWKP2XCOTI9u6GrcWeIhAjYD4w0nlfYXYp9OuM1AE9feLgEeQ0Cz URWTqfd4AhHqUUoql8lTWl0Lf6AKLLSsmCoFpv5lKbvFk3tTBG8chTFmCZcrhkXd3yB/NfAE= X-Gm-Gg: AeBDieuioAGnnQSbRrdgTTqNtmW3J2508u12tcJU93S8T1XAkYKIrw1PWls2PtC3IjA NR2JMbDCcdvFAYOymo1LTjkh2iLZ0sBsE0fInKpaNn7DfTg482n3l2LAyWSwyl/AAoTNQA4I0qf LaYUbFWeegiQaW497XHBOCbzYe792qZJn+IqIoWDPYhtKyKswIw/PAHLz/+k36Qus5l5vFM1EY/ ElJ8lrHL5n8+5ZTHkFzkcVrPz538LP/p38DFIX2bWVMwRdNQcxMbPbrNSZXo0fnt7vpgcaGHLgv AS4iWNYavRMnvE/qQAsIwVKvcQJIkWv6+Pphn+xWh+fl/pTBvaPgjWCyTUogVf6X4qbkby8TQEs LsQyTq/kzreSCLt3UTgeXVaQZIoQ= X-Received: by 2002:a05:600c:4e4f:b0:488:a2ac:a34c with SMTP id 5b1f17b1804b1-488fb7433ddmr197510775e9.12.1776693548837; Mon, 20 Apr 2026 06:59:08 -0700 (PDT) X-Received: by 2002:a05:600c:4e4f:b0:488:a2ac:a34c with SMTP id 5b1f17b1804b1-488fb7433ddmr197510015e9.12.1776693548026; Mon, 20 Apr 2026 06:59:08 -0700 (PDT) Received: from localhost ([31.111.84.232]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488fc0b4c85sm279811045e9.0.2026.04.20.06.59.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 Apr 2026 06:59:07 -0700 (PDT) From: Andrew Burgess To: Guinevere Larsen , gdb-patches@sourceware.org Cc: Guinevere Larsen , Eli Zaretskii Subject: Re: [PATCH v6 2/3] gdb: Make the parser recognize the [[N]] syntax for variables In-Reply-To: <20251029125831.2102647-3-guinevere@redhat.com> References: <20251029125831.2102647-1-guinevere@redhat.com> <20251029125831.2102647-3-guinevere@redhat.com> Date: Mon, 20 Apr 2026 14:59:06 +0100 Message-ID: <87y0ih3f85.fsf@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: ee0LKriMtbLfDPw4wWpua3802uoJEpmRM1XTcdVA89A_1776693550 X-Mimecast-Originator: redhat.com Content-Type: text/plain X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org Guinevere Larsen writes: > This commit adds a couple new rules to the YACC parser, that will allow > GDB to recognize expressions like [[N]]::var. > > This new syntax reuses the existing rules for searching for "block"s, > because it allows, with minimal changes to the .y file as a whole, while > also allowing [[N]]::function::symbol work. Notably, [[N]]::'file.c'::var > does not work yet, as this code change is also involved and would pollute > the current commit, so will be done in a separate one in the same series. > > To restrict the search to a desired namespace, a new function is > introduced, lookup_symbol_in_linker_namespace. This function will only > perform the symbol lookup in the objfiles that belong to the requested > namespace. > > This commit also changes the error message when "print var" if "var" is > only present in namespaces other than the current one. Before this commit, > lookup_minimal_symbol would find them as "external" symbols with > incomplete information - outputting " has incomplete > information, cast it to it's defined type." - which could be confusing for typo: "cast it to its defined type". I went to check if the original error message contained the same error. It doesn't, but not does it match what you quote. I think this is the error you are referencing, from typeprint.c: void error_unknown_type (const char *sym_print_name) { error (_("'%s' has unknown type; cast it to its declared type"), sym_print_name); } > the users. This commit changes the parser rule "variable: name_not_typename" > so that, if multiple namespaces are active, we'll look for minimal symbols > only in the current namespace. > > Known limitations: > * When using [[N]]::foo::var, if that specific foo version is not on the > stack, the error will be unable to include the linker namespace > requested. So if a user sees "foo" in the stack this could be > confusing, but it should be mitigated when a future patch adds the > namespace ID to the backtrace where applicable. > * Completion is not supported. That's because the function used to > complete symbols expects only text in the form "file.c:symbol", so > can't handle the double colon. This isn't unique to linker > namespaces, though, since func::var will also not complete, it is just > a quirk of how :: completion work at this point. > * The expression that parses [[N]] only takes an integer. That's > because there aren't many expressions that would make sense in there, > and the work of accepting an arbitrary expression felt too much for > little gain. > > Reviewed-By: Eli Zaretskii > --- > gdb/NEWS | 6 + > gdb/c-exp.y | 72 ++++++++--- > gdb/doc/gdb.texinfo | 6 + > gdb/minsyms.c | 124 ++++++++++++------- > gdb/minsyms.h | 8 ++ > gdb/parser-defs.h | 7 ++ > gdb/symtab.c | 37 ++++++ > gdb/symtab.h | 8 ++ > gdb/testsuite/gdb.base/dlmopen-ns-ids-lib.c | 14 +++ > gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c | 3 + > gdb/testsuite/gdb.base/dlmopen-ns-ids.exp | 53 ++++++++ > 11 files changed, 274 insertions(+), 64 deletions(-) > > diff --git a/gdb/NEWS b/gdb/NEWS > index 097d8da350b..273bd400f1b 100644 > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -227,6 +227,12 @@ info threads [-gid] [-stopped] [-running] [ID]... > These new flags can be useful to get a reduced list when there is a > large number of threads. > > +print > + The print command now accepts the following syntax to print values > + from a specific linker namespace: `[[N]]::foo'. N is the namespace > + identifier as understood by GDB. > + > + Double blank line. > * GDB-internal Thread Local Storage (TLS) support > > ** Linux targets for the x86_64, aarch64, ppc64, s390x, and riscv > diff --git a/gdb/c-exp.y b/gdb/c-exp.y > index 9f1cb1b2e2a..cb70bf3c863 100644 > --- a/gdb/c-exp.y > +++ b/gdb/c-exp.y > @@ -173,7 +173,7 @@ using namespace expr; > struct ttype tsym; > struct symtoken ssym; > int voidval; > - const struct block *bval; > + struct bval_type bval; > enum exp_opcode opcode; > > struct stoken_vector svec; > @@ -261,6 +261,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); > %token TYPEOF > %token DECLTYPE > %token TYPEID > +%token DOUBLESQUAREOPEN DOUBLESQUARECLOSE > > /* Special type cases, put in to allow the parser to distinguish different > legal basetypes. */ > @@ -1056,30 +1057,42 @@ exp : FALSEKEYWORD > > block : BLOCKNAME > { > - if ($1.sym.symbol) > - $$ = $1.sym.symbol->value_block (); > - else > + if ($1.sym.symbol == nullptr) > error (_("No file or function \"%s\"."), > copy_name ($1.stoken).c_str ()); > + $$.search_namespace = false; > + $$.b_val = $1.sym.symbol->value_block (); > } > | FILENAME > { > $$ = $1; > } > + | DOUBLESQUAREOPEN INT DOUBLESQUARECLOSE > + { > + $$.search_namespace = true; > + $$.namespace_val = $2.val; Totally trivial issue, but the indentation here is different to at least everything in this 'block' rule, you use TABS + 4 whitespace, while everything else uses TABS + 2 whitespace. Would be nice to be consistent. > + } > ; > > block : block COLONCOLON name > { > std::string copy = copy_name ($3); > - struct symbol *tem > - = lookup_symbol (copy.c_str (), $1, > - SEARCH_FUNCTION_DOMAIN, > - nullptr).symbol; > + struct block_symbol tem; > > - if (tem == nullptr) > + if ($1.search_namespace) > + tem = lookup_symbol_in_linker_namespace > + (copy.c_str (), $1.namespace_val, SEARCH_FUNCTION_DOMAIN); lookup_symbol_in_linker_namespace takes an 'int' for the namespace-id, but namespace_val is LONGEST. I suspect namespace_val needs to be LONGEST as it gets it value from an INT token, whose value is a LONGEST. But we should really have a check prior to the lookup_symbol_in_linker_namespace call that we're not narrowing the value in a meaningful way. Or just change the namespace-id argument to LONGEST throughout maybe? Either will work. > + else > + tem = lookup_symbol (copy.c_str (), $1.b_val, > + SEARCH_FUNCTION_DOMAIN, > + nullptr); > + > + if (tem.symbol == nullptr) > error (_("No function \"%s\" in specified context."), > copy.c_str ()); > - $$ = tem->value_block (); } > + $$.b_val = tem.symbol->value_block (); > + $$.search_namespace = false; > + } > ; > > variable: name_not_typename ENTRY > @@ -1098,9 +1111,15 @@ variable: name_not_typename ENTRY > variable: block COLONCOLON name > { > std::string copy = copy_name ($3); > - struct block_symbol sym > - = lookup_symbol (copy.c_str (), $1, > - SEARCH_VFT, NULL); > + struct block_symbol sym; > + > + if ($1.search_namespace) > + sym = lookup_symbol_in_linker_namespace > + (copy.c_str (), $1.namespace_val, > + SEARCH_VFT); > + else > + sym = lookup_symbol (copy.c_str (), $1.b_val, > + SEARCH_VFT, NULL); > > if (sym.symbol == 0) > error (_("No symbol \"%s\" in specified context."), > @@ -1196,13 +1215,25 @@ variable: name_not_typename > { > std::string arg = copy_name ($1.stoken); > > - bound_minimal_symbol msymbol > - = lookup_minimal_symbol (current_program_space, arg.c_str ()); > + int active_linker_nss > + = solib_linker_namespace_count > + (current_program_space); > + bound_minimal_symbol msymbol; > + > + if (active_linker_nss > 1) > + msymbol = lookup_minimal_symbol_in_linker_namespace > + (current_program_space, arg.c_str ()); > + else > + msymbol = lookup_minimal_symbol > + (current_program_space, arg.c_str ()); > if (msymbol.minsym == NULL) > { > if (!have_full_symbols (current_program_space) > && !have_partial_symbols (current_program_space)) > error (_("No symbol table is loaded. Use the \"file\" command.")); > + else if (active_linker_nss > 1) > + error (_("No symbol \"%s\" in the current linker namespace."), > + arg.c_str ()); > else > error (_("No symbol \"%s\" in current context."), > arg.c_str ()); > @@ -2540,7 +2571,9 @@ static const struct c_token tokentab2[] = > {"!=", NOTEQUAL, OP_NULL, 0}, > {"<=", LEQ, OP_NULL, 0}, > {">=", GEQ, OP_NULL, 0}, > - {".*", DOT_STAR, OP_NULL, FLAG_CXX} > + {".*", DOT_STAR, OP_NULL, FLAG_CXX}, > + {"[[", DOUBLESQUAREOPEN, OP_NULL, 0}, > + {"]]", DOUBLESQUARECLOSE, OP_NULL, 0}, > }; > > /* Identifier-like tokens. Only type-specifiers than can appear in > @@ -3143,8 +3176,9 @@ classify_name (struct parser_state *par_state, const struct block *block, > if (auto symtab = lookup_symtab (current_program_space, copy.c_str ()); > symtab != nullptr) > { > - yylval.bval > + yylval.bval.b_val > = symtab->compunit ()->blockvector ()->static_block (); > + yylval.bval.search_namespace = false; > > return FILENAME; > } > @@ -3394,7 +3428,7 @@ yylex (void) > name_obstack.clear (); > checkpoint = 0; > if (current.token == FILENAME) > - search_block = current.value.bval; > + search_block = current.value.bval.b_val; > else if (current.token == COLONCOLON) > search_block = NULL; > else > @@ -3577,7 +3611,7 @@ c_print_token (FILE *file, int type, YYSTYPE value) > break; > > case FILENAME: > - parser_fprintf (file, "bval<%s>", host_address_to_string (value.bval)); > + parser_fprintf (file, "bval<%s>", host_address_to_string (value.bval.b_val)); > break; > } > } > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > index 821f3ed4b05..b48f70d2250 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -10686,6 +10686,12 @@ you can choose a different format by specifying @samp{/@var{f}}, where > @var{f} is a letter specifying the format; see @ref{Output Formats,,Output > Formats}. > > +Additionally, if the inferior supports linker namespaces, @value{GDBN} > +has implemented the following syntax to allow users to resolve symbols > +to a specific namespace: @code{[[@var{n}]]::@var{symbol}}. Here @var{n} > +is @value{GDBN}'s namespace identifier, which may be different from the > +inferior's identifier. Instead of @code{...} I think a better choice would be @samp{...} here. My understanding is that @code would be for actual programming language code. > + > @anchor{print options} > The @code{print} command supports a number of options that allow > overriding relevant global print settings as set by @code{set print} > diff --git a/gdb/minsyms.c b/gdb/minsyms.c > index 7e4f47b8c3f..a73d4f21858 100644 > --- a/gdb/minsyms.c > +++ b/gdb/minsyms.c > @@ -335,7 +335,10 @@ lookup_minimal_symbol_demangled (const lookup_name_info &lookup_name, > } > } > > -/* Look through all the current minimal symbol tables and find the > +/* Main implementation for the lookup_minimal_symbol function. > + Receives a list of objfiles in which to look for the symbol. > + > + Look through all the current minimal symbol tables and find the > first minimal symbol that matches NAME. If OBJF is non-NULL, limit > the search to that objfile. If SFILE is non-NULL, the only file-scope > symbols considered will be from that source file (global symbols are > @@ -355,9 +358,9 @@ lookup_minimal_symbol_demangled (const lookup_name_info &lookup_name, > Obviously, there must be distinct mangled names for each of these, > but the demangled names are all the same: S::S or S::~S. */ > > -bound_minimal_symbol > -lookup_minimal_symbol (program_space *pspace, const char *name, objfile *objf, > - const char *sfile) > +static bound_minimal_symbol > +lookup_minimal_symbol_in_objfiles (std::vector objfile_list, > + const char *name, const char *sfile) > { > found_minimal_symbols found; > > @@ -373,53 +376,48 @@ lookup_minimal_symbol (program_space *pspace, const char *name, objfile *objf, > > lookup_name_info lookup_name (name, symbol_name_match_type::FULL); > > - for (objfile &objfile : pspace->objfiles ()) > + for (objfile *objfile : objfile_list) > { > if (found.external_symbol.minsym != NULL) > break; > > - if (objf == NULL || objf == &objfile > - || objf == objfile.separate_debug_objfile_backlink) > + symbol_lookup_debug_printf ("lookup_minimal_symbol (%s, %s, %s)", > + name, sfile != NULL ? sfile : "NULL", > + objfile_debug_name (objfile)); > + > + /* Do two passes: the first over the ordinary hash table, > + and the second over the demangled hash table. */ > + lookup_minimal_symbol_mangled (name, sfile, objfile, > + objfile->per_bfd->msymbol_hash, > + mangled_hash, mangled_cmp, found); > + > + /* If not found, try the demangled hash table. */ > + if (found.external_symbol.minsym == NULL) > { > - symbol_lookup_debug_printf ("lookup_minimal_symbol (%s, %s, %s, %s)", > - host_address_to_string (pspace), > - name, sfile != NULL ? sfile : "NULL", > - objfile_debug_name (&objfile)); > - > - /* Do two passes: the first over the ordinary hash table, > - and the second over the demangled hash table. */ > - lookup_minimal_symbol_mangled (name, sfile, &objfile, > - objfile.per_bfd->msymbol_hash, > - mangled_hash, mangled_cmp, found); > - > - /* If not found, try the demangled hash table. */ > - if (found.external_symbol.minsym == NULL) > + /* Once for each language in the demangled hash names > + table (usually just zero or one languages). */ > + for (unsigned iter = 0; iter < nr_languages; ++iter) > { > - /* Once for each language in the demangled hash names > - table (usually just zero or one languages). */ > - for (unsigned iter = 0; iter < nr_languages; ++iter) > - { > - if (!objfile.per_bfd->demangled_hash_languages.test (iter)) > - continue; > - enum language lang = (enum language) iter; > - > - unsigned int hash > - = (lookup_name.search_name_hash (lang) > - % MINIMAL_SYMBOL_HASH_SIZE); > - > - symbol_name_matcher_ftype *match > - = language_def (lang)->get_symbol_name_matcher > - (lookup_name); > - struct minimal_symbol **msymbol_demangled_hash > - = objfile.per_bfd->msymbol_demangled_hash; > - > - lookup_minimal_symbol_demangled (lookup_name, sfile, &objfile, > - msymbol_demangled_hash, > - hash, match, found); > - > - if (found.external_symbol.minsym != NULL) > - break; > - } > + if (!objfile->per_bfd->demangled_hash_languages.test (iter)) > + continue; > + enum language lang = (enum language) iter; > + > + unsigned int hash > + = (lookup_name.search_name_hash (lang) > + % MINIMAL_SYMBOL_HASH_SIZE); > + > + symbol_name_matcher_ftype *match > + = language_def (lang)->get_symbol_name_matcher > + (lookup_name); > + struct minimal_symbol **msymbol_demangled_hash > + = objfile->per_bfd->msymbol_demangled_hash; > + > + lookup_minimal_symbol_demangled (lookup_name, sfile, objfile, > + msymbol_demangled_hash, > + hash, match, found); > + > + if (found.external_symbol.minsym != NULL) > + break; > } > } > } > @@ -472,6 +470,42 @@ lookup_minimal_symbol (program_space *pspace, const char *name, objfile *objf, > return {}; > } > > +/* See minsyms.h. */ > + > +bound_minimal_symbol > +lookup_minimal_symbol (program_space *pspace, const char *name, objfile *objf, > + const char *sfile) > +{ > + std::vector search_objfiles; > + if (objf != nullptr) > + { > + search_objfiles.push_back (objf); > + if (objf->separate_debug_objfile_backlink != nullptr) > + search_objfiles.push_back (objf->separate_debug_objfile_backlink); There's a change in behaviour here. If we imagine that objfile A has a separate_debug_objfile of B. The previous code looped over every objfile and did: if (objf == NULL || objf == &objfile || objf == objfile.separate_debug_objfile_backlink) // Include this objfile. If OBJF was 'A' then we would include both 'A' and 'B' as B's backlink points at 'A'. However, the new code does: search_objfiles.push_back (objf); if (objf->separate_debug_objfile_backlink != nullptr) search_objfiles.push_back (objf->separate_debug_objfile_backlink); So if we pass 'A' then we include 'A', but A's backlink will be NULL, so we'll not search 'B'. Due to this flipping of the logic, then if we pass 'B' then under the old scheme we'd only include 'B', but under the new scheme we include both 'A' and 'B'. This change of behaviour wasn't called out in the commit message, so I'm assuming this might be a mistake. > + } > + else > + { > + for (objfile &objfile : pspace->objfiles ()) > + search_objfiles.push_back (&objfile); > + } > + > + return lookup_minimal_symbol_in_objfiles (search_objfiles, name, sfile); > +} > + > +/* See minsyms.h. */ > + > +bound_minimal_symbol > +lookup_minimal_symbol_in_linker_namespace (program_space *pspace, > + const char *name) > +{ > + LONGEST curr_namespace; > + get_internalvar_integer (lookup_internalvar ("_linker_namespace"), > + &curr_namespace); Rather than reading the internal variable, would it not be better to have a helper function in solib.{c,h} which returns the current namespace-id, then have the internal variable and this code just call that? > + return lookup_minimal_symbol_in_objfiles > + (get_objfiles_in_linker_namespace (curr_namespace, pspace), > + name, nullptr); > +} > + > /* See gdbsupport/symbol.h. */ > > int > diff --git a/gdb/minsyms.h b/gdb/minsyms.h > index 4aa8a428470..f2ba15d9318 100644 > --- a/gdb/minsyms.h > +++ b/gdb/minsyms.h > @@ -211,6 +211,14 @@ bound_minimal_symbol lookup_minimal_symbol (program_space *pspace, > objfile *obj = nullptr, > const char *sfile = nullptr); > > +/* Same as above, but only look for a minimal symbol in the objfiles that > + belong to the current linker namespace. This function is only meant to > + be called when attempting to resolve a symbol from a user command, and > + there are multiple linker namespaces available to resolve it in. */ > + > +bound_minimal_symbol lookup_minimal_symbol_in_linker_namespace > + (program_space *pspace, const char *name); > + > /* Look through all the minimal symbol tables in PSPACE and find the > first minimal symbol that matches NAME and has text type. If OBJF > is non-NULL, limit the search to that objfile. Returns a bound > diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h > index f5618f3a9ce..ff4ab6a09de 100644 > --- a/gdb/parser-defs.h > +++ b/gdb/parser-defs.h > @@ -358,6 +358,13 @@ struct ttype > struct type *type; > }; > > +struct bval_type > + { > + bool search_namespace; > + const struct block *b_val; > + LONGEST namespace_val; > + }; I know there are plenty of (older) structures in here that are missing comments, but there are also some, e.g. stoken, typed_stoken, that do have comments. I think it would be better if new code did comment the structures that are added. > + > struct symtoken > { > struct stoken stoken; > diff --git a/gdb/symtab.c b/gdb/symtab.c > index 786dd9f56ba..d237a5cc5d2 100644 > --- a/gdb/symtab.c > +++ b/gdb/symtab.c > @@ -2558,6 +2558,43 @@ 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) > +{ > + if (!current_program_space->solib_ops ()->supports_namespaces ()) > + error (_("Linker namespaces are not supported by the inferior.")); > + > + std::vector objfiles_in_namespace > + = get_objfiles_in_linker_namespace (nsid, current_program_space); > + > + if (objfiles_in_namespace.size() == 0) Missing space before '()'. > + 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. */ I find the whole alphabetical thing a bit weird. I'd just say: /* We look for both global and static symbols in here, the order is arbitrary. */ But if you prefer your wording then that's fine too I guess. > + for (objfile *objf : objfiles_in_namespace) > + { > + struct block_symbol bsym > + = lookup_global_symbol_from_objfile (objf, GLOBAL_BLOCK, > + name, domain); > + if (bsym.symbol != nullptr) > + return bsym; > + > + bsym = lookup_global_symbol_from_objfile (objf, STATIC_BLOCK, > + name, domain); > + if (bsym.symbol != nullptr) > + return bsym; > + } When looking at this function, I started looking in c-exp.y, and in here we see that the two paths are lookup_symbol_in_linker_namespace or lookup_symbol, so when I reviewed this function I was comparing against lookup_symbol. lookup_symbol calls lookup_symbol_in_language, which uses demangle_for_lookup to demangle and canonicalize the string being searched for. But lookup_symbol_in_linker_namespace doesn't call this function. Isn't that going to be a problem? After demangle_for_lookup lookup_symbol_in_language calls lookup_symbol_aux to do the actual lookup. This function does a bunch of local symbol lookup, which we probably don't need for the namespace searching path, but then does: /* Now do whatever is appropriate for LANGUAGE to look up static and global variables. */ result = langdef->lookup_symbol_nonlocal (name, block, domain); to lookup the global/static symbols, this does a bunch of language specific stuff, especially for e.g. C++. Yet lookup_symbol_in_linker_namespace doesn't call this, it just goes direct to the global/static block and looks for an exact match. Are there issues here? Or is there something that I'm missing. If this is a limitation then maybe this should be documented somewhere? > + > + 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 e47033efd01..fe2304acb4f 100644 > --- a/gdb/symtab.h > +++ b/gdb/symtab.h > @@ -2737,6 +2737,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. */ > diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids-lib.c b/gdb/testsuite/gdb.base/dlmopen-ns-ids-lib.c > index 86cbb0f4e38..cc35ce0080e 100644 > --- a/gdb/testsuite/gdb.base/dlmopen-ns-ids-lib.c > +++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids-lib.c > @@ -26,3 +26,17 @@ inc (int n) > int amount = gdb_dlmopen_glob; > return n + amount; /* bp.inc. */ > } > + > +static int > +change_global (int n) > +{ > + gdb_dlmopen_glob += n; > + return n; > +} > + > +__attribute__((visibility ("default"))) > +int > +func_with_other_call (int n) > +{ > + return change_global (n + 1); > +} > diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c b/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c > index c7c038a08d1..459ae547842 100644 > --- a/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c > +++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c > @@ -47,6 +47,9 @@ main (void) > fun (dl); > } > > + fun = dlsym (handle[0], "func_with_other_call"); > + fun (0); > + > dlclose (handle[0]); /* TAG: first dlclose */ > dlclose (handle[1]); /* TAG: second dlclose */ > dlclose (handle[2]); /* TAG: third dlclose */ > diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp > index f3bdfb054d9..fec7adb5317 100644 > --- a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp > +++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp > @@ -123,6 +123,10 @@ proc get_first_so_ns {} { > return $ns > } > > +proc ns_id_for_command {ns} { > + return "\[\[$ns\]\]" > +} > + > # Run the tests relating to the command "info sharedlibrary", to > # verify that the namespace ID is consistent. > proc test_info_shared {} { > @@ -315,6 +319,55 @@ proc test_info_linker_namespaces {} { > ".*" ] "print namespaces with no argument" > } > > +# Test that we can use the [[N]]::symbol syntax, and it's variations > +# like [[N]]::func::symbol. typo: "and its variations like..." Thanks, Andrew > +proc_with_prefix test_print_namespace_symbol {} { > + clean_restart > + gdb_load $::binfile > + > + set ns1 [ns_id_for_command 1] > + set ns2 [ns_id_for_command 2] > + > + if { ![runto_main] } { > + return > + } > + > + gdb_breakpoint [gdb_get_line_number "TAG: first dlclose"] > + gdb_breakpoint "change_global" allow-pending > + > + # Test printing variables for non-existent namespace. > + gdb_test "print ${ns1}::gdb_dlmopen_glob" "Namespace ..1.. is inactive" \ > + "Before loading namespaces" > + > + gdb_continue_to_breakpoint "change_global" > + > + # Test finding location of variables. > + gdb_test "print ${ns1}::gdb_dlmopen_glob" ".* = 0" "before changing" > + gdb_test_no_output "set ${ns1}::gdb_dlmopen_glob = 1" > + gdb_test "print ${ns1}::gdb_dlmopen_glob" ".* = 1" "after changing" > + gdb_test "print ${ns2}::gdb_dlmopen_glob" ".* = 0" "other namespace" > + > + gdb_test "print gdb_dlmopen_glob" ".* = 1" "changed the right variable" > + > + # Test finding functions in specific namespaces. > + gdb_test "print ${ns1}::inc (2)" ".* = 3" > + gdb_test "print ${ns2}::inc (2)" ".* = 2" > + > + # Test finding a specific block in the backtrace. > + gdb_test "print n" ".* = 1" > + gdb_test "print ${ns1}::func_with_other_call::n" ".* = 0" > + gdb_test "print ${ns2}::func_with_other_call::n" \ > + "No frame is currently executing in block func_with_other_call." > + > + # Leave to default namespace. > + gdb_continue_to_breakpoint "TAG: first dlclose" > + # This global doesn't exist in the default namespace. Rather than > + # returning a random one, we just say we didn't find one. > + gdb_test "print gdb_dlmopen_glob" \ > + "No symbol .gdb_dlmopen_glob. in the current linker namespace." > +} > + > test_info_shared > test_conv_vars > test_info_linker_namespaces > +test_print_namespace_symbol > -- > 2.51.0