[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