[PATCH v5 1/1] aarch64: Add bigobj support to AArch64 COFF
Alice Carlotti
alice.carlotti@arm.com
Thu Jan 15 20:39:09 GMT 2026
On Mon, Jan 12, 2026 at 02:54:45PM +0100, Evgeny Karpov wrote:
> During Boost library testing on aarch64-w64-mingw32, it appeared that 2^16
> sections are not enough. It can be handled by using the bigobj format to extend
> the total amount of sections to 2^32. This patch adds bigobj support to
> AArch64 COFF in a similar way to how it is done for x86_64.
>
> Co-authored-by: Martin Vejbora <mvejbora@microsoft.com>
> Signed-off-by: Evgeny Karpov <evgeny@kmaps.co>
> ---
> bfd/coff-aarch64.c | 75 +++++++++++++++++++++++++++++++++++++++++
> bfd/config.bfd | 2 +-
> bfd/configure | 1 +
> bfd/configure.ac | 1 +
> bfd/cpu-aarch64.c | 2 +-
> bfd/pe-aarch64.c | 3 ++
> bfd/targets.c | 2 ++
> gas/config/tc-aarch64.c | 22 +++++++++++-
> gas/doc/c-aarch64.texi | 5 +++
> ld/pe-dll.c | 12 +++++++
> 10 files changed, 122 insertions(+), 3 deletions(-)
LGTM, and I believe Jan has already approved the generic changes. Do you have
write access, or should I merge it for you tomorrow?
Alice
>
> diff --git a/bfd/coff-aarch64.c b/bfd/coff-aarch64.c
> index fae37bc1e54..c00448efc82 100644
> --- a/bfd/coff-aarch64.c
> +++ b/bfd/coff-aarch64.c
> @@ -1018,3 +1018,78 @@ const bfd_target
>
> COFF_SWAP_TABLE
> };
> +
> +#ifdef COFF_WITH_PE_BIGOBJ
> +const bfd_target
> + TARGET_SYM_BIG =
> +{
> + TARGET_NAME_BIG,
> + bfd_target_coff_flavour,
> + BFD_ENDIAN_LITTLE, /* Data byte order is little. */
> + BFD_ENDIAN_LITTLE, /* Header byte order is little. */
> +
> + (HAS_RELOC | EXEC_P /* Object flags. */
> + | HAS_LINENO | HAS_DEBUG
> + | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
> +
> + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags. */
> +#ifdef COFF_WITH_PE
> + | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING
> +#endif
> + | SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
> +
> +#ifdef TARGET_UNDERSCORE
> + TARGET_UNDERSCORE, /* Leading underscore. */
> +#else
> + 0, /* Leading underscore. */
> +#endif
> + '/', /* Ar_pad_char. */
> + 15, /* Ar_max_namelen. */
> + 0, /* match priority. */
> + TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
> + TARGET_MERGE_SECTIONS,
> +
> + /* Data conversion functions. */
> + bfd_getl64, bfd_getl_signed_64, bfd_putl64,
> + bfd_getl32, bfd_getl_signed_32, bfd_putl32,
> + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */
> + /* Header conversion functions. */
> + bfd_getl64, bfd_getl_signed_64, bfd_putl64,
> + bfd_getl32, bfd_getl_signed_32, bfd_putl32,
> + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */
> +
> + /* Note that we allow an object file to be treated as a core file as well. */
> + { /* bfd_check_format. */
> + _bfd_dummy_target,
> + coff_object_p,
> + bfd_generic_archive_p,
> + coff_object_p
> + },
> + { /* bfd_set_format. */
> + _bfd_bool_bfd_false_error,
> + coff_mkobject,
> + _bfd_generic_mkarchive,
> + _bfd_bool_bfd_false_error
> + },
> + { /* bfd_write_contents. */
> + _bfd_bool_bfd_false_error,
> + coff_write_object_contents,
> + _bfd_write_archive_contents,
> + _bfd_bool_bfd_false_error
> + },
> +
> + BFD_JUMP_TABLE_GENERIC (coff_aarch64),
> + BFD_JUMP_TABLE_COPY (coff),
> + BFD_JUMP_TABLE_CORE (_bfd_nocore),
> + BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
> + BFD_JUMP_TABLE_SYMBOLS (coff),
> + BFD_JUMP_TABLE_RELOCS (coff),
> + BFD_JUMP_TABLE_WRITE (coff),
> + BFD_JUMP_TABLE_LINK (coff),
> + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
> +
> + NULL,
> +
> + &bigobj_swap_table
> +};
> +#endif
> diff --git a/bfd/config.bfd b/bfd/config.bfd
> index 0f74fde2acc..4dde5321f23 100644
> --- a/bfd/config.bfd
> +++ b/bfd/config.bfd
> @@ -256,7 +256,7 @@ case "${targ}" in
> ;;
> aarch64-*-pe* | aarch64-*-mingw*)
> targ_defvec=aarch64_pe_le_vec
> - targ_selvecs="aarch64_pe_le_vec aarch64_pei_le_vec aarch64_elf64_le_vec aarch64_elf64_be_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_le_vec arm_elf32_be_vec pdb_vec"
> + targ_selvecs="aarch64_pe_le_vec aarch64_pei_le_vec aarch64_pe_bigobj_le_vec aarch64_elf64_le_vec aarch64_elf64_be_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_le_vec arm_elf32_be_vec pdb_vec"
> want64=true
> targ_underscore=no
> ;;
> diff --git a/bfd/configure b/bfd/configure
> index fc36a79f184..afa496a7042 100755
> --- a/bfd/configure
> +++ b/bfd/configure
> @@ -15850,6 +15850,7 @@ do
> aarch64_mach_o_vec) tb="$tb mach-o-aarch64.lo"; target_size=64 ;;
> aarch64_pei_le_vec) tb="$tb pei-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;;
> aarch64_pe_le_vec) tb="$tb pe-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;;
> + aarch64_pe_bigobj_le_vec) tb="$tb pe-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;;
> alpha_ecoff_le_vec) tb="$tb coff-alpha.lo ecoff.lo $ecoff"; target_size=64 ;;
> alpha_elf64_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
> alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
> diff --git a/bfd/configure.ac b/bfd/configure.ac
> index c5e24545dc9..f86c9eae754 100644
> --- a/bfd/configure.ac
> +++ b/bfd/configure.ac
> @@ -391,6 +391,7 @@ do
> aarch64_mach_o_vec) tb="$tb mach-o-aarch64.lo"; target_size=64 ;;
> aarch64_pei_le_vec) tb="$tb pei-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;;
> aarch64_pe_le_vec) tb="$tb pe-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;;
> + aarch64_pe_bigobj_le_vec) tb="$tb pe-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;;
> alpha_ecoff_le_vec) tb="$tb coff-alpha.lo ecoff.lo $ecoff"; target_size=64 ;;
> alpha_elf64_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
> alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
> diff --git a/bfd/cpu-aarch64.c b/bfd/cpu-aarch64.c
> index 5bdccd80428..21afa219cc6 100644
> --- a/bfd/cpu-aarch64.c
> +++ b/bfd/cpu-aarch64.c
> @@ -115,7 +115,7 @@ scan (const struct bfd_arch_info *info, const char *string)
> }
>
> /* Figure out if llp64 is default */
> -#if DEFAULT_VECTOR == aarch64_pe_le_vec
> +#if DEFAULT_VECTOR == aarch64_pe_le_vec || DEFAULT_VECTOR == aarch64_pe_bigobj_le_vec
> #define LLP64_DEFAULT true
> #define AARCH64_DEFAULT false
> #else
> diff --git a/bfd/pe-aarch64.c b/bfd/pe-aarch64.c
> index be6d32c0e93..5f9f928d4da 100644
> --- a/bfd/pe-aarch64.c
> +++ b/bfd/pe-aarch64.c
> @@ -23,6 +23,8 @@
>
> #define TARGET_SYM aarch64_pe_le_vec
> #define TARGET_NAME "pe-aarch64-little"
> +#define TARGET_SYM_BIG aarch64_pe_bigobj_le_vec
> +#define TARGET_NAME_BIG "pe-bigobj-aarch64-little"
> #define TARGET_ARCHITECTURE bfd_arch_aarch64
> #define TARGET_PAGESIZE 4096
> #define TARGET_BIG_ENDIAN 0
> @@ -32,6 +34,7 @@
> /* Rename the above into.. */
> #define COFF_WITH_peAArch64
> #define COFF_WITH_PE
> +#define COFF_WITH_PE_BIGOBJ
> #define PCRELOFFSET true
>
> /* Long section names not allowed in executable images, only object files. */
> diff --git a/bfd/targets.c b/bfd/targets.c
> index 9b1b5b3350d..6b1cf2dfd93 100644
> --- a/bfd/targets.c
> +++ b/bfd/targets.c
> @@ -684,6 +684,7 @@ extern const bfd_target aarch64_elf64_le_vec;
> extern const bfd_target aarch64_mach_o_vec;
> extern const bfd_target aarch64_pei_le_vec;
> extern const bfd_target aarch64_pe_le_vec;
> +extern const bfd_target aarch64_pe_bigobj_le_vec;
> extern const bfd_target alpha_ecoff_le_vec;
> extern const bfd_target alpha_elf64_vec;
> extern const bfd_target alpha_elf64_fbsd_vec;
> @@ -991,6 +992,7 @@ static const bfd_target * const _bfd_target_vector[] =
> &aarch64_elf64_le_vec,
> &aarch64_mach_o_vec,
> &aarch64_pe_le_vec,
> + &aarch64_pe_bigobj_le_vec,
> &aarch64_pei_le_vec,
> #endif
>
> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index 6a03dfe41ec..62e2d8d504d 100644
> --- a/gas/config/tc-aarch64.c
> +++ b/gas/config/tc-aarch64.c
> @@ -10279,6 +10279,11 @@ aarch64_after_parse_args (void)
> #endif
> }
>
> +#ifdef OBJ_COFF
> +/* Use big object file format. */
> +static bool use_big_obj = false;
> +#endif
> +
> #ifdef OBJ_ELF
> const char *
> elf64_aarch64_target_format (void)
> @@ -10298,7 +10303,7 @@ aarch64elf_frob_symbol (symbolS * symp, int *puntp)
> const char *
> coff_aarch64_target_format (void)
> {
> - return "pe-aarch64-little";
> + return use_big_obj ? "pe-bigobj-aarch64-little" : "pe-aarch64-little";
> }
> #endif
>
> @@ -10666,6 +10671,7 @@ const char md_shortopts[] = "m:";
> #define OPTION_EL (OPTION_MD_BASE + 1)
> #endif
> #endif
> +#define OPTION_MBIG_OBJ (OPTION_MD_BASE + 2)
>
> const struct option md_longopts[] = {
> #ifdef OPTION_EB
> @@ -10673,6 +10679,9 @@ const struct option md_longopts[] = {
> #endif
> #ifdef OPTION_EL
> {"EL", no_argument, NULL, OPTION_EL},
> +#endif
> +#ifdef OBJ_COFF
> + {"mbig-obj", no_argument, NULL, OPTION_MBIG_OBJ},
> #endif
> {NULL, no_argument, NULL, 0}
> };
> @@ -11312,6 +11321,12 @@ md_parse_option (int c, const char *arg)
> break;
> #endif
>
> +#ifdef OBJ_COFF
> + case OPTION_MBIG_OBJ:
> + use_big_obj = true;
> + break;
> +#endif
> +
> case 'a':
> /* Listing option. Just ignore these, we don't support additional
> ones. */
> @@ -11384,6 +11399,11 @@ md_show_usage (FILE * fp)
> fprintf (fp, _("\
> -EL assemble code for a little-endian cpu\n"));
> #endif
> +
> +#ifdef OBJ_COFF
> + fprintf (fp, _("\
> + -mbig-obj generate big object files\n"));
> +#endif
> }
>
> /* Parse a .cpu directive. */
> diff --git a/gas/doc/c-aarch64.texi b/gas/doc/c-aarch64.texi
> index c4e217f9fc5..f1b626adfbe 100644
> --- a/gas/doc/c-aarch64.texi
> +++ b/gas/doc/c-aarch64.texi
> @@ -127,6 +127,11 @@ extension options as the @option{-mcpu} option. Unlike
> @option{-mcpu}, extensions are not always enabled by default.
> @xref{AArch64 Extensions}.
>
> +@cindex @samp{-mbig-obj} option, AArch64
> +@item -mbig-obj
> +On PE/COFF target this option forces the use of big object file
> +format, which allows more than 32768 sections.
> +
> @cindex @code{-mverbose-error} command-line option, AArch64
> @item -mverbose-error
> This option enables verbose error messages for AArch64 gas. This option
> diff --git a/ld/pe-dll.c b/ld/pe-dll.c
> index 2185feba90e..f43bd14896e 100644
> --- a/ld/pe-dll.c
> +++ b/ld/pe-dll.c
> @@ -374,6 +374,18 @@ static pe_details_type pe_detail_list[] =
> false,
> autofilter_symbollist_generic
> },
> + {
> + "pei-aarch64-little",
> + "pe-bigobj-aarch64-little",
> + 2, /* IMAGE_REL_ARM64_ADDR32NB */
> + 8, /* IMAGE_REL_ARM64_SECREL */
> + 11, /* IMAGE_REL_ARM64_SECREL_LOW12L */
> + 13, /* IMAGE_REL_ARM64_SECTION */
> + PE_ARCH_aarch64,
> + bfd_arch_aarch64,
> + false,
> + autofilter_symbollist_generic
> + },
> { NULL, NULL, 0, 0, 0, 0, 0, 0, false, NULL }
> };
>
> --
> 2.50.1
>
More information about the Binutils
mailing list