summaryrefslogtreecommitdiff
path: root/gdb/riscv-tdep.c
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2020-10-27 15:31:53 +0000
committerAndrew Burgess <andrew.burgess@embecosm.com>2020-11-02 09:07:05 +0000
commite1f57067b162cba9f39e087726c7a2f2cfaae96f (patch)
tree713c49148ef348592b6b7999c64b318567e5db58 /gdb/riscv-tdep.c
parent8807d3127cb4b9199a3d5a16aa2851cc28e9826c (diff)
gdb/riscv: read frame base register as unsigned in the unwinder
I noticed an issue with the RISC-V prologue scanning stack unwinder. We currently read the frame base register (either $sp or $fp) as a signed value. This means that the frame_id's stack_addr field will be a signed value. In other contexts though these registers are data pointers, and so are unsigned. There's not many places where this mismatch actually shows though, but I did find one place. Consider this GDB session: (gdb) maintenance set dwarf unwinders off (gdb) set backtrace past-main on ... (gdb) b main Breakpoint 1 at 0x20400344: file main.c, line 86. (gdb) run ... (gdb) bt #0 main () at main.c:86 #1 0x2040005c in _start () at start.S:59 Backtrace stopped: frame did not save the PC (gdb) info frame 1 Stack frame at 0x80000a1c: pc = 0x2040005c in _start (start.S:59); saved pc = <not saved> Outermost frame: frame did not save the PC caller of frame at 0x80000a1c source language asm. Arglist at 0x80000a1c, args: Locals at 0x80000a1c, Previous frame's sp is 0x80000a1c (gdb) frame address 0x80000a1c No frame at address 0x80000a1c. (gdb) frame address 0xffffffff80000a1c #1 0x2040005c in _start () at start.S:59 59 call main Notice that the 'info frame 1' reports that the frame is at '0x80000a1c', this is the unsigned frame base value, but when I try to select a frame using this address I can't. The reason is that the frame_id for frame #1 actually has the unsigned (and hence sign-extended) stack_addr value. When I use the sign extended address I can correctly select the frame. I propose changing the prologue scanning unwinder to read the frame base as unsigned. After this in the above case I can now do this: (gdb) frame address 0x80000a1c #1 0x2040005c in _start () at start.S:59 59 call main (gdb) frame address 0xffffffff80000a1c No frame at address 0xffffffff80000a1c. Which I think makes more sense. This issue causes failures in gdb.base/frame-selection.exp if you compile for RV32 with a linker script that places the stack in the correct location, which are resolved by this patch. gdb/ChangeLog: * riscv-tdep.c (riscv_frame_cache): Read the frame base register as an unsigned value.
Diffstat (limited to 'gdb/riscv-tdep.c')
-rw-r--r--gdb/riscv-tdep.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 2c4eeab720..e18f953eb1 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -2942,7 +2942,7 @@ riscv_frame_cache (struct frame_info *this_frame, void **this_cache)
/* We can now calculate the frame base address. */
cache->frame_base
- = (get_frame_register_signed (this_frame, cache->frame_base_reg)
+ = (get_frame_register_unsigned (this_frame, cache->frame_base_reg)
+ cache->frame_base_offset);
if (riscv_debug_unwinder)
fprintf_unfiltered (gdb_stdlog, "Frame base is %s ($%s + 0x%x)\n",