[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