diff options
author | Luis Machado <luis.machado@arm.com> | 2023-04-03 13:58:12 +0100 |
---|---|---|
committer | Luis Machado <luis.machado@arm.com> | 2023-04-05 09:32:28 +0100 |
commit | f103ba71c7b773b9caaf93aa834e2005699b644d (patch) | |
tree | 442be957a0207e573f74e3d2583a779fdc8daae0 | |
parent | f6e8c7228463a552d175211f4fcea93cca889686 (diff) | |
download | gdb-f103ba71c7b773b9caaf93aa834e2005699b644d.zip gdb-f103ba71c7b773b9caaf93aa834e2005699b644d.tar.gz gdb-f103ba71c7b773b9caaf93aa834e2005699b644d.tar.bz2 |
Handle newer Morello Linux Kernels that set more restrictive bounds
Newer Morello Linux Kernels set more restrictive bounds in general [1], and
that is also true for CSP.
Adjust Morello GDB to cope with this, otherwise it will run into a tag fault
when attempting to start a program or call a function by hand.
-rw-r--r-- | gdb/aarch64-tdep.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 9c010cc..ee0e99e 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -5313,18 +5313,39 @@ morello_write_pc (struct regcache *regs, CORE_ADDR pc) struct gdbarch *gdbarch = regs->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + CORE_ADDR current_pc = 0; + + /* Read the lower 64 bits of the PCC and check if the PC we want to set it + to is the same or not. If it is the same, gdb is likely moving the + inferior. In that case we don't need to adjust the upper 64 bits and + tag of the PCC. Just return. */ + regs->cooked_read_part (tdep->cap_reg_pcc, 0, sizeof (pc), + (gdb_byte *) ¤t_pc); + + if (pc == current_pc) + return; + + /* Otherwise gdb is trying to do some other more complex operation, like + trying to do displaced stepping or a manual function call. In that case, + we do need to update the upper 64 bits of PCC and force the tag to 1. + + The strategy here is to rely on the bounds used by the CSP register, as + that gives us a broad range we can use. The PCC may have narrower + bounds, but at the moment there isn't a good way for gdb to find out + the precise bounds to use. */ regs->cooked_write_part (tdep->cap_reg_pcc, 0, sizeof (pc), (const gdb_byte *) &pc); - /* Upper 64 bits of the capability with maximum bounds and reasonable - permissions. We only adjust this if we are using the purecap ABI. */ - pc = 0xffffc00000010005; + /* Read the upper 64 bits of CSP. */ + CORE_ADDR bounds = 0; + regs->cooked_read_part (tdep->cap_reg_csp, 8, sizeof (bounds), + (gdb_byte *) &bounds); + + /* Set the upper 64 bits of PCC to the upper bits of CSP. */ regs->cooked_write_part (tdep->cap_reg_pcc, 8, sizeof (pc), - (const gdb_byte *) &pc); + (const gdb_byte *) &bounds); - /* We may need to set the tag of the PCC here, but we don't do so at the - moment. If this turns out to be a problem in the future, we should - force the tag to 1. */ + aarch64_register_set_tag (gdbarch, regs, tdep->cap_reg_pcc, true); } /* Initialize the current architecture based on INFO. If possible, |