[PATCH v4 3/7] Adjust x64 SEH implementation for AArch64
Evgeny Karpov
evgeny@kmaps.co
Thu Aug 14 22:47:53 GMT 2025
This patch defines the required unwind codes for AArch64 and updates handlers
for SEH commands that are used by both x64 and AArch64.
It implements encoding for unwind elements that will be emitted
to pdata/xdata sections.
The x64 SEH implementation emits .pdata/.xdata records at every seh_endproc.
This has been adjusted to keep the x64 SEH implementation unchanged and to
allow the aarch64 SEH to emit .pdata/.xdata records at the end of the assembly.
gas/ChangeLog:
* config/obj-coff-seh.c (struct aarch64_unwind_code_pack_info): New.
(defined): Add aarch64_unwind_code_pack_data.
(obj_coff_seh_code): Add COFFAARCH64 guard.
(seh_get_target_kind): Update.
(verify_context): Update.
(verify_context_and_target): Update.
(obj_coff_seh_eh): Add COFFAARCH64 guard.
(seh_aarch64_add_unwind_element): New.
(do_seh_endproc): Remove.
(emit_pdata_xdata_records): New.
(free_seh_ctx): New.
(obj_coff_seh_proc): Update.
(obj_coff_seh_do_final): Update.
(seh_x64_make_prologue_element): Add COFFAARCH64 guard.
(obj_coff_seh_save): Likewise.
(obj_coff_seh_stackalloc): Update.
(obj_coff_seh_setframe): Add COFFAARCH64 guard.
(seh_x64_write_function_xdata): Likewise.
(seh_arm_write_function_pdata): Likewise.
(write_function_pdata): Update.
* config/obj-coff-seh.h (defined): Add COFFAARCH64 guard.
(SEH_CMDS): Redefine for AArch64.
(obj_coff_seh_setframe): Add COFFAARCH64 guard.
(obj_coff_seh_endproc): Likewise.
(obj_coff_seh_proc): Likewise.
(obj_coff_seh_handler): Likewise.
(obj_coff_seh_handlerdata): Likewise.
(obj_coff_seh_code): Likewise.
---
gas/config/obj-coff-seh.c | 321 +++++++++++++++++++++++++++++++++++---
gas/config/obj-coff-seh.h | 23 ++-
2 files changed, 319 insertions(+), 25 deletions(-)
diff --git a/gas/config/obj-coff-seh.c b/gas/config/obj-coff-seh.c
index 1607a430cf6..158be2795dd 100644
--- a/gas/config/obj-coff-seh.c
+++ b/gas/config/obj-coff-seh.c
@@ -28,14 +28,86 @@ struct seh_seg_list {
char *seg_name;
};
+struct aarch64_unwind_code_pack_info {
+ const char *directive;
+ unsigned offset_bits;
+ unsigned reg_bits;
+ unsigned code_bits;
+ unsigned code;
+ unsigned offset_right_shift;
+ unsigned offset;
+ unsigned reg_right_shift;
+ unsigned reg_offset;
+ unsigned type;
+ unsigned size;
+};
+
/* Local data. */
+#if defined (COFFAARCH64)
+static seh_context *seh_ctx_root = NULL;
+#endif
static seh_context *seh_ctx_cur = NULL;
+static bool in_seh_proc = false;
static htab_t seh_hash;
static struct seh_seg_list *x_segcur = NULL;
static struct seh_seg_list *p_segcur = NULL;
+#if defined (COFFAARCH64)
+static const struct aarch64_unwind_code_pack_info
+aarch64_unwind_code_pack_data[] = {
+/* Unwind codes packing for AArch64 is described at
+ https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling?view=msvc-170#unwind-codes
+ and calculated in seh_aarch64_add_unwind_element function.
+
+ directive, offset_bits, reg_bits, code_bits, code, offset_right_shift,
+ offset, reg_right_shift, reg_offset, type, size. */
+ {NULL, 5, 0, 3, AARCH64_UNOP_ALLOCS, 4, 0, 0,
+ 0, alloc_s, 1},
+ {NULL, 11, 0, 5, AARCH64_UNOP_ALLOCM, 4, 0, 0,
+ 0, alloc_m, 2},
+ {NULL, 24, 0, 8, AARCH64_UNOP_ALLOCL, 4, 0, 0,
+ 0, alloc_l, 4},
+ {".seh_save_reg", 6, 4, 6, AARCH64_UNOP_SAVEREG, 3, 0, 0,
+ 19, save_reg, 2},
+ {".seh_save_reg_x", 5, 4, 7, AARCH64_UNOP_SAVEREGX, 3, 1, 0,
+ 19, save_reg_x, 2},
+ {".seh_save_regp", 6, 4, 6, AARCH64_UNOP_SAVEREGP, 3, 0, 0,
+ 19, save_regp, 2},
+ {".seh_save_regp_x", 6, 4, 6, AARCH64_UNOP_SAVEREGPX, 3, 1, 0,
+ 19, save_regp_x, 2},
+ {".seh_save_fregp", 6, 3, 7, AARCH64_UNOP_SAVEFREGP, 3, 0, 0,
+ 8, save_fregp, 2},
+ {".seh_save_fregp_x", 6, 3, 7, AARCH64_UNOP_SAVEFREGPX, 3, 1, 0,
+ 8, save_fregp_x, 2},
+ {".seh_save_freg", 6, 3, 7, AARCH64_UNOP_SAVEFREG, 3, 0, 0,
+ 8, save_freg, 2},
+ {".seh_save_freg_x", 5, 3, 8, AARCH64_UNOP_SAVEFREGX, 3, 1, 0,
+ 8, save_freg_x, 2},
+ {".seh_save_lrpair", 6, 3, 7, AARCH64_UNOP_SAVELRPAIR, 3, 0, 1,
+ 19, save_lrpair, 2},
+ {".seh_save_fplr", 6, 0, 2, AARCH64_UNOP_SAVEFPLR, 3, 0, 0,
+ 0, save_fplr, 1},
+ {".seh_save_fplr_x", 6, 0, 6, AARCH64_UNOP_SAVEFPLRX, 3, 1, 0,
+ 0, save_fplr_x, 1},
+ {".seh_save_r19r20_x", 5, 0, 3, AARCH64_UNOP_SAVER19R20X, 3, 0, 0,
+ 0, save_r19r20_x, 1},
+ {".seh_add_fp", 8, 0, 8, AARCH64_UNOP_ADDFP, 0, 0, 0,
+ 0, add_fp, 2},
+ {".seh_set_fp", 0, 0, 8, AARCH64_UNOP_SETFP, 0, 0, 0,
+ 0, set_fp, 1},
+ {".seh_save_next", 0, 0, 8, AARCH64_UNOP_SAVENEXT, 0, 0, 0,
+ 0, save_next, 1},
+ {".seh_nop", 0, 0, 8, AARCH64_UNOP_NOP, 0, 0, 0,
+ 0, nop, 1},
+ {".seh_pac_sign_lr", 0, 0, 8, AARCH64_UNOP_PACSIGNLR, 0, 0, 0,
+ 0, pac_sign_lr, 1},
+ {NULL, 0, 0, 8, AARCH64_UNOP_END, 0, 0, 0,
+ 0, end, 1},
+};
+#endif
+
static void write_function_xdata (seh_context *);
static void write_function_pdata (seh_context *);
@@ -164,12 +236,14 @@ seh_validate_seg (const char *directive)
return 0;
}
+#if !defined (COFFAARCH64)
/* Switch back to the code section, whatever that may be. */
static void
obj_coff_seh_code (int ignored ATTRIBUTE_UNUSED)
{
subseg_set (seh_ctx_cur->code_seg, 0);
}
+#endif
static void
switch_xdata (int subseg, segT code_seg)
@@ -189,6 +263,7 @@ switch_pdata (segT code_seg)
/* Parsing routines. */
+#if !defined (COFFAARCH64)
/* Return the style of SEH unwind info to generate. */
static seh_kind
@@ -199,7 +274,6 @@ seh_get_target_kind (void)
switch (bfd_get_arch (stdoutput))
{
- case bfd_arch_aarch64:
case bfd_arch_arm:
case bfd_arch_powerpc:
case bfd_arch_sh:
@@ -227,18 +301,24 @@ seh_get_target_kind (void)
}
return seh_kind_unknown;
}
+#endif
/* Verify that seh directives are supported. */
static bool
verify_target (const char *directive)
{
+#if defined (COFFAARCH64)
+ (void) directive; /* Unused. */
+#else
if (seh_get_target_kind () == seh_kind_unknown)
{
as_warn (_("%s ignored for this target"), directive);
ignore_rest_of_line ();
return false;
}
+#endif
+
return true;
}
@@ -247,7 +327,7 @@ verify_target (const char *directive)
static int
verify_context (const char *directive)
{
- if (seh_ctx_cur == NULL)
+ if (!in_seh_proc)
{
as_bad (_("%s used outside of .seh_proc block"), directive);
ignore_rest_of_line ();
@@ -256,6 +336,7 @@ verify_context (const char *directive)
return 1;
}
+#if !defined (COFFAARCH64)
/* Similar, except we also verify the appropriate target. */
static int
@@ -269,6 +350,7 @@ verify_context_and_target (const char *directive,
seh_kind target)
}
return verify_context (directive);
}
+#endif
/* Skip whitespace and a comma. Error if the comma is not seen. */
@@ -292,6 +374,7 @@ skip_whitespace_and_comma (int required)
return 0;
}
+#if !defined (COFFAARCH64)
/* Mark current context to use 32-bit instruction (arm). */
static void
@@ -320,6 +403,7 @@ obj_coff_seh_eh (int what ATTRIBUTE_UNUSED)
demand_empty_rest_of_line ();
}
+#endif
/* Set for current context the default handler (x64). */
@@ -366,10 +450,21 @@ obj_coff_seh_handler (int what ATTRIBUTE_UNUSED)
seh_ctx_cur->handler_data.X_add_number = 0;
seh_ctx_cur->handler_flags = 0;
+#if defined (COFFAARCH64)
+ seh_ctx_cur->aarch64_ctx.xdata_header.x = 1;
+#endif
+
if (!skip_whitespace_and_comma (0))
return;
- if (seh_get_target_kind () == seh_kind_x64)
+ bool seh_handler_supported;
+#if defined (COFFAARCH64)
+ seh_handler_supported = true;
+#else
+ seh_handler_supported = seh_get_target_kind () == seh_kind_x64;
+#endif
+
+ if (seh_handler_supported)
{
do
{
@@ -401,26 +496,97 @@ obj_coff_seh_handler (int what ATTRIBUTE_UNUSED)
static void
obj_coff_seh_handlerdata (int what ATTRIBUTE_UNUSED)
{
+#if !defined (COFFAARCH64)
if (!verify_context_and_target (".seh_handlerdata", seh_kind_x64))
return;
+#endif
demand_empty_rest_of_line ();
switch_xdata (seh_ctx_cur->subsection + 1, seh_ctx_cur->code_seg);
}
+#if defined (COFFAARCH64)
+/* Obtain available unwind element. */
+
+static void
+seh_aarch64_add_unwind_element (seh_aarch64_unwind_types unwind_type,
+ int offset, int reg)
+{
+ gas_assert (in_seh_proc);
+
+ seh_aarch64_context* aarch64_ctx = &seh_ctx_cur->aarch64_ctx;
+ seh_aarch64_unwind_code *aarch64_element;
+ aarch64_element = aarch64_ctx->unwind_codes
+ + aarch64_ctx->unwind_codes_count++;
+ const struct aarch64_unwind_code_pack_info *unwind_code_pack_info;
+ unwind_code_pack_info = aarch64_unwind_code_pack_data + unwind_type;
+ aarch64_element->value = 0;
+ int value_offset_bits = 0;
+
+ const unsigned max_unwind_size = AARCH64_MAX_UNWIND_CODES_SIZE;
+ if ((aarch64_ctx->unwind_codes_byte_count
+ + unwind_code_pack_info->size) > max_unwind_size)
+ {
+ as_bad (_ ("no unwind element available."));
+ return;
+ }
+
+ if (unwind_code_pack_info->offset_bits)
+ {
+ offset = (offset >> unwind_code_pack_info->offset_right_shift)
+ - unwind_code_pack_info->offset;
+ offset &= (1 << unwind_code_pack_info->offset_bits) - 1;
+ aarch64_element->value |= offset << value_offset_bits;
+ value_offset_bits += unwind_code_pack_info->offset_bits;
+ }
+
+ if (unwind_code_pack_info->reg_bits)
+ {
+ reg = (reg >> unwind_code_pack_info->reg_right_shift)
+ - unwind_code_pack_info->reg_offset;
+ reg &= (1 << unwind_code_pack_info->reg_bits) - 1;
+ aarch64_element->value |= reg << value_offset_bits;
+ value_offset_bits += unwind_code_pack_info->reg_bits;
+ }
+
+ if (unwind_code_pack_info->code_bits)
+ {
+ int code = unwind_code_pack_info->code;
+ code &= (1 << unwind_code_pack_info->code_bits) - 1;
+ aarch64_element->value |= code << value_offset_bits;
+ }
+
+ aarch64_element->type = unwind_code_pack_info->type;
+ aarch64_ctx->unwind_codes_byte_count += unwind_code_pack_info->size;
+}
+#endif
+
/* Mark end of current context. */
static void
-do_seh_endproc (void)
+emit_pdata_xdata_records (struct seh_context *seh_ctx)
{
- seh_ctx_cur->end_addr = symbol_temp_new_now ();
+ write_function_xdata (seh_ctx);
+ write_function_pdata (seh_ctx);
+}
- write_function_xdata (seh_ctx_cur);
- write_function_pdata (seh_ctx_cur);
- free (seh_ctx_cur->elems);
- free (seh_ctx_cur->func_name);
- free (seh_ctx_cur);
- seh_ctx_cur = NULL;
+static void
+free_seh_ctx (struct seh_context *seh_ctx)
+{
+ free (seh_ctx->elems);
+ free (seh_ctx->func_name);
+#if defined (COFFAARCH64)
+ seh_aarch64_func_fragment *fragment;
+ fragment = seh_ctx->aarch64_ctx.func_fragment.next;
+ while (fragment)
+ {
+ seh_aarch64_func_fragment *next = fragment->next;
+ XDELETE (fragment);
+ fragment = next;
+ }
+ XDELETEVEC (seh_ctx->aarch64_ctx.epilogue_scopes);
+#endif
+ free (seh_ctx);
}
static void
@@ -429,13 +595,21 @@ obj_coff_seh_endproc (int what ATTRIBUTE_UNUSED)
if (!verify_target (".seh_endproc"))
return;
demand_empty_rest_of_line ();
- if (seh_ctx_cur == NULL)
+ if (!in_seh_proc)
{
as_bad (_(".seh_endproc used without .seh_proc"));
return;
}
seh_validate_seg (".seh_endproc");
- do_seh_endproc ();
+
+ seh_ctx_cur->end_addr = symbol_temp_new_now ();
+#if !defined (COFFAARCH64)
+ emit_pdata_xdata_records (seh_ctx_cur);
+ free_seh_ctx (seh_ctx_cur);
+ seh_ctx_cur = NULL;
+#endif
+
+ in_seh_proc = false;
}
/* Mark begin of new context. */
@@ -448,10 +622,15 @@ obj_coff_seh_proc (int what ATTRIBUTE_UNUSED)
if (!verify_target (".seh_proc"))
return;
- if (seh_ctx_cur != NULL)
+ if (in_seh_proc)
{
as_bad (_("previous SEH entry not closed (missing .seh_endproc)"));
- do_seh_endproc ();
+#if !defined (COFFAARCH64)
+ seh_ctx_cur->end_addr = symbol_temp_new_now ();
+ emit_pdata_xdata_records (seh_ctx_cur);
+ free_seh_ctx (seh_ctx_cur);
+ seh_ctx_cur = NULL;
+#endif
}
if (*input_line_pointer == 0 || *input_line_pointer == '\n')
@@ -461,15 +640,45 @@ obj_coff_seh_proc (int what ATTRIBUTE_UNUSED)
return;
}
+
+#if defined (COFFAARCH64)
+ if (!seh_ctx_root)
+ {
+ seh_ctx_root = XCNEW (seh_context);
+ seh_ctx_cur = seh_ctx_root;
+ }
+ else
+ {
+ seh_ctx_cur->next = XCNEW (seh_context);
+ seh_ctx_cur = seh_ctx_cur->next;
+ }
+
+ seh_ctx_cur->next = NULL;
+#else
seh_ctx_cur = XCNEW (seh_context);
+#endif
seh_ctx_cur->code_seg = now_seg;
- if (seh_get_target_kind () == seh_kind_x64)
+ bool use_xdata;
+#if defined (COFFAARCH64)
+ use_xdata = true;
+#else
+ use_xdata = seh_get_target_kind () == seh_kind_x64;
+#endif
+
+ if (use_xdata)
{
x_segcur = seh_hash_find_or_make (seh_ctx_cur->code_seg, ".xdata");
seh_ctx_cur->subsection = x_segcur->subseg;
x_segcur->subseg += 2;
+
+#if defined (COFFAARCH64)
+ seh_ctx_cur->aarch64_ctx.unwind_codes_count = 0;
+ seh_ctx_cur->aarch64_ctx.epilogue_scopes_count = 0;
+ seh_ctx_cur->aarch64_ctx.epilogue_scopes_capacity = 0;
+ seh_ctx_cur->aarch64_ctx.epilogue_scopes = NULL;
+#endif
}
SKIP_WHITESPACE ();
@@ -481,6 +690,7 @@ obj_coff_seh_proc (int what ATTRIBUTE_UNUSED)
demand_empty_rest_of_line ();
seh_ctx_cur->start_addr = symbol_temp_new_now ();
+ in_seh_proc = true;
}
/* Mark end of prologue for current context. */
@@ -498,6 +708,22 @@ obj_coff_seh_endprologue (int what ATTRIBUTE_UNUSED)
as_warn (_("duplicate .seh_endprologue in .seh_proc block"));
else
seh_ctx_cur->endprologue_addr = symbol_temp_new_now ();
+
+#if defined (COFFAARCH64)
+ const int n = seh_ctx_cur->aarch64_ctx.unwind_codes_count;
+
+ /* Unwind codes need to be reversed. */
+ for (int i = 0; i < n / 2; ++i)
+ {
+ seh_aarch64_unwind_code *unwind_codes;
+ unwind_codes = seh_ctx_cur->aarch64_ctx.unwind_codes;
+ seh_aarch64_unwind_code temp = unwind_codes[i];
+ unwind_codes[i] = unwind_codes[n-i-1];
+ unwind_codes[n-i-1] = temp;
+ }
+
+ seh_aarch64_add_unwind_element (end, 0, 0);
+#endif
}
/* End-of-file hook. */
@@ -505,10 +731,27 @@ obj_coff_seh_endprologue (int what ATTRIBUTE_UNUSED)
void
obj_coff_seh_do_final (void)
{
- if (seh_ctx_cur != NULL)
+ if (in_seh_proc)
as_bad (_("open SEH entry at end of file (missing .seh_endproc)"));
+
+#if defined (COFFAARCH64)
+
+ if (!seh_ctx_root)
+ return;
+
+ struct seh_context *seh_ctx = seh_ctx_root;
+ while (seh_ctx)
+ {
+ emit_pdata_xdata_records (seh_ctx);
+ struct seh_context *next = seh_ctx->next;
+ free_seh_ctx (seh_ctx);
+ seh_ctx = next;
+ }
+ seh_ctx_root = NULL;
+#endif
}
+#if !defined (COFFAARCH64)
/* Enter a prologue element into current context (x64). */
static void
@@ -516,7 +759,7 @@ seh_x64_make_prologue_element (int code, int info,
offsetT off)
{
seh_prologue_element *n;
- if (seh_ctx_cur == NULL)
+ if (!in_seh_proc)
return;
if (seh_ctx_cur->elems_count == seh_ctx_cur->elems_max)
{
@@ -682,6 +925,7 @@ obj_coff_seh_save (int what)
seh_x64_make_prologue_element (code, reg, off);
}
+#endif
/* Add a stack-allocation token to current context. */
@@ -689,15 +933,37 @@ static void
obj_coff_seh_stackalloc (int what ATTRIBUTE_UNUSED)
{
offsetT off;
- int code, info;
+#if !defined (COFFAARCH64)
if (!verify_context_and_target (".seh_stackalloc", seh_kind_x64)
|| !seh_validate_seg (".seh_stackalloc"))
return;
+#endif
off = get_absolute_expression ();
demand_empty_rest_of_line ();
+#if defined (COFFAARCH64)
+ /* aarch64 offset should be encoded in multiples of sixteen. */
+ if ((off & 0xf) != 0)
+ {
+ as_bad (_(".seh_stackalloc offset < 16-byte stack alignment"));
+ return;
+ }
+
+ if (off < 0x200)
+ seh_aarch64_add_unwind_element (alloc_s, off, 0);
+ else if (off < 0x8000)
+ seh_aarch64_add_unwind_element (alloc_m, off, 0);
+ else if (off < 0x10000000)
+ seh_aarch64_add_unwind_element (alloc_l, off, 0);
+ else
+ {
+ as_bad (_(".seh_stackalloc offset out of range"));
+ return;
+ }
+#else
+ int code, info;
if (off == 0)
return;
if (off < 0)
@@ -719,8 +985,10 @@ obj_coff_seh_stackalloc (int what ATTRIBUTE_UNUSED)
}
seh_x64_make_prologue_element (code, info, off);
+#endif
}
+#if !defined (COFFAARCH64)
/* Add a frame-pointer token to current context. */
static void
@@ -758,7 +1026,8 @@ obj_coff_seh_setframe (int what ATTRIBUTE_UNUSED)
seh_x64_make_prologue_element (UWOP_SET_FPREG, 0, 0);
}
}
-
+#endif
+
/* Data writing routines. */
/* Output raw integers in 1, 2, or 4 bytes. */
@@ -781,6 +1050,7 @@ out_four (int data)
md_number_to_chars (frag_more (4), data, 4);
}
+#if !defined (COFFAARCH64)
/* Write out prologue data for x64. */
static void
@@ -929,6 +1199,7 @@ seh_x64_write_function_xdata (seh_context *c)
/* Handler data will be tacked in here by subsections. */
}
+#endif
/* Write out xdata for one function. */
@@ -938,17 +1209,23 @@ write_function_xdata (seh_context *c)
segT save_seg = now_seg;
int save_subseg = now_subseg;
+#if !defined (COFFAARCH64)
/* MIPS, SH, ARM don't have xdata. */
if (seh_get_target_kind () != seh_kind_x64)
return;
+#endif
switch_xdata (c->subsection, c->code_seg);
+#if defined (COFFAARCH64)
+#else
seh_x64_write_function_xdata (c);
+#endif
subseg_set (save_seg, save_subseg);
}
+#if !defined (COFFAARCH64)
/* Write pdata section data for one function (arm). */
static void
@@ -999,6 +1276,7 @@ seh_arm_write_function_pdata (seh_context *c)
val |= 0x80000000U;
out_four (val);
}
+#endif
/* Write out pdata for one function. */
@@ -1011,6 +1289,8 @@ write_function_pdata (seh_context *c)
memset (&exp, 0, sizeof (expressionS));
switch_pdata (c->code_seg);
+#if defined (COFFAARCH64)
+#else
switch (seh_get_target_kind ())
{
case seh_kind_x64:
@@ -1054,6 +1334,7 @@ write_function_pdata (seh_context *c)
default:
abort ();
}
+#endif
subseg_set (save_seg, save_subseg);
}
diff --git a/gas/config/obj-coff-seh.h b/gas/config/obj-coff-seh.h
index ad58a409997..9aa97813754 100644
--- a/gas/config/obj-coff-seh.h
+++ b/gas/config/obj-coff-seh.h
@@ -112,6 +112,17 @@ typedef enum seh_aarch64_unwind_types
{"seh_code", obj_coff_seh_code, 0}, \
{"seh_handlerdata", obj_coff_seh_handlerdata, 0},
+#if defined (COFFAARCH64)
+#undef SEH_CMDS
+#define SEH_CMDS \
+ {"seh_proc", obj_coff_seh_proc, 0}, \
+ {"seh_endproc", obj_coff_seh_endproc, 0}, \
+ {"seh_endprologue", obj_coff_seh_endprologue, 0}, \
+ {"seh_stackalloc", obj_coff_seh_stackalloc, 0}, \
+ {"seh_handler", obj_coff_seh_handler, 0}, \
+ {"seh_handlerdata", obj_coff_seh_handlerdata, 0},
+#endif
+
/* Type definitions. */
typedef struct seh_prologue_element
@@ -271,18 +282,20 @@ typedef enum seh_kind {
/* Forward declarations. */
static void obj_coff_seh_stackalloc (int);
-static void obj_coff_seh_setframe (int);
static void obj_coff_seh_endprologue (int);
+static void obj_coff_seh_endproc (int);
+static void obj_coff_seh_proc (int);
+static void obj_coff_seh_handler (int);
+static void obj_coff_seh_handlerdata (int);
+#if !defined (COFFAARCH64)
+static void obj_coff_seh_setframe (int);
static void obj_coff_seh_save (int);
static void obj_coff_seh_pushreg (int);
static void obj_coff_seh_pushframe (int);
-static void obj_coff_seh_endproc (int);
static void obj_coff_seh_eh (int);
static void obj_coff_seh_32 (int);
-static void obj_coff_seh_proc (int);
-static void obj_coff_seh_handler (int);
-static void obj_coff_seh_handlerdata (int);
static void obj_coff_seh_code (int);
+#endif
#define UNDSEC bfd_und_section_ptr
--
2.39.5
More information about the Binutils
mailing list