From: Luis Machado Date: Wed, 1 Dec 2021 11:23:24 +0000 (-0300) Subject: Adjust PCC bounds when calling a function by hand in AAPCS64-CAP X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7e3d91f8199006eedcb87b0a86c96a313c4d5f14;p=thirdparty%2Fbinutils-gdb.git Adjust PCC bounds when calling a function by hand in AAPCS64-CAP For dynamically-linked binaries using the AAPCS64-CAP ABI, the PCC bounds for distinct DSO's can be different, and that needs to be taken into account. Since there isn't a good interface for GDB to fetch the precise bounds (the .plt.got could be used for this, but doesn't contain data for symbols not being used by the program), we use maximum bounds and the existing PCC permissions. This allows GDB to call functions by hand in AAPCS64-CAP mode. Also, revert a previous change to do partial writes (lower 64 bits) of the PCC, as this isn't needed anymore. --- diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 1badb114770..5e29e72169f 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -5363,6 +5363,33 @@ aarch64_register_tag (struct gdbarch *gdbarch, return true; } +/* Morello-specific hook to write the PC. This is mostly used when calling + a function by hand. Different DSO's have different bounds for PCC, so GDB + would need to figure out those bounds. + + Given that information is not currently available, we set maximum bounds + for PCC as a compromise. */ + +static void +morello_write_pc (struct regcache *regs, CORE_ADDR pc) +{ + struct gdbarch *gdbarch = regs->arch (); + aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch); + + 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; + regs->cooked_write_part (tdep->cap_reg_pcc, 8, sizeof (pc), + (const gdb_byte *) &pc); + + /* 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. */ +} + /* Initialize the current architecture based on INFO. If possible, re-use an architecture from ARCHES, which is a list of architectures already created during this debugging session. @@ -5712,13 +5739,21 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Set address class hooks for capabilities. */ if (feature_capability) { - set_gdbarch_sp_regnum (gdbarch, tdep->cap_reg_csp); - set_gdbarch_pc_regnum (gdbarch, tdep->cap_reg_pcc); - - /* Morello-specific implementations for function calls and returning - of results. */ - set_gdbarch_push_dummy_call (gdbarch, morello_push_dummy_call); - set_gdbarch_return_value (gdbarch, morello_return_value); + if (have_capability) + { + /* These hooks only make sense if we are using the AAPCS64-CAP + ABI. */ + set_gdbarch_sp_regnum (gdbarch, tdep->cap_reg_csp); + set_gdbarch_pc_regnum (gdbarch, tdep->cap_reg_pcc); + + /* Hook to adjust the PCC bounds. */ + set_gdbarch_write_pc (gdbarch, morello_write_pc); + + /* Morello-specific implementations for function calls and returning + of results. */ + set_gdbarch_push_dummy_call (gdbarch, morello_push_dummy_call); + set_gdbarch_return_value (gdbarch, morello_return_value); + } /* Address manipulation. */ set_gdbarch_addr_bits_remove (gdbarch, aarch64_addr_bits_remove); diff --git a/gdb/regcache.c b/gdb/regcache.c index 12daa98826d..47fd6a6ac41 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -1366,22 +1366,11 @@ regcache_write_pc (struct regcache *regcache, CORE_ADDR pc) { struct gdbarch *gdbarch = regcache->arch (); int regnum = gdbarch_pc_regnum (gdbarch); - int reg_size = register_size (gdbarch, regnum); if (gdbarch_write_pc_p (gdbarch)) gdbarch_write_pc (gdbarch, regcache, pc); else if (gdbarch_pc_regnum (gdbarch) >= 0) - { - /* If our PC is bigger than a CORE_ADDR, only modify the required - bits. Leave the unmodified bits alone. */ - if (reg_size > sizeof (pc)) - regcache->cooked_write_part (regnum, 0, sizeof (pc), - (const gdb_byte *) &pc); - else - { - regcache_cooked_write_unsigned (regcache, regnum, pc); - } - } + regcache_cooked_write_unsigned (regcache, regnum, pc); else internal_error (__FILE__, __LINE__, _("regcache_write_pc: Unable to update PC"));