From: Luis Machado Date: Mon, 28 Sep 2020 14:06:30 +0000 (-0300) Subject: [Morello] Fix displaced stepping LSB adjustment and add debugging output X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f281d14e9cca1cb250ad24c062639c2054629253;p=thirdparty%2Fbinutils-gdb.git [Morello] Fix displaced stepping LSB adjustment and add debugging output This patch fixes cases where the LSB of a pure cap function isn't cleared when we use it for address arithmetic. Also adds debugging output. gdb/ChangeLog: 2020-10-20 Luis Machado * aarch64-tdep.c (aarch64_displaced_step_data) : New field. (aarch64_displaced_step_b): Add debugging output. (aarch64_displaced_step_copy_insn): Initialize the gdbarch member. (aarch64_pointer_to_address, aarch64_address_to_pointer) (aarch64_integer_to_address): Add debugging output. * arch/aarch64-insn.c (aarch64_decode_b, aarch64_decode_bcond) (aarch64_decode_cb, aarch64_decode_tb) (aarch64_decode_ldr_literal): Refactor and add debugging output. * infrun.c (displaced_step_prepare_throw): Clear LSB bits. --- diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 7c9d238fe2d..01d1e327da3 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -3070,6 +3070,8 @@ struct aarch64_displaced_step_data unsigned insn_count; /* Registers when doing displaced stepping. */ struct regcache *regs; + /* The gdbarch. */ + struct gdbarch *gdbarch; aarch64_displaced_step_copy_insn_closure *dsc; }; @@ -3083,6 +3085,15 @@ aarch64_displaced_step_b (const int is_bl, const int32_t offset, struct aarch64_displaced_step_data *dsd = (struct aarch64_displaced_step_data *) data; int64_t new_offset = data->insn_addr - dsd->new_addr + offset; + struct gdbarch *gdbarch = dsd->gdbarch; + + if (aarch64_debug) + debug_printf ("aarch64_displaced_step_b: Insn address %s, offset %s\n" + "new_offset: %s, new_addr: %s", + paddress (gdbarch, data->insn_addr), + paddress (gdbarch, offset), + paddress (gdbarch, new_offset), + paddress (gdbarch, dsd->new_addr)); if (can_encode_int32 (new_offset, 28)) { @@ -3312,6 +3323,7 @@ aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch, dsd.base.insn_addr = from; dsd.new_addr = to; dsd.regs = regs; + dsd.gdbarch = gdbarch; dsd.dsc = dsc.get (); dsd.insn_count = 0; aarch64_relocate_instruction (insn, &visitor, @@ -3572,6 +3584,9 @@ aarch64_pointer_to_address (struct gdbarch *gdbarch, struct type *type, { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + if (aarch64_debug) + debug_printf ("aarch64: Entering %s\n", __func__); + if (type->length <= 8) return signed_pointer_to_address (gdbarch, type, buf); else @@ -3580,6 +3595,9 @@ aarch64_pointer_to_address (struct gdbarch *gdbarch, struct type *type, the extra information. */ return extract_unsigned_integer (buf, 8, byte_order); } + + if (aarch64_debug) + debug_printf ("aarch64: Exiting %s\n", __func__); } /* Implements the gdbarch_address_to_pointer hook. */ @@ -3590,6 +3608,9 @@ aarch64_address_to_pointer (struct gdbarch *gdbarch, struct type *type, { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + if (aarch64_debug) + debug_printf ("aarch64: Entering %s\n", __func__); + if (type->length <= 8) address_to_signed_pointer (gdbarch, type, buf, addr); else @@ -3598,6 +3619,9 @@ aarch64_address_to_pointer (struct gdbarch *gdbarch, struct type *type, memset (buf, 0, type->length); store_unsigned_integer (buf, 8, byte_order, addr); } + + if (aarch64_debug) + debug_printf ("aarch64: Exiting %s\n", __func__); } /* Implements the gdbarch_integer_to_address hook. */ @@ -3606,7 +3630,13 @@ static CORE_ADDR aarch64_integer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf) { + if (aarch64_debug) + debug_printf ("aarch64: Entering %s\n", __func__); + return aarch64_pointer_to_address (gdbarch, type, buf); + + if (aarch64_debug) + debug_printf ("aarch64: Exiting %s\n", __func__); } /* Remove useless bits from addresses in a running program. This is diff --git a/gdb/arch/aarch64-insn.c b/gdb/arch/aarch64-insn.c index 3a3104f1c6a..2c51b90db1e 100644 --- a/gdb/arch/aarch64-insn.c +++ b/gdb/arch/aarch64-insn.c @@ -91,6 +91,11 @@ int aarch64_decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl, int32_t *offset) { + if (aarch64_debug) + debug_printf ("aarch64: Entering %s\n", __func__); + + int retval = 0; + /* b 0001 01ii iiii iiii iiii iiii iiii iiii */ /* bl 1001 01ii iiii iiii iiii iiii iiii iiii */ if (decode_masked_match (insn, 0x7c000000, 0x14000000)) @@ -106,9 +111,13 @@ aarch64_decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl, core_addr_to_string_nz (addr + *offset)); } - return 1; + retval = 1; } - return 0; + + if (aarch64_debug) + debug_printf ("aarch64: Exiting %s\n", __func__); + + return retval; } /* Decode an opcode if it represents a conditional branch instruction. @@ -125,6 +134,11 @@ int aarch64_decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond, int32_t *offset) { + if (aarch64_debug) + debug_printf ("aarch64: Entering %s\n", __func__); + + int retval = 0; + /* b.cond 0101 0100 iiii iiii iiii iiii iii0 cccc */ if (decode_masked_match (insn, 0xff000010, 0x54000000)) { @@ -137,9 +151,13 @@ aarch64_decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond, core_addr_to_string_nz (addr), insn, *cond, core_addr_to_string_nz (addr + *offset)); } - return 1; + retval = 1; } - return 0; + + if (aarch64_debug) + debug_printf ("aarch64: Exiting %s\n", __func__); + + return retval; } /* Decode an opcode if it represents a CBZ or CBNZ instruction. @@ -157,6 +175,11 @@ int aarch64_decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, int *is_cbnz, unsigned *rn, int32_t *offset) { + if (aarch64_debug) + debug_printf ("aarch64: Entering %s\n", __func__); + + int retval = 0; + /* cbz T011 010o iiii iiii iiii iiii iiir rrrr */ /* cbnz T011 010o iiii iiii iiii iiii iiir rrrr */ if (decode_masked_match (insn, 0x7e000000, 0x34000000)) @@ -173,9 +196,13 @@ aarch64_decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, int *is_cbnz, *is_cbnz ? "cbnz" : "cbz", core_addr_to_string_nz (addr + *offset)); } - return 1; + retval = 1; } - return 0; + + if (aarch64_debug) + debug_printf ("aarch64: Exiting %s\n", __func__); + + return retval; } /* Decode an opcode if it represents a TBZ or TBNZ instruction. @@ -193,6 +220,11 @@ int aarch64_decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz, unsigned *bit, unsigned *rt, int32_t *imm) { + if (aarch64_debug) + debug_printf ("aarch64: Entering %s\n", __func__); + + int retval = 0; + /* tbz b011 0110 bbbb biii iiii iiii iiir rrrr */ /* tbnz B011 0111 bbbb biii iiii iiii iiir rrrr */ if (decode_masked_match (insn, 0x7e000000, 0x36000000)) @@ -209,9 +241,13 @@ aarch64_decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz, *is_tbnz ? "tbnz" : "tbz", *rt, *bit, core_addr_to_string_nz (addr + *imm)); } - return 1; + retval = 1; } - return 0; + + if (aarch64_debug) + debug_printf ("aarch64: Exiting %s\n", __func__); + + return retval; } /* Decode an opcode if it represents an LDR or LDRSW instruction taking a @@ -230,6 +266,11 @@ int aarch64_decode_ldr_literal (CORE_ADDR addr, uint32_t insn, int *is_w, int *is64, unsigned *rt, int32_t *offset) { + if (aarch64_debug) + debug_printf ("aarch64: Entering %s\n", __func__); + + int retval = 0; + /* LDR 0T01 1000 iiii iiii iiii iiii iiir rrrr */ /* LDRSW 1001 1000 iiii iiii iiii iiii iiir rrrr */ if ((insn & 0x3f000000) == 0x18000000) @@ -253,10 +294,13 @@ aarch64_decode_ldr_literal (CORE_ADDR addr, uint32_t insn, int *is_w, *is_w ? "ldrsw" : "ldr", *is64 ? "x" : "w", *rt); - return 1; + retval = 1; } - return 0; + if (aarch64_debug) + debug_printf ("aarch64: Exiting %s\n", __func__); + + return retval; } /* Visit an instruction INSN by VISITOR with all needed information in DATA. diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index 528c9beea66..517d3bd884b 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -2556,6 +2556,10 @@ linux_displaced_step_location (struct gdbarch *gdbarch) throw_error (NOT_SUPPORTED_ERROR, _("Cannot find AT_ENTRY auxiliary vector entry.")); + /* Some architectures like AArch64 Morello have the LSB set for addresses + in the text segment (pure capability ABI). */ + addr = gdbarch_addr_bits_remove (gdbarch, addr); + /* Make certain that the address points at real code, and not a function descriptor. */ addr = gdbarch_convert_from_func_ptr_addr