From e843807b2df9f99b8172bfaf4daa3a42461cdbfa Mon Sep 17 00:00:00 2001 From: Lancelot SIX Date: Fri, 16 Jul 2021 22:10:08 +0000 Subject: gdb: Support stepping out from signal handler on riscv*-linux Currently, gdb cannot step outside of a signal handler on RISC-V platforms. This causes multiple failures in gdb.base/sigstep.exp: FAIL: gdb.base/sigstep.exp: continue to handler, nothing in handler, step from handler: leave handler (timeout) FAIL: gdb.base/sigstep.exp: continue to handler, si+advance in handler, step from handler: leave handler (timeout) FAIL: gdb.base/sigstep.exp: continue to handler, nothing in handler, next from handler: leave handler (timeout) FAIL: gdb.base/sigstep.exp: continue to handler, si+advance in handler, next from handler: leave handler (timeout) FAIL: gdb.base/sigstep.exp: stepi from handleri: leave signal trampoline FAIL: gdb.base/sigstep.exp: nexti from handleri: leave signal trampoline === gdb Summary === # of expected passes 587 # of unexpected failures 6 This patch adds support for stepping outside of a signal handler on riscv*-*-linux*. Implementation is heavily inspired from mips_linux_syscall_next_pc and surroundings as advised by Pedro Alves. After this patch, all tests in gdb.base/sigstep.exp pass. Build and tested on riscv64-linux-gnu. --- gdb/riscv-tdep.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'gdb/riscv-tdep.c') diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 19e2616..b5b0d2d 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -1421,6 +1421,8 @@ public: /* These are needed for stepping over atomic sequences. */ LR, SC, + /* This instruction is used to do a syscall. */ + ECALL, /* Other instructions are not interesting during the prologue scan, and are ignored. */ @@ -1711,6 +1713,8 @@ riscv_insn::decode (struct gdbarch *gdbarch, CORE_ADDR pc) decode_r_type_insn (SC, ival); else if (is_sc_d_insn (ival)) decode_r_type_insn (SC, ival); + else if (is_ecall_insn (ival)) + decode_i_type_insn (ECALL, ival); else /* None of the other fields are valid in this case. */ m_opcode = OTHER; @@ -3764,6 +3768,7 @@ static CORE_ADDR riscv_next_pc (struct regcache *regcache, CORE_ADDR pc) { struct gdbarch *gdbarch = regcache->arch (); + const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); struct riscv_insn insn; CORE_ADDR next_pc; @@ -3826,6 +3831,11 @@ riscv_next_pc (struct regcache *regcache, CORE_ADDR pc) if (src1 >= src2) next_pc = pc + insn.imm_signed (); } + else if (insn.opcode () == riscv_insn::ECALL) + { + if (tdep->syscall_next_pc != nullptr) + next_pc = tdep->syscall_next_pc (get_current_frame ()); + } return next_pc; } -- cgit v1.1