[PATCH] PE/COFF: auto-promote to bigobj target when section count overflows
Oleg Tolmatcev
oleg.tolmatcev@gmail.com
Sun Jun 21 17:49:21 GMT 2026
Regular PE/COFF uses 16-bit section numbers in the symbol table,
limiting objects to at most 65535 sections. When this limit is
exceeded, the assembler silently truncates section numbers, producing
corrupt objects that cause confusing linker errors like:
undefined reference to `vtable for ...'
Fix this by automatically switching the xvec to the matching bigobj
target before any headers or symbols are finalized, so the object is
written out using the extended COFF format which supports 32-bit
section numbers.
bfd/
* coffcode.h (coff_compute_section_file_positions): Auto-promote
to bigobj target when section count exceeds 16-bit limit.
gas/
* testsuite/gas/pe/big-obj-auto.d: New test.
* testsuite/gas/pe/big-obj-auto.s: New test.
* testsuite/gas/pe/pe.exp: Run big-obj-auto.
Signed-off-by: Oleg Tolmatcev <oleg.tolmatcev@gmail.com>
---
bfd/coffcode.h | 14 ++++++++++++++
gas/testsuite/gas/pe/big-obj-auto.d | 9 +++++++++
gas/testsuite/gas/pe/big-obj-auto.s | 16 ++++++++++++++++
gas/testsuite/gas/pe/pe.exp | 1 +
4 files changed, 40 insertions(+)
create mode 100644 gas/testsuite/gas/pe/big-obj-auto.d
create mode 100644 gas/testsuite/gas/pe/big-obj-auto.s
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 7439fca676..5c9722a15e 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -360,6 +360,10 @@ CODE_FRAGMENT
#include "coffswap.h"
#endif
+#ifdef COFF_WITH_PE_BIGOBJ
+extern const bfd_target TARGET_SYM_BIG;
+#endif
+
#define STRING_SIZE_SIZE 4
#define DOT_DEBUG ".debug"
@@ -3154,6 +3158,16 @@ coff_compute_section_file_positions (bfd * abfd)
if (target_index >= bfd_coff_max_nscns (abfd))
{
+#ifdef COFF_WITH_PE_BIGOBJ
+ if (abfd->xvec != &TARGET_SYM_BIG)
+ {
+ /* Regular PE/COFF uses 16-bit section numbers in symbols.
+ Promote oversized objects to the matching bigobj target
+ before any headers or symbols are finalized. */
+ abfd->xvec = &TARGET_SYM_BIG;
+ return coff_compute_section_file_positions (abfd);
+ }
+#endif
bfd_set_error (bfd_error_file_too_big);
_bfd_error_handler
/* xgettext:c-format */
diff --git a/gas/testsuite/gas/pe/big-obj-auto.d b/gas/testsuite/gas/pe/big-obj-auto.d
new file mode 100644
index 0000000000..9538ed4c67
--- /dev/null
+++ b/gas/testsuite/gas/pe/big-obj-auto.d
@@ -0,0 +1,9 @@
+#objdump: -h
+#name: PE big obj auto-promotion
+
+.*: *file format pe-bigobj-.*
+
+Sections:
+#...
+5000. \.data\$a49999 .*
+ CONTENTS, ALLOC, LOAD, DATA
diff --git a/gas/testsuite/gas/pe/big-obj-auto.s b/gas/testsuite/gas/pe/big-obj-auto.s
new file mode 100644
index 0000000000..dbf2585e81
--- /dev/null
+++ b/gas/testsuite/gas/pe/big-obj-auto.s
@@ -0,0 +1,16 @@
+ .file "big-obj-auto.s"
+
+ .irp n,0,1,2,3,4
+ .irp m,0,1,2,3,4,5,6,7,8,9
+ .irp c,0,1,2,3,4,5,6,7,8,9
+ .irp d,0,1,2,3,4,5,6,7,8,9
+ .irp u,0,1,2,3,4,5,6,7,8,9
+ .globl a\n\m\c\d\u
+ .section .data$a\n\m\c\d\u,"w"
+a\n\m\c\d\u :
+ .byte 1
+ .endr
+ .endr
+ .endr
+ .endr
+ .endr
diff --git a/gas/testsuite/gas/pe/pe.exp b/gas/testsuite/gas/pe/pe.exp
index e25de3cfa9..092ab4b335 100644
--- a/gas/testsuite/gas/pe/pe.exp
+++ b/gas/testsuite/gas/pe/pe.exp
@@ -70,4 +70,5 @@ if {[istarget "aarch64-*-pe*"] || [istarget "aarch64-*-mingw*"]} {
if ([istarget "*-*-mingw*"]) then {
run_dump_test "big-obj"
+ run_dump_test "big-obj-auto"
}
--
2.54.0.windows.1
More information about the Binutils
mailing list