From: Guinevere Larsen <guinevere@redhat.com>
To: gdb-patches@sourceware.org
Cc: Guinevere Larsen <guinevere@redhat.com>
Subject: [PATCH 1/1] gdb: Print linker namespace when showing a frame
Date: Tue, 12 Aug 2025 17:21:42 -0300 [thread overview]
Message-ID: <20250812202142.3308633-1-guinevere@redhat.com> (raw)
When a user is stopped in a private linker namespace, the only way for
them to realize that is using the _linker_namespace convenience
variable. While serviceable, this is a sub-optimal solution, as most
users are unaware of convenience variables.
This commit introduces a new way for users to be informed of the linker
namespace of a function, by printing it along with the function name.
This is done by using the proposed syntax for symbols and locations,
like so:
#0 [[0]]::main ()
This is done by exporting part of the functionality behind the
_linker_namespace variable, namely, find the linker namespace that
contains the given address on the current program space. Since this
change also touched the convenience variable code, this commit fixes a
formatting error in that function.
The namespace ID is only printed if multiple namespaces are active,
otherwise no change in behavior is expected. This commit also updates
the test gdb.base/dlmopen-ns-ids.exp to test this functionality.
---
gdb/solib.c | 28 ++++++++++++++---------
gdb/solib.h | 5 ++++
gdb/stack.c | 13 +++++++++++
gdb/testsuite/gdb.base/dlmopen-ns-ids.exp | 12 +++++++++-
gdb/testsuite/gdb.mi/mi-dlmopen.exp | 2 +-
5 files changed, 47 insertions(+), 13 deletions(-)
diff --git a/gdb/solib.c b/gdb/solib.c
index 3ec2032f012..2f32f08b645 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1805,6 +1805,21 @@ remove_user_added_objfile (struct objfile *objfile)
}
}
+/* See solib.h. */
+
+int
+linker_namespace_contains_addr (CORE_ADDR addr)
+{
+ for (const solib &so : current_program_space->solibs ())
+ if (solib_contains_address_p (so, addr))
+ {
+ if (so.ops ().supports_namespaces ())
+ return so.ops ().find_solib_ns (so);
+ }
+
+ return 0;
+}
+
/* Implementation of the linker_namespace convenience variable.
This returns the GDB internal identifier of the linker namespace,
@@ -1813,19 +1828,10 @@ remove_user_added_objfile (struct objfile *objfile)
static value *
linker_namespace_make_value (gdbarch *gdbarch, internalvar *var,
- void *ignore)
+ void *ignore)
{
- int nsid = 0;
CORE_ADDR curr_pc = get_frame_pc (get_selected_frame ());
-
- for (const solib &so : current_program_space->solibs ())
- if (solib_contains_address_p (so, curr_pc))
- {
- if (so.ops ().supports_namespaces ())
- nsid = so.ops ().find_solib_ns (so);
-
- break;
- }
+ int nsid = linker_namespace_contains_addr (curr_pc);
/* If the PC is not in an SO, or the solib_ops doesn't support
linker namespaces, the inferior is in the default namespace. */
diff --git a/gdb/solib.h b/gdb/solib.h
index b9465e103bd..213f66c7ae4 100644
--- a/gdb/solib.h
+++ b/gdb/solib.h
@@ -303,6 +303,11 @@ extern const char *solib_name_from_address (struct program_space *, CORE_ADDR);
extern bool solib_contains_address_p (const solib &, CORE_ADDR);
+/* Given the address ADDR, return which linker namespace contains
+ this address in the current program space. */
+
+int linker_namespace_contains_addr (CORE_ADDR addr);
+
/* Return whether the data starting at VADDR, size SIZE, must be kept
in a core file for shared libraries loaded before "gcore" is used
to be handled correctly when the core file is loaded. This only
diff --git a/gdb/stack.c b/gdb/stack.c
index e6335669531..10078e06766 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1363,6 +1363,19 @@ print_frame (struct ui_out *uiout,
annotate_frame_function_name ();
string_file stb;
+
+ /* Print the linker namespace containing the frame, if there
+ are multiple namespaces active. */
+ LONGEST num_linker_namespaces;
+ get_internalvar_integer (lookup_internalvar ("_active_linker_namespaces"),
+ &num_linker_namespaces);
+ if (pc_p && num_linker_namespaces > 1)
+ {
+ LONGEST curr_namespace = linker_namespace_contains_addr (pc);
+ std::string s = string_printf ("[[%ld]]::", curr_namespace);
+ gdb_puts (s.c_str (), &stb);
+ }
+
gdb_puts (funname ? funname.get () : "??", &stb);
uiout->field_stream ("func", stb, function_name_style.style ());
uiout->wrap_hint (3);
diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
index 4d3e8eba2ab..a88ad817dc1 100644
--- a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
+++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
@@ -107,6 +107,8 @@ proc test_info_shared {} {
# Run all tests related to the linkage namespaces convenience
# variables, _active_namespaces and _current_namespaces.
+# Also tests that the namespace ID is only printed at the correct
+# times.
proc_with_prefix test_conv_vars {} {
clean_restart $::binfile
@@ -124,6 +126,11 @@ proc_with_prefix test_conv_vars {} {
gdb_test "print \$_linker_namespace" ".* = 0" \
"Still in the default namespace"
+ # There should be no namespace ID visible, since there's
+ # only one namespace loaded.
+ gdb_test "backtrace" "\#0\\s+main .*" \
+ "No namespace ID in backtrace"
+
gdb_breakpoint "inc" allow-pending
gdb_breakpoint [gdb_get_line_number "TAG: first dlclose"]
@@ -132,11 +139,14 @@ proc_with_prefix test_conv_vars {} {
gdb_test "print \$_linker_namespace" ".* = $dl" \
"Verify we're in namespace $dl"
+
+ gdb_test "frame" "\#0\\s+\\\[\\\[$dl\\\]\\\]::inc.*" \
+ "Namespace ID in the frame"
}
# Check that we display the namespace of the selected
# frame, not the lowermost one.
- gdb_test "up" "\#1.*in main.*"
+ gdb_test "up" "\#1.*in \\\[\\\[0\\\]\\\]::main.*"
gdb_test "print \$_linker_namespace" ".* = 0" \
"print namespace of selected frame"
diff --git a/gdb/testsuite/gdb.mi/mi-dlmopen.exp b/gdb/testsuite/gdb.mi/mi-dlmopen.exp
index c0208ebcc51..3070f879d17 100644
--- a/gdb/testsuite/gdb.mi/mi-dlmopen.exp
+++ b/gdb/testsuite/gdb.mi/mi-dlmopen.exp
@@ -146,7 +146,7 @@ proc check_solib_unload_events {} {
-disp keep -func main -file ".*$::srcfile" -line $::bp_main
# Run past all the dlopen and dlmopen calls.
- mi_execute_to "exec-continue" "breakpoint-hit" main "" ".*" $::bp_loaded \
+ mi_execute_to "exec-continue" "breakpoint-hit" {\[\[0\]\]::main} "" ".*" $::bp_loaded \
{"" "disp=\"keep\""} "continue until all libraries are loaded"
# Check that the dynamic linker has now been loaded multiple times.
--
2.50.1
next reply other threads:[~2025-08-12 20:22 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-12 20:21 Guinevere Larsen [this message]
2025-08-13 19:28 ` Simon Marchi
2025-08-13 20:18 ` 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=20250812202142.3308633-1-guinevere@redhat.com \
--to=guinevere@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