summaryrefslogtreecommitdiff
path: root/opcodes
diff options
context:
space:
mode:
authorAndrew Burgess <aburgess@redhat.com>2023-03-13 13:17:43 +0000
committerAndrew Burgess <aburgess@redhat.com>2023-04-03 12:35:08 +0100
commit29caf11836611478a1fb32283b07e6777dfa5c28 (patch)
treef7006a9189cc81ff88a62375e150b8335439f6c9 /opcodes
parent3ad6e510cd59b77e9f179eb01f0c52bf46fb7c42 (diff)
downloadbinutils-gdb-29caf11836611478a1fb32283b07e6777dfa5c28.tar.gz
gdb/riscv: fix regressions in gdb.base/unwind-on-each-insn.exp
This commit builds on the previous one to fix all the remaining failures in gdb.base/unwind-on-each-insn.exp for RISC-V. The problem we have in gdb.base/unwind-on-each-insn.exp is that, when we are in the function epilogue, the previous frame and stack pointer values are being restored, and so, the values that we calculated during the function prologue are no longer suitable. Here's an example from the function 'bar' in the mentioned test. This was compiled for 64-bit RISC-V with compressed instruction support: Dump of assembler code for function bar: 0x000000000001018a <+0>: add sp,sp,-32 0x000000000001018c <+2>: sd ra,24(sp) 0x000000000001018e <+4>: sd fp,16(sp) 0x0000000000010190 <+6>: add fp,sp,32 0x0000000000010192 <+8>: sd a0,-24(fp) 0x0000000000010196 <+12>: ld a0,-24(fp) 0x000000000001019a <+16>: jal 0x10178 <foo> 0x000000000001019e <+20>: nop 0x00000000000101a0 <+22>: ld ra,24(sp) 0x00000000000101a2 <+24>: ld fp,16(sp) 0x00000000000101a4 <+26>: add sp,sp,32 0x00000000000101a6 <+28>: ret End of assembler dump. When we are at address 0x101a4 the previous instruction has restored the frame-pointer, as such GDB's (current) preference for using the frame-pointer as the frame base address is clearly not going to work. We need to switch to using the stack-pointer instead. At address 0x101a6 the previous instruction has restored the stack-pointer value. Currently GDB will not understand this and so will still assume the stack has been decreased by 32 bytes in this function. My proposed solution is to extend GDB such that GDB will scan the instructions at the current $pc looking for this pattern: ld fp,16(sp) add sp,sp,32 ret Obviously the immediates can change, but the basic pattern indicates that the function is in the process of restoring state before returning. If GDB sees this pattern then GDB can use the inferior's position within this instruction sequence to help calculate the correct frame-id. With this implemented then gdb.base/unwind-on-each-insn.exp now fully passes. Obviously what I've implemented is just a heuristic. It's not going to work for every function. If the compiler reorders the instructions, or merges the epilogue back into the function body then GDB is once again going to get the frame-id wrong. I'm OK with that, we're no worse off that we are right now in that situation (plus we can always improve the heuristic later). Remember, this is for debugging code without debug information, and (in our imagined situation) with more aggressive levels of optimisation being used. Obviously GDB is going to struggle in these situations. My thinking is, lets get something in place now. Then, later, if possible, we might be able to improve the logic to cover more situations -- if there's an interest in doing so. But I figure we need something in place as a starting point. After this commit gdb.base/unwind-on-each-insn.exp passes with no failures on RV64.
Diffstat (limited to 'opcodes')
0 files changed, 0 insertions, 0 deletions