commit 221194ec9eaa7113ff90632adbb68e0881f07467 Author: Jiong Wang Date: Fri Aug 4 17:14:15 2017 +0100 [Patch 4] diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index b505013..5f7a5a2 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -453,6 +453,40 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch, /* Stop analysis on branch. */ break; } + else if (inst.opcode->iclass == ic_system) + { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + /* Record the state of return address. + 1 means it is mangled, otherwise 0. */ + int ra_state_val = 0; + + /* PACIASP (HINT 25). + we can't match the name because PACIASP is an alias of HINT while + we are passing a TRUE noaliases_p to aarch64_decode_insn. */ + if (insn == 0xd503233f) + ra_state_val = 1; + /* AUTIASP (HINT 29). */ + else if (insn == 0xd50323bf) + ra_state_val = 0; + else + { + if (aarch64_debug) + { + debug_printf ("aarch64: prologue analysis gave up addr=%s" + " opcode=0x%x\n", + core_addr_to_string_nz (start), insn); + } + break; + } + + if (aarch64_tdep_has_pauth_p (tdep) && cache != NULL) + { + int ra_state = (tdep->regnum.pauth_ra_state_regnum + + gdbarch_num_regs (gdbarch)); + + trad_frame_set_value (cache->saved_regs, ra_state, ra_state_val); + } + } else { if (aarch64_debug) @@ -644,6 +678,58 @@ aarch64_analyze_prologue_test (void) == -1); } } + + /* Test a prologue in which there is return address signing instruction. */ + { + struct aarch64_prologue_cache cache; + cache.saved_regs = trad_frame_alloc_saved_regs (gdbarch); + + struct gdbarch_info info; + + gdbarch_info_init (&info); + info.bfd_arch_info = bfd_scan_arch ("aarch64"); + info.target_desc = tdesc_aarch64_pauth; + + struct gdbarch *gdbarch = gdbarch_find_by_info (info); + SELF_CHECK (gdbarch != NULL); + + int ra_state = (gdbarch_tdep (gdbarch)->regnum.pauth_ra_state_regnum + + gdbarch_num_regs (gdbarch)); + + static const uint32_t insns[] = { + 0xd503233f, /* paciasp (hint 25) */ + 0xa9bd7bfd, /* stp x29, x30, [sp, #-48]! */ + 0x910003fd, /* mov x29, sp */ + 0xf801c3f3, /* str x19, [sp, #28] */ + 0xb9401fa0, /* ldr x19, [x29, #28] */ + }; + instruction_reader_test reader (insns); + + CORE_ADDR end = aarch64_analyze_prologue (gdbarch, 0, 128, &cache, reader); + + SELF_CHECK (end == 4 * 4); + + SELF_CHECK (cache.framereg == AARCH64_FP_REGNUM); + SELF_CHECK (cache.framesize == 48); + + for (int i = 0; i < AARCH64_X_REGISTER_COUNT; i++) + { + if (i == 19) + SELF_CHECK (cache.saved_regs[i].addr == -20); + else if (i == AARCH64_FP_REGNUM) + SELF_CHECK (cache.saved_regs[i].addr == -48); + else if (i == AARCH64_LR_REGNUM) + SELF_CHECK (cache.saved_regs[i].addr == -40); + else + SELF_CHECK (cache.saved_regs[i].addr == -1); + } + + if (aarch64_tdep_has_pauth_p (gdbarch_tdep (gdbarch))) + { + SELF_CHECK (trad_frame_value_p (cache.saved_regs, ra_state)); + SELF_CHECK (cache.saved_regs[ra_state].addr == 1); + } + } } } // namespace selftests #endif /* GDB_SELF_TEST */ @@ -853,8 +939,30 @@ aarch64_prologue_prev_register (struct frame_info *this_frame, if (prev_regnum == AARCH64_PC_REGNUM) { CORE_ADDR lr; + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); lr = frame_unwind_register_unsigned (this_frame, AARCH64_LR_REGNUM); + + if (aarch64_tdep_has_pauth_p (tdep)) + { + int ra_state_regno = (tdep->regnum.pauth_ra_state_regnum + + gdbarch_num_regs (gdbarch)); + if (trad_frame_value_p (cache->saved_regs, ra_state_regno)) + { + CORE_ADDR ra_state + = frame_unwind_register_unsigned (this_frame, ra_state_regno); + + if (ra_state) + { + int cmask_num = tdep->regnum.pauth_reg_base + 1; + CORE_ADDR cmask + = frame_unwind_register_unsigned (this_frame, cmask_num); + lr = lr & ~cmask; + } + } + } + return frame_unwind_got_constant (this_frame, prev_regnum, lr); }