Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Guinevere Larsen <guinevere@redhat.com>
To: Andrew Burgess <aburgess@redhat.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH v6 3/3] gdb: extend the [[N]]::foo syntax for files
Date: Tue, 28 Apr 2026 17:20:11 -0300	[thread overview]
Message-ID: <362da4a2-fd80-48f0-8eea-79365b77a008@redhat.com> (raw)
In-Reply-To: <87v7dl3brm.fsf@redhat.com>

On 4/20/26 12:13 PM, Andrew Burgess wrote:
> Guinevere Larsen <guinevere@redhat.com> writes:
>
>> This commit implements the missing support for [[N]]::'file.c'::var
>> syntax that was skipped on the previous commit.
>>
>> This is done by adding a new value to the global parser_state, so that
>> the classify_name function can restrict its search for file names to the
>> specified linker namespace.  It had to be done this way because if the
>> logic was contained on the newly added "block: block COLONCOLON
>> FILENAME" rule, we would not have the name to rerun the search.
> Did you consider adding the filename to the <whatever> type such that it
> was available within the rule to allow for the filename to be re-looked
> up?
>
> I'd be interested to know if this was tried, why this was worse than
> pushing parser state back to the lexer, which I always thought was not a
> great design.
I can't remember having tried it, so I'll explore this option and report 
back.
>>                                                                   Because
>> of that, the new rule only exists to make sure this is only used in the
>> intended syntax.  This commit also adds a link to the solib_ops relevant
>> to the expression being parsed, as a way to identify if linker
>> namespaces are supported; this could be achieved by guarding the search
>> functions instead, but I think that this is more reliable.
>>
>> The new rule uses "block" rather than a linker namespace specific token,
>> because if we allowed that token to also reduce into block, the new rule
>> would never be triggered as the simple reduction would be preferred. If
>> we didn't allow the linker namespace to reduce into block, the rest of
>> the syntaxes for [[N]]::foo would be more involved, so the option in
>> this commit seemed like the simplest solution.
>>
>> The rule "block: block COLONCOLON name" also had to be updated because,
>> if a user tried to search for a file not present in the linker
>> namespace, GDB would miscategorize it to 'name' instead of 'filename',
>> and if no function of the same name was found, the error would only say
>> "No function \"foo\" (...)" which could confuse a user. The new error
>> says "Nothing named \"foo\" (...)" instead since it is impossible for us
>> to disambiguate between filename or function name, and both would be
>> valid in this code path.
>>
>> The parser_state changes were not used for the previous commit because
>> the lookup_symbol calls would lead to an even more intrusive change for
>> no real gain, since the search would be rerun any way. There is an
>> argument to be made that the results could be different if only
>> namespace had a type and another had a variable, but a situation where
>> that significantly changes the result is quite unlikely, I think.
>> ---
>>   gdb/c-exp.y                               | 18 +++++++++++--
>>   gdb/linespec.c                            |  4 +--
>>   gdb/parse.c                               |  3 ++-
>>   gdb/parser-defs.h                         | 32 +++++++++++++++++++++--
>>   gdb/rust-parse.c                          |  3 ++-
>>   gdb/symtab.c                              | 26 +++++++++++++-----
>>   gdb/symtab.h                              |  7 ++++-
>>   gdb/testsuite/gdb.base/dlmopen-ns-ids.exp | 12 +++++++++
>>   8 files changed, 90 insertions(+), 15 deletions(-)
>>
>> diff --git a/gdb/c-exp.y b/gdb/c-exp.y
>> index cb70bf3c863..f59aca327ed 100644
>> --- a/gdb/c-exp.y
>> +++ b/gdb/c-exp.y
>> @@ -1071,6 +1071,7 @@ block	:	BLOCKNAME
>>   			{
>>   			    $$.search_namespace = true;
>>   			    $$.namespace_val = $2.val;
>> +			    pstate->set_linker_namespace ($2.val);
>>   			}
>>   	;
>>   
>> @@ -1087,12 +1088,24 @@ block	:	block COLONCOLON name
>>   						 SEARCH_FUNCTION_DOMAIN,
>>   						 nullptr);
>>   
>> -			  if (tem.symbol == nullptr)
>> +			  if (tem.symbol == nullptr && !$$.search_namespace)
>>   			    error (_("No function \"%s\" in specified context."),
>>   				   copy.c_str ());
>> +			  else if (tem.symbol == nullptr && $$.search_namespace)
> My yacc foo is weak, but isn't '$$' the rule's output?  Which is only
> being set below.  Shouldn't this be $1 maybe?  If there's not some
> reason why search_namespace is being set to the correct value (that I'm
> missing) then this would seem to indicate that there's a gap in the
> testing here.
You're right, this must ave slipped past me at some point, thanks!
>
>> +			    /* COPY can be a function or a file.  There is no way
>> +			       to identify which the user intended, so emit a
>> +			       generic warning instead.  */
>> +			    error (_("Nothing named \"%s\" in specified context."),
>> +				   copy.c_str ());
>>   			  $$.b_val = tem.symbol->value_block ();
>>   			  $$.search_namespace = false;
>>   			}
>> +	|	block COLONCOLON FILENAME
>> +			{
>> +			    if (!$1.search_namespace)
>> +				error (_("Filename must be the first part of the expression"));
>> +			    $$ = $3;
>> +			}
>>   	;
>>   
>>   variable:	name_not_typename ENTRY
>> @@ -3173,7 +3186,8 @@ classify_name (struct parser_state *par_state, const struct block *block,
>>   	  || is_quoted_name)
>>   	{
>>   	  /* See if it's a file name. */
>> -	  if (auto symtab = lookup_symtab (current_program_space, copy.c_str ());
>> +	  if (auto symtab = lookup_symtab (current_program_space, copy.c_str (),
>> +					   par_state->get_linker_namespace ());
>>   	      symtab != nullptr)
>>   	    {
>>   	      yylval.bval.b_val
>> diff --git a/gdb/linespec.c b/gdb/linespec.c
>> index 08f7fdd0daa..ec90ad4826a 100644
>> --- a/gdb/linespec.c
>> +++ b/gdb/linespec.c
>> @@ -3633,11 +3633,11 @@ collect_symtabs_from_filename (const char *file,
>>   	  if (pspace->executing_startup)
>>   	    continue;
>>   
>> -	  iterate_over_symtabs (pspace, file, collector);
>> +	  iterate_over_symtabs (pspace, file, -1, collector);
>>   	}
>>       }
>>     else
>> -    iterate_over_symtabs (search_pspace, file, collector);
>> +    iterate_over_symtabs (search_pspace, file, -1, collector);
>>   
>>     /* It is tempting to use the unordered_dense 'extract' method here,
>>        and remove the separate vector -- but it's unclear if ordering
>> diff --git a/gdb/parse.c b/gdb/parse.c
>> index d76768f41d7..7358c369d52 100644
>> --- a/gdb/parse.c
>> +++ b/gdb/parse.c
>> @@ -420,7 +420,8 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
>>   
>>     parser_state ps (lang, get_current_arch (), expression_context_block,
>>   		   expression_context_pc, flags, *stringptr,
>> -		   completer != nullptr, tracker);
>> +		   completer != nullptr, tracker,
>> +		   current_program_space->solib_ops ());
>>   
>>     scoped_restore_current_language lang_saver (lang->la_language);
>>   
>> diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
>> index ff4ab6a09de..c0be1083f66 100644
>> --- a/gdb/parser-defs.h
>> +++ b/gdb/parser-defs.h
>> @@ -26,6 +26,7 @@
>>   #include "expression.h"
>>   #include "symtab.h"
>>   #include "expop.h"
>> +#include "solib.h"
>>   
>>   struct block;
>>   struct language_defn;
>> @@ -147,7 +148,8 @@ struct parser_state : public expr_builder
>>   		parser_flags flags,
>>   		const char *input,
>>   		bool completion,
>> -		innermost_block_tracker *tracker)
>> +		innermost_block_tracker *tracker,
>> +		const solib_ops *ops)
>>       : expr_builder (lang, gdbarch),
>>         expression_context_block (context_block),
>>         expression_context_pc (context_pc),
>> @@ -157,7 +159,8 @@ struct parser_state : public expr_builder
>>         comma_terminates ((flags & PARSER_COMMA_TERMINATES) != 0),
>>         parse_completion (completion),
>>         void_context_p ((flags & PARSER_VOID_CONTEXT) != 0),
>> -      debug ((flags & PARSER_DEBUG) != 0)
>> +      debug ((flags & PARSER_DEBUG) != 0),
>> +      m_solib_ops (ops)
>>     {
>>     }
>>   
>> @@ -263,6 +266,21 @@ struct parser_state : public expr_builder
>>       push (expr::make_operation<T> (std::move (lhs), std::move (rhs)));
>>     }
>>   
>> +  void set_linker_namespace (LONGEST ns_id)
>> +  {
>> +    if (m_solib_ops == nullptr)
>> +      error (_("Linker namespaces require an active inferior"));
>> +    if (m_solib_ops->supports_namespaces ())
>> +      linker_namespace = ns_id;
>> +    else
>> +      error (_("Linker namespaces are not supported"));
>> +  }
>> +
>> +  LONGEST get_linker_namespace ()
> This can be const.
Fixed, just in case I still need to use the parser state in the lexer.
>
>> +  {
>> +    return linker_namespace;
>> +  }
>> +
>>     /* Function called from the various parsers' yyerror functions to throw
>>        an error.  The error will include a message identifying the location
>>        of the error within the current expression.  */
>> @@ -323,6 +341,16 @@ struct parser_state : public expr_builder
>>   
>>     /* Stack of operations.  */
>>     std::vector<expr::operation_up> m_operations;
>> +
>> +  /* If the expression is being restricted to a specific namespace, this is
>> +     where that information is stored for the block lookup.  It should be
>> +     accessed through setter/getters to ensure that the linker namespace is
>> +     only set when the gdbarch supports it.  */
>> +  LONGEST linker_namespace = -1;
> This should be renamed m_linker_namespace as it is private.
>
> Also, I couldn't find anything that would reset the linker namepsace
> back to -1 when parsing a complex expression.  For example, something
> like:
>
>    print [[1]]::'foo.c'::var_a + 'bar.c'::var_b
>
> After parsing the [[1]] linker_namespace will be set to '1', but is it
> ever reset?  Will we not end up parsing the "'bar.c'::var_b" as if the
> lookup had to be in namespace 1?

You're right, I think I missed it as a possibility.

Hopefully I'll be able to move away from state in the lexer, and that 
won't be a concern.

>
> Thanks,
> Andrew
>
>> +
>> +  /* Used to figure out if an inferior is capable of handling linker
>> +     namespaces at all.  */
>> +  const solib_ops *m_solib_ops;
>>   };
>>   
>>   /* A string token, either a char-string or bit-string.  Char-strings are
>> diff --git a/gdb/rust-parse.c b/gdb/rust-parse.c
>> index b740d5a7b16..27f03b23e6a 100644
>> --- a/gdb/rust-parse.c
>> +++ b/gdb/rust-parse.c
>> @@ -2315,7 +2315,8 @@ rust_lex_tests (void)
>>   {
>>     /* Set up dummy "parser", so that rust_type works.  */
>>     parser_state ps (language_def (language_rust), current_inferior ()->arch (),
>> -		   nullptr, 0, 0, nullptr, 0, nullptr);
>> +		   nullptr, 0, 0, nullptr, 0, nullptr,
>> +		   current_program_space->solib_ops ());
>>     rust_parser parser (&ps);
>>   
>>     rust_lex_test_one (&parser, "", 0);
>> diff --git a/gdb/symtab.c b/gdb/symtab.c
>> index d237a5cc5d2..bbaf94e51d0 100644
>> --- a/gdb/symtab.c
>> +++ b/gdb/symtab.c
>> @@ -618,6 +618,7 @@ compare_filenames_for_search (const char *filename, const char *search_name)
>>   
>>   void
>>   iterate_over_symtabs (program_space *pspace, const char *name,
>> +		      LONGEST linker_ns,
>>   		      gdb::function_view<bool (symtab *)> callback)
>>   {
>>     gdb::unique_xmalloc_ptr<char> real_path;
>> @@ -630,20 +631,33 @@ iterate_over_symtabs (program_space *pspace, const char *name,
>>         gdb_assert (IS_ABSOLUTE_PATH (real_path.get ()));
>>       }
>>   
>> -  for (objfile &objfile : pspace->objfiles ())
>> -    if (objfile.map_symtabs_matching_filename (name, real_path.get (),
>> -					       callback))
>> +  std::vector<objfile *> objfiles_to_search;
>> +  if (linker_ns >= 0)
>> +    {
>> +      gdb_assert (pspace->solib_ops ()->supports_namespaces ());
>> +      objfiles_to_search
>> +	= get_objfiles_in_linker_namespace (linker_ns, pspace);
>> +    }
>> +  else
>> +    {
>> +      for (objfile &objf : pspace->objfiles ())
>> +	objfiles_to_search.push_back (&objf);
>> +    }
>> +
>> +  for (objfile *objfile : objfiles_to_search)
>> +    if (objfile->map_symtabs_matching_filename (name, real_path.get (),
>> +						callback))
>>         return;
>>   }
>>   
>>   /* See symtab.h.  */
>>   
>>   symtab *
>> -lookup_symtab (program_space *pspace, const char *name)
>> +lookup_symtab (program_space *pspace, const char *name, LONGEST linker_ns)
>>   {
>>     struct symtab *result = NULL;
>>   
>> -  iterate_over_symtabs (pspace, name, [&] (symtab *symtab)
>> +  iterate_over_symtabs (pspace, name, linker_ns, [&] (symtab *symtab)
>>       {
>>         result = symtab;
>>         return true;
>> @@ -6158,7 +6172,7 @@ collect_file_symbol_completion_matches (completion_tracker &tracker,
>>   
>>     /* Go through symtabs for SRCFILE and check the externs and statics
>>        for symbols which match.  */
>> -  iterate_over_symtabs (current_program_space, srcfile, [&] (symtab *s)
>> +  iterate_over_symtabs (current_program_space, srcfile, -1, [&] (symtab *s)
>>       {
>>         add_symtab_completions (s->compunit (),
>>   			      tracker, mode, lookup_name,
>> diff --git a/gdb/symtab.h b/gdb/symtab.h
>> index fe2304acb4f..bda6e82da02 100644
>> --- a/gdb/symtab.h
>> +++ b/gdb/symtab.h
>> @@ -2079,7 +2079,8 @@ const char *multiple_symbols_select_mode (void);
>>   
>>   /* Lookup a symbol table in PSPACE by source file name.  */
>>   
>> -extern symtab *lookup_symtab (program_space *pspace, const char *name);
>> +extern symtab *lookup_symtab (program_space *pspace, const char *name,
>> +			      LONGEST linker_ns = -1);
>>   
>>   /* An object of this type is passed as the 'is_a_field_of_this'
>>      argument to lookup_symbol and lookup_symbol_in_language.  */
>> @@ -2805,10 +2806,14 @@ bool compare_glob_filenames_for_search (const char *filename,
>>      psymtabs.  *If* there is no '/' in the name, a match after a '/' in the
>>      symtab filename will also work.
>>   
>> +   If LINKER_NS is 0 or greater, only the objfiles in the provided linker
>> +   namespace will be iterated over.
>> +
>>      Call CALLBACK with each symtab that is found.  If CALLBACK returns
>>      true, the search stops.  */
>>   
>>   void iterate_over_symtabs (program_space *pspace, const char *name,
>> +			   LONGEST linker_ns,
>>   			   gdb::function_view<bool (symtab *)> callback);
>>   
>>   std::vector<const linetable_entry *> find_linetable_entries_for_symtab_line
>> diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
>> index fec7adb5317..a1e18fc39d3 100644
>> --- a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
>> +++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
>> @@ -325,9 +325,15 @@ proc_with_prefix test_print_namespace_symbol {} {
>>       clean_restart
>>       gdb_load $::binfile
>>   
>> +    set ns0 [ns_id_for_command 0]
>>       set ns1 [ns_id_for_command 1]
>>       set ns2 [ns_id_for_command 2]
>>   
>> +    # Test printing variables before starting the inferior
>> +    gdb_test "print ${ns1}::gdb_dlmopen_glob" \
>> +	"Linker namespaces require an active inferior" \
>> +	"Before starting inferior"
>> +
>>       if { ![runto_main] } {
>>   	return
>>       }
>> @@ -365,6 +371,12 @@ proc_with_prefix test_print_namespace_symbol {} {
>>       # 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."
>> +
>> +    # Minimal testing for finding files in namespaces.
>> +    gdb_test "print ${ns1}::'${::srcfile_lib}'::gdb_dlmopen_glob" \
>> +	".* = 2"
>> +    gdb_test "print ${ns0}::'${::srcfile_lib}'::gdb_dlmopen_glob" \
>> +	"Nothing named .${::srcfile_lib}. in specified context."
>>   }
>>   
>>   test_info_shared
>> -- 
>> 2.51.0


-- 
Cheers,
Guinevere Larsen
It/she


  reply	other threads:[~2026-04-28 20:20 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-29 12:58 [PATCH v6 0/3] Introduce syntax for linker-namespace specific symbols Guinevere Larsen
2025-10-29 12:58 ` [PATCH v6 1/3] gdb: make lookup_minimal_symbol_linkage work with linker namespaces Guinevere Larsen
2026-01-28 11:22   ` Andrew Burgess
2025-10-29 12:58 ` [PATCH v6 2/3] gdb: Make the parser recognize the [[N]] syntax for variables Guinevere Larsen
2026-04-20 13:59   ` Andrew Burgess
2026-04-28 19:32     ` Guinevere Larsen
2025-10-29 12:58 ` [PATCH v6 3/3] gdb: extend the [[N]]::foo syntax for files Guinevere Larsen
2026-04-20 15:13   ` Andrew Burgess
2026-04-28 20:20     ` Guinevere Larsen [this message]
2026-05-13 17:08     ` Guinevere Larsen
2025-11-27 20:30 ` [PING]Re: [PATCH v6 0/3] Introduce syntax for linker-namespace specific symbols Guinevere Larsen
2025-12-12 17:20   ` [PINGv2][PATCH " Guinevere Larsen
2026-01-06 17:17   ` Guinevere Larsen
2026-01-14 14:11     ` Guinevere Larsen
2026-03-05 12:20       ` [PINGv3][PATCH " Guinevere Larsen
2026-03-05 12:21       ` Guinevere Larsen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=362da4a2-fd80-48f0-8eea-79365b77a008@redhat.com \
    --to=guinevere@redhat.com \
    --cc=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox