[PATCH v2 4/7] Add aarch64-specific SEH commands

Evgeny Karpov Evgeny.Karpov@microsoft.com
Fri May 9 11:07:42 GMT 2025


Implementation for aarch64 contains SEH commands that are not present for
x64 architecture, such as .seh_startepilogue/.seh_endepilogue,
.seh_save_reg*, .seh_save_freg*, and others.

gas/ChangeLog:

	* config/obj-coff-seh.c (defined): Use COFFAARCH64 guard.
	(obj_coff_seh_startepilogue): New.
	(obj_coff_seh_endepilogue): New.
	(obj_coff_seh_endfunclet): New.
	(obj_coff_seh_save_reg): New.
---
 gas/config/obj-coff-seh.c | 138 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 138 insertions(+)

diff --git a/gas/config/obj-coff-seh.c b/gas/config/obj-coff-seh.c
index d861be4418e..8f9562ee234 100644
--- a/gas/config/obj-coff-seh.c
+++ b/gas/config/obj-coff-seh.c
@@ -681,6 +681,86 @@ obj_coff_seh_endprologue (int what ATTRIBUTE_UNUSED)
     }
 }
 
+#if defined (COFFAARCH64)
+static void
+obj_coff_seh_startepilogue (int what ATTRIBUTE_UNUSED)
+{
+  symbolS *epilogue_start_addr;
+  expressionS exp;
+
+  if (!verify_context (".seh_startepilogue")
+      || !seh_validate_seg (".seh_startepilogue"))
+    return;
+  demand_empty_rest_of_line ();
+
+  if (seh_get_target_kind () != seh_kind_arm64)
+    return;
+
+  epilogue_start_addr = symbol_temp_new_now ();
+  exp.X_op = O_subtract;
+  exp.X_add_symbol = epilogue_start_addr;
+  exp.X_op_symbol = seh_ctx_cur->start_addr;
+  exp.X_add_number = 0;
+
+  if (!resolve_expression (&exp) || exp.X_op != O_constant
+      || exp.X_add_number < 0)
+    as_bad (_(".seh_startepilog offset expression for %s "
+      "does not evaluate to a non-negative constant"),
+      S_GET_NAME (epilogue_start_addr));
+
+  seh_arm64_epilogue_scope *epilogue_scope;
+  epilogue_scope = seh_ctx_cur->arm64_ctx.epilogue_scopes
+    + seh_ctx_cur->arm64_ctx.epilogue_scopes_count;
+  epilogue_scope->epilogue_start_offset = exp.X_add_number / 4;
+  epilogue_scope->reserved = 0;
+  epilogue_scope->epilogue_start_index
+    = seh_ctx_cur->arm64_ctx.unwind_codes_byte_count;
+  seh_ctx_cur->arm64_ctx.epilogue_scopes_count++;
+}
+
+static void
+obj_coff_seh_endepilogue (int what ATTRIBUTE_UNUSED)
+{
+  if (!verify_context (".seh_endepilogue")
+      || !seh_validate_seg (".seh_endepilogue"))
+    return;
+
+  demand_empty_rest_of_line ();
+
+  expressionS exp;
+  symbolS *epilogue_end_addr = symbol_temp_new_now ();
+  exp.X_op = O_subtract;
+  exp.X_add_symbol = epilogue_end_addr;
+  exp.X_op_symbol = seh_ctx_cur->start_addr;
+  exp.X_add_number = 0;
+
+  if (!resolve_expression (&exp) || exp.X_op != O_constant
+      || exp.X_add_number < 0)
+    as_bad (_(".seh_endepilogue offset expression for %s "
+      "does not evaluate to a non-negative constant"),
+      S_GET_NAME (epilogue_end_addr));
+
+   seh_arm64_epilogue_scope *epilogue_scope;
+   epilogue_scope = seh_ctx_cur->arm64_ctx.epilogue_scopes
+     + seh_ctx_cur->arm64_ctx.epilogue_scopes_count - 1;
+
+   epilogue_scope->epilogue_end_offset = exp.X_add_number;
+
+  /* End code.  */
+  seh_arm64_add_unwind_element (end, 0, 0);
+}
+
+static void
+obj_coff_seh_endfunclet (int what ATTRIBUTE_UNUSED)
+{
+  if (!verify_context (".seh_endfunclet")
+      || !seh_validate_seg (".seh_endfunclet"))
+    return;
+
+  demand_empty_rest_of_line ();
+}
+#endif
+
 /* End-of-file hook.  */
 
 void
@@ -866,6 +946,64 @@ obj_coff_seh_save (int what)
 }
 #endif
 
+#if defined (COFFAARCH64)
+static void
+obj_coff_seh_save_reg (int type)
+{
+  if (type < 0 || type > unwind_last_type)
+    {
+      as_bad (_("invalid pseudo operation."));
+      return;
+    }
+
+  const struct unwind_code_pack_info *unwind_code_pack_info;
+  unwind_code_pack_info = unwind_code_pack_infos + type;
+
+  if (!unwind_code_pack_info->directive
+      || !verify_context_and_target (unwind_code_pack_info->directive,
+      seh_kind_arm64)
+      || !seh_validate_seg (unwind_code_pack_info->directive))
+    return;
+
+  SKIP_WHITESPACE ();
+
+  char *symbol_name = NULL;
+  int reg = -1;
+
+  if (unwind_code_pack_info->reg_bits)
+    {
+      char name_end = get_symbol_name (&symbol_name);
+      reg = atoi (symbol_name + 1);
+      (void) restore_line_pointer (name_end);
+
+      if (!skip_whitespace_and_comma (1))
+	return;
+
+      if (reg < 0)
+	{
+	  as_bad (_("register is negative"));
+	  return;
+	}
+    }
+
+  offsetT off = -1;
+  if (unwind_code_pack_info->offset_bits)
+    {
+      off = get_absolute_expression ();
+
+      if (off < 0)
+	{
+	  as_bad (_("offset is negative"));
+	  return;
+	}
+    }
+
+  demand_empty_rest_of_line ();
+
+  seh_arm64_add_unwind_element (type, off, reg);
+}
+#endif
+
 /* Add a stack-allocation token to current context.  */
 
 static void
-- 
2.25.1



More information about the Binutils mailing list