]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: pass minsym section to find_function_start_sal, when possible
authorSébastien Darche <sdarche@efficios.com>
Fri, 3 Oct 2025 13:18:30 +0000 (09:18 -0400)
committerSébastien Darche <sdarche@efficios.com>
Tue, 28 Oct 2025 13:43:30 +0000 (09:43 -0400)
We may rely on a minimal symbol to place a breakpoint on a function,
for instance when debug infos are unavailable. The minsym_found
function attempts to convert that minsym to a sal using either
find_function_start_sal or filling a sal manually from the minimal
symbol. This patch implements the decision to make it the responsibility
of the sal creation site to properly fill out the section field when
that is possible.

The function address may be updated when dealing with ifuncs, which
means the section from the minsym may be completely different from the
actual function address's section. A preceding change (6f7ad238 : gdb:
ensure bp_location::section is set correct to avoid an assert) has
proposed recomputing the section by calling find_pc_overlay. However,
this ends up setting the section to NULL in most cases. While the
section is often recomputed later on, I think it might be more
appropriate to set it once and for all when creating the sal.

The parent commit ensures that find_function_start_sal will return a
symtab_and_line with a section if possible. minsym_found can pass the
section if it can be trusted later on - it is in fact necessary to
ensure we get the proper pc/section with overlays. When dealing with
an ifunc that was resolved, then the section has to be recomputed
since the ifunc implementation may be in another section, or objfile.
This is now done in find_sal_for_pc_sect.

This change restores the section argument in
find_function_start_sal that was removed in a previous commit (6b0581fc
: gdb/symtab: remove section parameter from find_function_start_sal),
as it avoids an unnecessary lookup later in find_sal_for_pc_sect. The
function now sends the minsym's section if it corresponds to the actual
function, and not an ifunc.

This commit fixes a failure on gdb.rocm/displaced-stepping.exp. A new
test case is also provided to check that a breakpoint on a kernel is hit
without debug infos.

Approved-By: Tom Tromey <tom@tromey.com>
Change-Id: I7a502dc4565911cec92618f34be3d4bcbf8560c5

gdb/elfread.c
gdb/linespec.c
gdb/symtab.c
gdb/symtab.h
gdb/testsuite/gdb.rocm/break-kernel-no-debug-info.cpp [new file with mode: 0644]
gdb/testsuite/gdb.rocm/break-kernel-no-debug-info.exp [new file with mode: 0644]

index c91b9ab7c214e9123c405f7e0b539b7a4f4e09d5..db024c06344f204c7b973806303d73f3a2817f89 100644 (file)
@@ -1046,7 +1046,7 @@ elf_gnu_ifunc_resolver_return_stop (code_breakpoint *b)
 
   b->type = bp_breakpoint;
   update_breakpoint_locations (b, current_program_space,
-                              find_function_start_sal (resolved_pc, true),
+                              find_function_start_sal (resolved_pc, nullptr, true),
                               {});
 }
 
index b7ddd166c8ac3255bcce301982665ca1179774ce..4560459ad3c03ca8846efa1d230bbe552d97672e 100644 (file)
@@ -4059,6 +4059,7 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
 
   CORE_ADDR func_addr;
   bool is_function = msymbol_is_function (objfile, msymbol, &func_addr);
+  obj_section *section = msymbol->obj_section (objfile);
 
   if (is_function)
     {
@@ -4066,7 +4067,15 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
 
       if (msymbol->type () == mst_text_gnu_ifunc
          || msymbol->type () == mst_data_gnu_ifunc)
-       want_start_sal = gnu_ifunc_resolve_name (msym_name, &func_addr);
+       {
+         want_start_sal = gnu_ifunc_resolve_name (msym_name, &func_addr);
+
+         /* We have found a different pc by resolving the ifunc. The
+            section from the minsym may not be the same as the ifunc
+            implementation.  Do not trust it.  */
+         if (want_start_sal)
+           section = nullptr;
+       }
       else
        want_start_sal = true;
     }
@@ -4074,7 +4083,7 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
   symtab_and_line sal;
 
   if (is_function && want_start_sal)
-    sal = find_function_start_sal (func_addr, self->funfirstline);
+    sal = find_function_start_sal (func_addr, section, self->funfirstline);
   else
     {
       sal.objfile = objfile;
@@ -4086,14 +4095,15 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
       else
        sal.pc = msymbol->value_address (objfile);
       sal.pspace = current_program_space;
-    }
 
-  /* Don't use the section from the msymbol, the code above might have
-     adjusted FUNC_ADDR, in which case the msymbol's section might not be
-     the section containing FUNC_ADDR.  It might not even be in the same
-     objfile.  As the section is primarily to assist with overlay
-     debugging, it should reflect the SAL's pc value.  */
-  sal.section = find_pc_overlay (sal.pc);
+      /* The minsym does not correspond to an ifunc that could be
+        resolved.  The section from the minsym may thus be trusted,
+        and cannot be nullptr (since the minsym is from an objfile).
+        Ensure all resulting sals have a non-null section when
+        possible.  */
+      gdb_assert (section != nullptr);
+      sal.section = section;
+    }
 
   if (self->maybe_add_address (objfile->pspace (), sal.pc))
     add_sal_to_sals (self, result, sal, msymbol->natural_name (), false);
index bd3d55eecb0160d0a845cdfd76d49fb16c123560..3b0687c0750c9587dd4cccff0686f4069e0c448f 100644 (file)
@@ -3560,10 +3560,10 @@ find_function_start_sal_1 (CORE_ADDR func_addr, obj_section *section,
 /* See symtab.h.  */
 
 symtab_and_line
-find_function_start_sal (CORE_ADDR func_addr, bool funfirstline)
+find_function_start_sal (CORE_ADDR func_addr, obj_section *section, bool funfirstline)
 {
   symtab_and_line sal
-    = find_function_start_sal_1 (func_addr, nullptr, funfirstline);
+    = find_function_start_sal_1 (func_addr, section, funfirstline);
 
   /* find_function_start_sal_1 does a linetable search, so it finds
      the symtab and linenumber, but not a symbol.  Fill in the
index 985843f76b650643d54347b64e357c20ed50555a..e47033efd01d1b86d470f3b138829504dfcca327 100644 (file)
@@ -2516,6 +2516,7 @@ extern symtab_and_line find_function_start_sal (symbol *sym, bool
 
 /* Same, but start with a function address instead of a symbol.  */
 extern symtab_and_line find_function_start_sal (CORE_ADDR func_addr,
+                                               obj_section *section,
                                                bool funfirstline);
 
 extern void skip_prologue_sal (struct symtab_and_line *);
diff --git a/gdb/testsuite/gdb.rocm/break-kernel-no-debug-info.cpp b/gdb/testsuite/gdb.rocm/break-kernel-no-debug-info.cpp
new file mode 100644 (file)
index 0000000..f46a57c
--- /dev/null
@@ -0,0 +1,30 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2025 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <hip/hip_runtime.h>
+
+__global__ void
+kern ()
+{
+}
+
+int
+main ()
+{
+  kern<<<1, 1>>> ();
+  return hipDeviceSynchronize () != hipSuccess;
+}
diff --git a/gdb/testsuite/gdb.rocm/break-kernel-no-debug-info.exp b/gdb/testsuite/gdb.rocm/break-kernel-no-debug-info.exp
new file mode 100644 (file)
index 0000000..df65b7c
--- /dev/null
@@ -0,0 +1,53 @@
+# Copyright 2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test setting a breakpoint on a kernel symbol without debug info,
+# relying on minimal symbols from the ELF.
+
+# A bug occured when GDB did not find the appropriate architecture for
+# breakpoints on minimal symbols. This had the effect that the
+# breakpoint would not be hit on the GPU when no debugging infos are
+# available.
+
+load_lib rocm.exp
+
+standard_testfile .cpp
+
+require allow_hipcc_tests
+
+# Build for hip, explicitly without debug infos
+if {[build_executable "failed to prepare" $testfile $srcfile {hip nodebug}]} {
+    return
+}
+
+clean_restart
+
+with_rocm_gpu_lock {
+    gdb_test "file $::binfile" ".*No debugging symbols.*" "load file"
+
+    if {![runto_main]} {
+       return
+    }
+
+    gdb_test "with breakpoint pending on -- break kern" \
+       "Breakpoint $::decimal \\(kern\\) pending."
+
+    gdb_test "continue" \
+       "Thread $::decimal hit Breakpoint $::decimal, $::hex in kern.*"
+
+    gdb_test "continue" \
+       "Inferior 1 .* exited normally.*" \
+       "continue to end"
+}