[PATCH v5 1/1] aarch64: Add bigobj support to AArch64 COFF
Evgeny Karpov
evgeny.karpov@arm.com
Mon Jan 12 13:54:45 GMT 2026
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(-)
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