]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/testsuite: fix skip-tree.exp test for PowerPC
authorAndrew Burgess <aburgess@redhat.com>
Thu, 16 Apr 2026 15:55:27 +0000 (17:55 +0200)
committerAndrew Burgess <aburgess@redhat.com>
Fri, 17 Apr 2026 10:30:17 +0000 (11:30 +0100)
The gdb.base/skip-tree.exp test was added in commit:

  commit 5ed98c177f9a2381fe5c6ab873d05f1e5dcb8f7f
  Date:   Wed Feb 4 20:31:31 2026 +0000

      gdb: introduce '**' for skip globs

This test currently fails on PowerPC due to architectural differences
in function return handling.

On PowerPC64 ELFv2, calls to external functions are followed by a
`nop` instruction that serves as a placeholder for TOC pointer
restoration. Since this `nop` typically has no DWARF line entry,
`finish` reports the call line instead of the next line.

This issue was reported here:

  https://inbox.sourceware.org/gdb-patches/20260415055144.2729164-1-abhay@linux.ibm.com

The fix proposed there was to add a PowerPC specific check so that the
test would send a `next` command after using `finish` to advance to
the expected source line.

This commit actually takes a more general approach.  After calling
`finish` we check which line we ended up on.  If it was the caller
line then we send GDB a `next` to move to the expected line.  If we
arrive directly at the next line, then no `next` is needed.

I've tested this change on x86-64, where no `next` is needed, and
PowerPC, where `next` is now used as required to get the test
passing.

To simplify the pattern matching in the exp file, I tweaked the source
file slightly.  But adding a call to a dummy 'func5' it's now easy to
pattern match as we step through 'func1', 'func2', etc.

Co-Authored-By: Abhay Kandpal <abhay@linux.ibm.com>
gdb/testsuite/gdb.base/skip-tree.c
gdb/testsuite/gdb.base/skip-tree.exp

index 4a254b860b14a91e6f5e72721b69cfe736eceb62..3bedc397a857199b386a7689932ab05322978945 100644 (file)
@@ -22,17 +22,26 @@ extern void func4 (void);
 
 static volatile int global_var;
 
+void
+func5 (void)
+{
+  /* Nothing.  */
+}
+
 int
 main (void)
 {
+  /* Some filler before the real work starts.  */
   ++global_var;
 
   func1 ();    /* In aa/bb/file.c */
   func2 ();    /* In cc/bb/file.c */
   func3 ();    /* In dd/ee/file.c */
   func4 ();    /* In dd/ee/ff/file.c */
+  func5 ();    /* Makes exp file simpler.  */
 
-  ++global_var;        /* End marker.  */
+  /* Some filler before the function ends.  */
+  ++global_var;
 
   return 0;
 }
index dc93c4cef84046d6289b9a0cb7731280cfe6ca46..b1d42ffa87e523d7697fccfcd3306bdf0318b3bc 100644 (file)
@@ -48,7 +48,7 @@ set lineno_f1 [gdb_get_line_number "func1 ();" $srcfile]
 set lineno_f2 [gdb_get_line_number "func2 ();" $srcfile]
 set lineno_f3 [gdb_get_line_number "func3 ();" $srcfile]
 set lineno_f4 [gdb_get_line_number "func4 ();" $srcfile]
-set lineno_end [gdb_get_line_number "End marker" $srcfile]
+set lineno_f5 [gdb_get_line_number "func5 ();" $srcfile]
 
 # Compile all the source files into DESTFILE.  If RELATIVE_FILENAMES
 # is true then the compilation is done using relative filenames to the
@@ -139,19 +139,29 @@ proc run_test { file_glob skip_func1 skip_func2 skip_func3 skip_func4 \
                     "$::decimal\\s+\\+\\+global_var_$i;"] \
                "step into func$i"
 
-           # Now finish the function, returning to the caller.
-           gdb_test "finish" ".*" \
-               "finish from func$i"
+           # Now finish the function, returning to the caller.  Some
+           # targets, after the finish, will place the inferior back
+           # on the calling line.  We spot this and issue a 'next' to
+           # move forward to the next function call.
+           set saw_next_line false
+           set saw_previous_line false
+           gdb_test_multiple "finish" "finish from func$i" {
+               -re -wrap "\r\n$::decimal\\s+func[expr {$i + 1}] \\(\\);\[^\r\n\]*" {
+                   pass $gdb_test_name
+               }
+               -re -wrap "\r\n$::decimal\\s+func$i \\(\\);\[^\r\n\]*" {
+                   # After 'finish' this target reports the inferior
+                   # as still on the calling line.  Use 'next' to
+                   # prepare for the next test.
+                   send_gdb "next\n"
+                   exp_continue
+               }
+           }
        } else {
            # After skipping the function, on which line should we
            # stop, and what does the line look like.
-           if { $j < 5 } {
-               set lineno [set "::lineno_f$j"]
-               set after_skip_re "func$j \\(\\);\[^\r\n\]+"
-           } else {
-               set lineno $::lineno_end
-               set after_skip_re "\\+\\+global_var;\[^\r\n\]+"
-           }
+           set lineno [set "::lineno_f$j"]
+           set after_skip_re "func$j \\(\\);\[^\r\n\]+"
 
            # Step the inferior, we expect to skip the function.
            gdb_test "step" \