From: Luis Machado Date: Mon, 3 Apr 2023 12:58:12 +0000 (+0100) Subject: Handle newer Morello Linux Kernels that set more restrictive bounds X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f103ba71c7b773b9caaf93aa834e2005699b644d;p=thirdparty%2Fbinutils-gdb.git 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. --- diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 9c010cc0edc..ee0e99e854d 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,