[PATCH v8 1/1] aarch64: Implement Structured Exception Handling (SEH) on AArch64
Jan Beulich
jbeulich@suse.com
Tue Jun 16 05:53:33 GMT 2026
On 15.06.2026 18:06, Evgeny Karpov wrote:
> The patch reuses shared helpers for SEH and implements SEH on AArch64.
> The implementation is based on
> (https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling?view=msvc-170)
> and pdata/xdata SEH records are emitted from md_finish.
>
> When .pdata/.xdata is emitted, the function size is required.
> Function sizes are calculated as late as possible, and the code segment needs
> to be relaxed to be able to calculate the function sizes.
>
> Initially, obj_coff_generate_pdata was called in write_object_file.
> Before the change, obj_coff_generate_pdata was used only to validate
> syntax, which was sufficient for that purpose. However, that location
> seems incorrect, as it is too late to emit .pdata/.xdata records
> in the AArch64 case.
>
> md_finish has been declared for AArch64 and extended with
> seh_aarch64_write_data to emit .pdata/.xdata records after all
> assembly has been completed.
>
> Signed-off-by: Evgeny Karpov <evgeny@kmaps.co>
This wants approval from an Arm64 maintainer. Just one nit:
> --- /dev/null
> +++ b/gas/config/obj-coff-seh-aarch64.h
> @@ -0,0 +1,251 @@
> +/* SEH .pdata/.xdata COFF object file format on AArch64
> + Copyright (C) 2026 Free Software Foundation, Inc.
> +
> + This file is part of GAS.
> +
> + GAS is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3, or (at your option)
> + any later version.
> +
> + GAS is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with GAS; see the file COPYING. If not, write to the Free
> + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
> + 02110-1301, USA. */
> +
> +/* SEH COFF AArch64 implementation partially intersects with the x64
> + version, however it has a different extension to the unwind codes.
> + It emits SEH data to pdata and xdata sections. In some cases SEH
> + data could be emitted to a packed record in the pdata section
> + without the need for data in the xdata section. However, the packed
> + pdata record is not implemented yet.
> +
> + The current implementation does not include:
> + - Packed .pdata record.
> + - Support for AdvSIMD and SVE.
> + - Epilogue start index different than 0. */
> +
> +#ifndef OBJ_COFF_SEH_AARCH64_H
> +#define OBJ_COFF_SEH_AARCH64_H
> +
> +/* Unwind codes for AArch64 are described at
> + https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling?view=msvc-170#unwind-codes. */
> +
> +typedef enum seh_aarch64_unwind_types
> +{
> + unwind_alloc_s,
> + unwind_alloc_m,
> + unwind_alloc_l,
> + unwind_save_reg,
> + unwind_save_reg_x,
> + unwind_save_regp,
> + unwind_save_regp_x,
> + unwind_save_fregp,
> + unwind_save_fregp_x,
> + unwind_save_freg,
> + unwind_save_freg_x,
> + unwind_save_lrpair,
> + unwind_save_fplr,
> + unwind_save_fplr_x,
> + unwind_save_r19r20_x,
> + unwind_add_fp,
> + unwind_set_fp,
> + unwind_save_next,
> + unwind_nop,
> + unwind_pac_sign_lr,
> + unwind_end,
> + unwind_end_c,
> + unwind_last_type = unwind_end_c
> +} seh_aarch64_unwind_types;
> +
> +#define SEH_CMDS \
> + /* Start a function that contains SEH. */ \
> + {"seh_proc", obj_coff_seh_proc, 0}, \
> + \
> + /* End a function that contains SEH. */ \
> + {"seh_endproc", obj_coff_seh_endproc, 0}, \
> + \
> + /* End a SEH prologue with unwinding codes. */ \
> + {"seh_endprologue", obj_coff_seh_endprologue, 0}, \
> + \
> + /* Allocate stack. */ \
> + {"seh_stackalloc", obj_coff_seh_stackalloc, 0}, \
> + \
> + /* Set a SEH handler. */ \
> + {"seh_handler", obj_coff_seh_handler, 0}, \
> + \
> + /* Set a SEH handler data. */ \
> + {"seh_handlerdata", obj_coff_seh_handlerdata, 0}, \
> + \
> + /* Switch back to the code section. */ \
> + {"seh_code", obj_coff_seh_code, 0}, \
> + \
> + /* Start a SEH epilogue. */ \
> + {"seh_startepilogue", obj_coff_seh_startepilogue, 0}, \
> + \
> + /* End a SEH epilogue. */ \
> + {"seh_endepilogue", obj_coff_seh_endepilogue, 0}, \
> + \
> + /* Save an 'x' register. */ \
> + {"seh_save_reg", obj_coff_seh_save_reg, unwind_save_reg}, \
> + \
> + /* Save an 'x' register with a pre-indexed offset. */ \
> + {"seh_save_reg_x", obj_coff_seh_save_reg, unwind_save_reg_x}, \
> + \
> + /* Save an 'x' register pair. */ \
> + {"seh_save_regp", obj_coff_seh_save_reg, unwind_save_regp}, \
> + \
> + /* Save an 'x' register pair with a pre-indexed offset. */ \
> + {"seh_save_regp_x", obj_coff_seh_save_reg, unwind_save_regp_x}, \
> + \
> + /* Save an 'x' register and lr. */ \
> + {"seh_save_lrpair", obj_coff_seh_save_reg, unwind_save_lrpair}, \
> + \
> + /* Save a 'd' register pair. */ \
> + {"seh_save_fregp", obj_coff_seh_save_reg, unwind_save_fregp}, \
> + \
> + /* Save a 'd' register pair with a pre-indexed offset. */ \
> + {"seh_save_fregp_x", obj_coff_seh_save_reg, unwind_save_fregp_x}, \
> + \
> + /* Save a 'd' register. */ \
> + {"seh_save_freg", obj_coff_seh_save_reg, unwind_save_freg}, \
> + \
> + /* Save a 'd' register with a pre-indexed offset. */ \
> + {"seh_save_freg_x", obj_coff_seh_save_reg, unwind_save_freg_x}, \
> + \
> + /* Save fp and lr registers. */ \
> + {"seh_save_fplr", obj_coff_seh_save_reg, unwind_save_fplr}, \
> + \
> + /* Save fp and lr registers with a pre-indexed offset. */ \
> + {"seh_save_fplr_x", obj_coff_seh_save_reg, unwind_save_fplr_x}, \
> + \
> + /* Save x19 and x20 registers with a pre-indexed offset. */ \
> + {"seh_save_r19r20_x", obj_coff_seh_save_reg, unwind_save_r19r20_x}, \
> + \
> + /* Set fp by sp + offset. */ \
> + {"seh_add_fp", obj_coff_seh_save_reg, unwind_add_fp}, \
> + \
> + /* Unwind operation is not required. */ \
> + {"seh_nop", obj_coff_seh_save_reg, unwind_nop}, \
> + \
> + /* Sign the return address in lr with pacibsp. */ \
> + {"seh_pac_sign_lr", obj_coff_seh_save_reg, unwind_pac_sign_lr}, \
> + \
> + /* Set fp by sp. */ \
> + {"seh_set_fp", obj_coff_seh_save_reg, unwind_set_fp}, \
> + \
> + /* Save next register pair. */ \
> + {"seh_save_next", obj_coff_seh_save_reg, unwind_save_next},
Can the backslashes here please all align properly? (It looks worse than it
is in reply context here, but there look to be quite a few genuine issues.)
Jan
More information about the Binutils
mailing list