[RESEND] Fix AArch64 prologue analysis for functions using Shadow Call Stack
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-arm |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 |
success
|
Test passed
|
Commit Message
When code is compiled with Shadow Call Stack (SCS) enabled, the compiler
inserts instructions to manage the SCS in the prologue. Update the AArch64
prologue analysis to account for such instructions.
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102768
---
gdb/aarch64-tdep.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
@@ -574,6 +574,16 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
cache->saved_regs[regnum].set_value (ra_state_val);
}
}
+ else if (inst.opcode->iclass == ldst_imm9
+ && inst.operands[0].type == AARCH64_OPND_Rt
+ && inst.operands[0].addr.base_regno == AARCH64_LR_REGNUM
+ && inst.operands[1].type == AARCH64_OPND_ADDR_SIMM9
+ && inst.operands[1].addr.base_regno == 18 /* platform register */
+ && inst.operands[1].addr.postind
+ && strcmp ("str", inst.opcode->name) == 0)
+ {
+ /* ShadowCallStack - ignore for prologue analysis. */
+ }
else
{
aarch64_debug_printf ("prologue analysis gave up addr=%s"
@@ -947,6 +957,44 @@ aarch64_analyze_prologue_test (void)
&& cache.saved_regs[i].realreg () == i);
}
}
+
+ /* Test a prologue with ShadowCallStack. */
+ {
+ static const uint32_t insns[] = {
+ 0xf800865e, /* str x30, [x18], #8 */
+ 0xa9af7bfd, /* stp x29, x30, [sp,#-272]! */
+ 0x910003fd, /* mov x29, sp */
+ 0x97ffffe6, /* bl 0x400580 */
+ };
+ instruction_reader_test reader (insns);
+
+ trad_frame_reset_saved_regs (gdbarch, cache.saved_regs);
+ CORE_ADDR end = aarch64_analyze_prologue (gdbarch, 0, 128, &cache, reader);
+ SELF_CHECK (end == 4 * 3);
+
+ SELF_CHECK (cache.framereg == AARCH64_FP_REGNUM);
+ SELF_CHECK (cache.framesize == 272);
+
+ for (int i = 0; i < AARCH64_X_REGISTER_COUNT; i++)
+ {
+ if (i == AARCH64_FP_REGNUM)
+ SELF_CHECK (cache.saved_regs[i].addr () == -272);
+ else if (i == AARCH64_LR_REGNUM)
+ SELF_CHECK (cache.saved_regs[i].addr () == -264);
+ else
+ SELF_CHECK (cache.saved_regs[i].is_realreg ()
+ && cache.saved_regs[i].realreg () == i);
+ }
+
+ for (int i = 0; i < AARCH64_D_REGISTER_COUNT; i++)
+ {
+ int num_regs = gdbarch_num_regs (gdbarch);
+ int regnum = i + num_regs + AARCH64_D0_REGNUM;
+
+ SELF_CHECK (cache.saved_regs[regnum].is_realreg ()
+ && cache.saved_regs[regnum].realreg () == regnum);
+ }
+ }
}
} // namespace selftests
#endif /* GDB_SELF_TEST */