gdb/riscv: fix gdb.arch/riscv-unwind-long-insn.exp on RV64
authorAndrew Burgess <aburgess@redhat.com>
Tue, 16 Aug 2022 15:52:08 +0000 (16:52 +0100)
committerAndrew Burgess <aburgess@redhat.com>
Tue, 16 Aug 2022 16:10:49 +0000 (17:10 +0100)
I noticed that the gdb.arch/riscv-unwind-long-insn.exp test was
failing when run on a 64-bit RISC-V target.

The problem was that GDB was failing to stop after a finish command,
and was then running to an unexpected location.

The reason GDB failed to stop at the finish breakpoint was that the
frame-id of the inferior, when we reached the finish breakpoint,
didn't match the expected frame-id that was stored on the breakpoint.

The reason for this mismatch was that the assembler code that is
included in this test, was written only taking 32-bit RISC-V into
account, as a result, the $fp register was being corrupted, and this
was causing the frame-id mismatch.

Specifically, the $fp register would end up being sign-extended from
32 to 64 bits.  If the expected $fp value has some significant bits
above bit 31 then the computed and expected frame-ids would not match.

To fix this I propose merging the two .s files into a single .S file,
and making use of preprocessor macros to specialise the file for the
correct size of $fp.  There are plenty of existing tests that already
make use of preprocessor macros in assembler files, so I assume this
approach is fine.

Once I'd decided to make use of preprocessor macros to solve the 32/64
bit issue, then I figured I might as well merge the two test assembler
files, they only differed by a single instruction.

With this change in place I now see this test fully passing on 32 and
64 bit RISC-V targets.

gdb/testsuite/gdb.arch/riscv-unwind-long-insn-6.s [deleted file]
gdb/testsuite/gdb.arch/riscv-unwind-long-insn-8.s [deleted file]
gdb/testsuite/gdb.arch/riscv-unwind-long-insn.S [new file with mode: 0644]
gdb/testsuite/gdb.arch/riscv-unwind-long-insn.exp

diff --git a/gdb/testsuite/gdb.arch/riscv-unwind-long-insn-6.s b/gdb/testsuite/gdb.arch/riscv-unwind-long-insn-6.s
deleted file mode 100644 (file)
index 9a72847..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright 2019-2022 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/>.  */
-
-       .option nopic
-       .text
-
-        .align 1
-       .globl  bar
-       .type   bar, @function
-bar:
-        tail       1f
-       .size   bar, .-func
-
-       .align  1
-       .globl  func
-       .type   func, @function
-func:
-        /* A fake 6 byte instruction.  This is never executed, but the
-          prologue scanner will try to decode it.  These long
-          instructions are ISA extensions, use .byte rather than an
-          actual instruction mnemonic so that the test can be compiled
-          with a toolchain that doesn't include any long instruction
-          extensions.  */
-        .byte 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00
-1:
-       addi    sp,sp,-16
-       sw      s0,12(sp)
-       addi    s0,sp,16
-       nop
-       lw      s0,12(sp)
-       addi    sp,sp,16
-       jr      ra
-       .size   func, .-func
diff --git a/gdb/testsuite/gdb.arch/riscv-unwind-long-insn-8.s b/gdb/testsuite/gdb.arch/riscv-unwind-long-insn-8.s
deleted file mode 100644 (file)
index 694f10a..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright 2019-2022 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/>.  */
-
-       .option nopic
-       .text
-
-        .align 1
-       .globl  bar
-       .type   bar, @function
-bar:
-        tail       1f
-       .size   bar, .-func
-
-       .align  1
-       .globl  func
-       .type   func, @function
-func:
-        /* A fake 8 byte instruction.  This is never executed, but the
-          prologue scanner will try to decode it.  These long
-          instructions are ISA extensions, use .byte rather than an
-          actual instruction mnemonic so that the test can be compiled
-          with a toolchain that doesn't include any long instruction
-          extensions.  */
-        .byte 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-1:
-       addi    sp,sp,-16
-       sw      s0,12(sp)
-       addi    s0,sp,16
-       nop
-       lw      s0,12(sp)
-       addi    sp,sp,16
-       jr      ra
-       .size   func, .-func
diff --git a/gdb/testsuite/gdb.arch/riscv-unwind-long-insn.S b/gdb/testsuite/gdb.arch/riscv-unwind-long-insn.S
new file mode 100644 (file)
index 0000000..00e0a34
--- /dev/null
@@ -0,0 +1,62 @@
+/* Copyright 2019-2022 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/>.  */
+
+       .option nopic
+       .text
+
+       .align  1
+       .globl  bar
+       .type   bar, @function
+bar:
+       tail       1f
+       .size   bar, .-func
+
+       .align  1
+       .globl  func
+       .type   func, @function
+func:
+       /* A fake instruction of either 6 or 8 bytes.  This is never
+          executed, but the prologue scanner will try to decode it.
+          These long instructions are ISA extensions, use .byte rather
+          than an actual instruction mnemonic so that the test can be
+          compiled with a toolchain that doesn't include any long
+          instruction extensions.  */
+#if BAD_INSN_LEN == 6
+       /* A fake 6 byte instruction.  */
+       .byte 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00
+#elif BAD_INSN_LEN == 8
+       /* A fake 8 byte instruction.  */
+       .byte 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+#else
+#error unexpected bad instruction length
+#endif
+
+1:
+       addi    sp,sp,-16
+#if __SIZEOF_POINTER__ == 8
+       sd      s0,8(sp)
+#else
+       sw      s0,8(sp)
+#endif
+       addi    s0,sp,16
+       nop
+#if __SIZEOF_POINTER__ == 8
+       ld      s0,8(sp)
+#else
+       lw      s0,8(sp)
+#endif
+       addi    sp,sp,16
+       jr      ra
+       .size   func, .-func
index 448c0b0c275906315eda24990b443e085bb84b5b..385e16b575fde4c2ad3cb30fb28316b0634255d5 100644 (file)
@@ -27,13 +27,15 @@ if {![istarget "riscv*-*-*"]} {
     return
 }
 
+standard_testfile riscv-unwind-long-insn.c \
+    riscv-unwind-long-insn.S
+
 foreach_with_prefix {insn_size} {6 8} {
-    standard_testfile riscv-unwind-long-insn.c \
-       riscv-unwind-long-insn-${insn_size}.s
+    set flags [list debug additional_flags=-DBAD_INSN_LEN=${insn_size}]
 
     set testfile "${testfile}-${insn_size}"
     if {[prepare_for_testing "failed to prepare" $testfile \
-            "$srcfile $srcfile2"  debug]} {
+            "$srcfile $srcfile2" $flags]} {
        return -1
     }