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

Message ID 2b95f92d-33cd-4c92-9abf-ffb7a61bcf65@jbeekman.nl
State New
Headers
Series [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

Jethro Beekman July 16, 2024, 8:08 a.m. UTC
  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(+)
  

Patch

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 */