[PATCH RESEND] Fix AArch64 prologue analysis for functions using Shadow Call Stack

Jethro Beekman jethro@jbeekman.nl
Tue Jul 16 08:08:23 GMT 2024


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(+)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index e4bca6c6632..15542af3488 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -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 */
-- 
2.45.2



More information about the Gdb-patches mailing list