diff options
author | Lancelot SIX <lsix@lancelotsix.com> | 2021-09-27 21:56:58 +0000 |
---|---|---|
committer | Lancelot SIX <lsix@lancelotsix.com> | 2021-10-03 14:00:58 +0000 |
commit | 2b014cc535e9d8eeb2203b1f5e9fd5c5e8fb5028 (patch) | |
tree | deac1d41f717e0b6c198964e868fee9e70bb7d23 | |
parent | d4e8e096a57a6384a5e0e97ade6f77bf1d418a90 (diff) | |
download | gdb-2b014cc535e9d8eeb2203b1f5e9fd5c5e8fb5028.zip gdb-2b014cc535e9d8eeb2203b1f5e9fd5c5e8fb5028.tar.gz gdb-2b014cc535e9d8eeb2203b1f5e9fd5c5e8fb5028.tar.bz2 |
gdb: Support the c.mv insn in the riscv prologue scanner.
While working on other problems, I encountered situations where GDB
fails to properly unwind the stack because some functions use the C.MV
instruction in the prologue. The prologue scanner stops when it hits
this instruction assuming its job is done at this point. Unfortunately
the prologue is not necessarily finished yet, preventing GDB to properly
unwind.
This commit adds support for handling such instruction in
riscv_scan_prologue.
Note that C.MV is part of the compressed instruction set. The MV
counterpart from the base ISA is a pseudo instruction that expands to
'ADDI RD,RS1,0' which is already supported.
Tested on riscv64-linux-gnu.
All feedback are welcome.
-rw-r--r-- | gdb/riscv-tdep.c | 13 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.c | 29 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.exp | 44 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.s | 47 |
4 files changed, 132 insertions, 1 deletions
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 8b55bc3..b8844b6 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -1411,6 +1411,7 @@ public: SW, LD, LW, + MV, /* These are needed for software breakpoint support. */ JAL, JALR, @@ -1789,9 +1790,11 @@ riscv_insn::decode (struct gdbarch *gdbarch, CORE_ADDR pc) else if (xlen != 4 && is_c_sdsp_insn (ival)) decode_css_type_insn (SD, ival, EXTRACT_CSSTYPE_SDSP_IMM (ival)); /* C_JR and C_MV have the same opcode. If RS2 is 0, then this is a C_JR. - So must try to match C_JR first as it ahs more bits in mask. */ + So must try to match C_JR first as it has more bits in mask. */ else if (is_c_jr_insn (ival)) decode_cr_type_insn (JALR, ival); + else if (is_c_mv_insn (ival)) + decode_cr_type_insn (MV, ival); else if (is_c_j_insn (ival)) decode_cj_type_insn (JAL, ival); else if (is_c_beqz_insn (ival)) @@ -1964,6 +1967,14 @@ riscv_scan_prologue (struct gdbarch *gdbarch, insn.imm_signed ()), (insn.opcode () == riscv_insn::LW ? 4 : 8)); } + else if (insn.opcode () == riscv_insn::MV) + { + /* Handle: c.mv RD, RS2 */ + gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS); + gdb_assert (insn.rs2 () < RISCV_NUM_INTEGER_REGS); + gdb_assert (insn.rs2 () > 0); + regs[insn.rd ()] = regs[insn.rs2 ()]; + } else { end_prologue_addr = cur_pc; diff --git a/gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.c b/gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.c new file mode 100644 index 0000000..bb8a8ee --- /dev/null +++ b/gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.c @@ -0,0 +1,29 @@ +/* Copyright 2021 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/>. */ + +/* See riscv64-unwind-prologue-with-mv.s for implementation. */ + +extern int bar (); + +/* See riscv64-unwind-prologue-with-mv.s for implementation. */ + +extern int foo (); + +int +main () +{ + return foo (); +} + diff --git a/gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.exp b/gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.exp new file mode 100644 index 0000000..47429ba --- /dev/null +++ b/gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.exp @@ -0,0 +1,44 @@ +# Copyright 2021 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/>. + +# This tests GDB's ability to use the RISC-V prologue scanner in order to +# unwind through a function that uses the 'c.mv' instruction in its prologue. + +if {![istarget "riscv64-*-*"]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +standard_testfile .c .s +if {[prepare_for_testing "failed to prepare" $testfile \ + "$srcfile $srcfile2" nodebug]} { + return -1 +} + +if ![runto_main] then { + fail "can't run to main" + return 0 +} + +gdb_breakpoint "bar" +gdb_continue_to_breakpoint "bar" +gdb_test "bt" \ + [multi_line \ + "#0\[ \t\]*$hex in bar \\\(\\\)" \ + "#1\[ \t\]*$hex in foo \\\(\\\)" \ + "#2\[ \t\]*$hex in main \\\(\\\)"] \ + "Backtrace to the main frame" +gdb_test "finish" "foo \\\(\\\)" "finish bar" +gdb_test "finish" "main \\\(\\\)" "finish foo" diff --git a/gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.s b/gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.s new file mode 100644 index 0000000..a1ec538 --- /dev/null +++ b/gdb/testsuite/gdb.arch/riscv64-unwind-prologue-with-mv.s @@ -0,0 +1,47 @@ +/* Copyright 2021 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/>. */ + +/* This testcase contains a function where the 'c.mv' instruction is used in + the prologue. + + The following functions are roughly equivalent to the following C code (with + prologue crafted to contain the c.mv instruction): + + int bar () { return 0; } + int foo () { return bar (); } */ + + .option pic + .text + .align 1 + .globl bar + .type bar, @function +bar: + li a0,0 + jr ra + .size bar, .-bar + + .align 1 + .globl foo + .type foo, @function +foo: + addi sp,sp,-32 + c.mv t3,ra + sd t3,8(sp) + call bar + ld t3,8(sp) + mv ra,t3 + addi sp,sp,32 + jr ra + .size foo, .-foo |