[PATCH v4 3/7] Adjust x64 SEH implementation for AArch64

Jan Beulich jbeulich@suse.com
Mon Feb 2 07:24:09 GMT 2026


On 30.01.2026 18:46, Evgeny Karpov wrote:
> On Fri, Oct 10, 2025 Jan Beulich wrote:
>> On 15.08.2025 00:47, Evgeny Karpov wrote:
>>> 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.
>>
>> Which needs to be this way because of ...?

This was left unanswered, yet the question becomes relevant further down
(already in one of the original comments).

>>> 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.
>>
>> Resulting in more open-coding / duplicate code at the two prior call sites.
>> Tolerable, but not very nice.
> 
> Splitting SEH implementations for x64 and aarch64 into two separate source files
> should look better. Also it should prevent regressions in x64 implementation
> because the x64 files will be only renamed.
> Here is a proposal for the file names:
> obj-coff-seh.h (common)
> obj-coff-seh-i386.h / obj-coff-seh-i386.c 
> and obj-coff-seh-aarch64.h / obj-coff-seh-aarch64.c

The current file isn't x86-only afaics, but also contains code to support
e.g. Arm and MIPS.

>>> @@ -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 ();
>>
>> I fear I don't understand why this change would be needed. (Can it
>> be broken out as a separate change, with a proper description?)
> 
> seh_ctx_cur is NULL in the aarch64 implementation, as data has postponed
> emitting to xdata.

This is where the question at the top is relevant.

>>> @@ -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;
>>
>> Why unconditionally 1?
> 
> It indicates the presence of exception data, which is always emitted.

Why's there a flag if this data is always emitted?

>>> @@ -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;
>>
>> Move this up to prevent the value becoming a dangling pointer during the 1st
>> loop iteration?
> 
> Yes, as an option, it can be moved. Anyway, multithreading is not supported
> by this implementation.

I never thought of multi-threading here. Any function you call can, in principle,
look at and use the pointer.

>>> @@ -938,17 +1209,23 @@ write_function_xdata (seh_context *c)
>>>    segT save_seg = now_seg;
>>>    int save_subseg = now_subseg;
>>>
>>> +#if !defined (COFFAARCH64)
>>
>> You use this here and elsewhere; why ...
>>
>>>    /* 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
>>
>> ... not also here?
> 
> The first condition is needed only for x64, otherwise it should be modified.
> However, the decision has been made to have a static implementation for aarch64.
> The second place is needed for a call of two different architecture specific
> implementations.

Perhaps the question wasn't clear enough: It went like "Why #if !defined() in
one place but #if defined() / <nothing> / #else in other places?" But as you
intend to split file, this question will become moot anyway.

Jan


More information about the Binutils mailing list