diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 70fc324985..8cf9a6c9ca 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2018-09-26 Andrew Burgess + + * riscv-tdep.c (riscv_insn::decode): Decode c.lui. + (riscv_scan_prologue): Split handling of AUIPC, LUI, ADD, ADDI, + and NOP. + 2018-09-26 Simon Marchi * elf32-nds32.c (elf32_nds32_allocate_dynrelocs): Remove. diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 254914c9c7..163c8ec231 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -1227,7 +1227,11 @@ riscv_insn::decode (struct gdbarch *gdbarch, CORE_ADDR pc) m_imm.s = EXTRACT_RVC_ADDI4SPN_IMM (ival); } else if (is_c_lui_insn (ival)) - m_opcode = OTHER; + { + m_opcode = LUI; + m_rd = decode_register_index (ival, OP_SH_CRS1S); + m_imm.s = EXTRACT_RVC_LUI_IMM (ival); + } /* C_SD and C_FSW have the same opcode. C_SD is RV64 and RV128 only, and C_FSW is RV32 only. */ else if (xlen != 4 && is_c_sd_insn (ival)) @@ -1359,28 +1363,41 @@ riscv_scan_prologue (struct gdbarch *gdbarch, gdb_assert (insn.rs1 () < RISCV_NUM_INTEGER_REGS); regs[insn.rd ()] = pv_add_constant (regs[insn.rs1 ()], 0); } - else if ((insn.rd () == RISCV_GP_REGNUM - && (insn.opcode () == riscv_insn::AUIPC - || insn.opcode () == riscv_insn::LUI - || (insn.opcode () == riscv_insn::ADDI - && insn.rs1 () == RISCV_GP_REGNUM) - || (insn.opcode () == riscv_insn::ADD - && (insn.rs1 () == RISCV_GP_REGNUM - || insn.rs2 () == RISCV_GP_REGNUM)))) - || (insn.opcode () == riscv_insn::ADDI - && insn.rd () == RISCV_ZERO_REGNUM - && insn.rs1 () == RISCV_ZERO_REGNUM - && insn.imm_signed () == 0)) + else if ((insn.opcode () == riscv_insn::ADDI + && insn.rd () == RISCV_ZERO_REGNUM + && insn.rs1 () == RISCV_ZERO_REGNUM + && insn.imm_signed () == 0)) { - /* Handle: auipc gp, n - or: addi gp, gp, n - or: add gp, gp, reg - or: add gp, reg, gp - or: lui gp, n - or: add x0, x0, 0 (NOP) */ - /* These instructions are part of the prologue, but we don't need - to do anything special to handle them. */ + /* Handle: add x0, x0, 0 (NOP) */ } + else if (insn.opcode () == riscv_insn::AUIPC) + { + gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS); + regs[insn.rd ()] = pv_constant (cur_pc + insn.imm_signed ()); + } + else if (insn.opcode () == riscv_insn::LUI) + { + /* Handle: lui REG, n + Where REG is not gp register. */ + gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS); + regs[insn.rd ()] = pv_constant (insn.imm_signed ()); + } + else if (insn.opcode () == riscv_insn::ADDI) + { + /* Handle: addi REG1, REG2, IMM */ + gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS); + gdb_assert (insn.rs1 () < RISCV_NUM_INTEGER_REGS); + regs[insn.rd ()] + = pv_add_constant (regs[insn.rs1 ()], insn.imm_signed ()); + } + else if (insn.opcode () == riscv_insn::ADD) + { + /* Handle: addi REG1, REG2, IMM */ + gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS); + gdb_assert (insn.rs1 () < RISCV_NUM_INTEGER_REGS); + gdb_assert (insn.rs2 () < RISCV_NUM_INTEGER_REGS); + regs[insn.rd ()] = pv_add (regs[insn.rs1 ()], regs[insn.rs2 ()]); + } else { end_prologue_addr = cur_pc; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index d15fcff17b..2b4b0973ef 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2018-09-26 Andrew Burgess + + * gdb.base/large-frame-1.c: New file. + * gdb.base/large-frame-2.c: New file. + * gdb.base/large-frame.exp: New file. + * gdb.base/large-frame.h: New file. + 2018-09-24 Jozef Lawrynowicz PR gdb/20948 diff --git a/gdb/testsuite/gdb.base/large-frame-1.c b/gdb/testsuite/gdb.base/large-frame-1.c new file mode 100644 index 0000000000..cd9c5ccdd0 --- /dev/null +++ b/gdb/testsuite/gdb.base/large-frame-1.c @@ -0,0 +1,32 @@ +/* This file is part of GDB, the GNU debugger. + + Copyright 2018 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 . */ + +#include "large-frame.h" + +__attribute__ ((noinline)) void +blah (int *a) +{ + asm ("" :: "m" (a) : "memory"); +} + +int +main () +{ + func (); + + return 0; +} diff --git a/gdb/testsuite/gdb.base/large-frame-2.c b/gdb/testsuite/gdb.base/large-frame-2.c new file mode 100644 index 0000000000..2491c34729 --- /dev/null +++ b/gdb/testsuite/gdb.base/large-frame-2.c @@ -0,0 +1,25 @@ +/* This file is part of GDB, the GNU debugger. + + Copyright 2018 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 . */ + +#include "large-frame.h" + +__attribute__ ((noinline)) int +func (void) +{ + int a[4096]; + blah (a); +} diff --git a/gdb/testsuite/gdb.base/large-frame.exp b/gdb/testsuite/gdb.base/large-frame.exp new file mode 100644 index 0000000000..00090da795 --- /dev/null +++ b/gdb/testsuite/gdb.base/large-frame.exp @@ -0,0 +1,57 @@ +# Copyright 2018 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 . +# +# This file is part of the gdb testsuite. + +# This test was added to test GDB's ability to backtrace over a large +# stack frame for which there is no debug information. This should +# test the non-DWARF stack unwinder. +# +# The test was originally added for Risc-V where this case caused a +# problem at one point, however, there's nothing Risc-V specific in +# the test. + +proc run_test { opt_level } { + global srcfile srcfile2 binfile hex + + standard_testfile large-frame-1.c large-frame-2.c + + if {[prepare_for_testing_full "failed to prepare" \ + [list ${binfile}-${opt_level} debug \ + $srcfile [list debug] \ + $srcfile2 [list nodebug optimize=-$opt_level]]]} { + return + } + + if { ![runto_main] } then { + unsupported "runto main" + return + } + + gdb_breakpoint "blah" + gdb_continue_to_breakpoint "blah" + + gdb_test "backtrace" [multi_line \ + "#0 blah \[^\n\r\]+" \ + "#1 $hex in func \[^\n\r\]+" \ + "#2 $hex in main \[^\n\r\]+"] +} + +foreach opt { O0 O1 O2 } { + with_test_prefix "optimize=-$opt" { + run_test $opt + } +} + diff --git a/gdb/testsuite/gdb.base/large-frame.h b/gdb/testsuite/gdb.base/large-frame.h new file mode 100644 index 0000000000..17058a5efd --- /dev/null +++ b/gdb/testsuite/gdb.base/large-frame.h @@ -0,0 +1,24 @@ +/* This file is part of GDB, the GNU debugger. + + Copyright 2018 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 . */ + +#ifndef LARGE_FRAME_H +#define LARGE_FRAME_H + +extern void blah (int *); +extern int func (void); + +#endif /* LARGE_FRAME_H */