From patchwork Tue Jul 14 20:23:49 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleg Tolmatcev X-Patchwork-Id: 139174 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 303EB4BA23EA for ; Tue, 14 Jul 2026 20:25:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 303EB4BA23EA Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=Sk/EoDwD X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by sourceware.org (Postfix) with ESMTPS id 691394BA23CE for ; Tue, 14 Jul 2026 20:24:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 691394BA23CE Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 691394BA23CE Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::32a ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1784060684; cv=none; b=mROb1S8zKU52IBV/F8RX+DXkb5QTSJPwz5I0CFtAOxw9YSsKNynG5dtP6IHG/i9dexXarhDkjYHgf0ij7zSlcLstMOr7BiMQk+25luK+b+5i+VOlJRvtHlmKednp2/VdcBrSlnwXQrApCZ11OXZ5JtwLODTux7G3UnARXipJciM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1784060684; c=relaxed/simple; bh=UR0ZvOMj2SfnTDuLalMkpKM+/uLY1IaZqmvchqV+cCE=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=g6FotI1hDmO1GnoDgXgbX3FSSojhyIZVdHMgoW/2iajin563uK2wEr7KkvKPCfQg6ifpToV9/XybJffOf9nDrTI5q2gPu94w44FdXlMGKK7M3eshGuF1idIsMd63GHPluSPX/aGs/vsus4dKGH0ypRu9PUdLT0ZZ6TigjKE4FrI= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=Sk/EoDwD DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 691394BA23CE Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-493ec555a26so30324745e9.0 for ; Tue, 14 Jul 2026 13:24:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784060683; x=1784665483; darn=sourceware.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=BhZrSPwnKx1BXGVKGauDb9NiwHbR9UtBmbOJgdLvwMM=; b=Sk/EoDwDm6eJB93H5VfZcz0ljousiQ+zJTIbF9tJvkhmmgM5hDRf4qP5FJ+wQ9n++s S/m6+fpXu9kS7baRP/ANahcyZDFq9xPNHCvnydC6g+NpgcDUElSq73woBpf5advhdyNH TUAJ9tzNO/As4iamnRYqu2Lg/hrGmLdSgSH9MaOR2jnyIYa7/Wd4SczkajdivyDqBZuR hYdf5LtlXqdnnVQ6R3JILJ8U5NzzV2FaupXyxpf07u+k3fy0MferfVoJbMXLvpmS5LRj t56QrRGeb8Ew+kHzqia2cFaWqz9oA/v6iLSC9YG0wuQIVk7uxL5n/LHtb4Wd2NXxzZc4 NuUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784060683; x=1784665483; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=BhZrSPwnKx1BXGVKGauDb9NiwHbR9UtBmbOJgdLvwMM=; b=TwYN5WqrMuH5kzDTnq6BtauN9a+/blKVEb6ZorraIM7o9GHivCE2zRicEoX/BOmhod ihPxkCQUCAF5SbvIHr7ordkjiyyEEPaW6jf9Llzrfk+o5TLykMgm1AKs4mU5XE3HB6Xd gSzltcbSojhV7bF/XO6Nq6kLwfLtXbhA+NDTqnebQ1wuWZCAkTWFtBoqjkL1RUTTGzMp v/8RraGPfgzQvk6seVieJdscm2A6s6/4vhpXtLi/IxVRnhGIFt2ih0kilE+ScmNh8vTa jUzsxTLIpej8jqkLiZb8R97Jz8uyz1cxygolgnwpFjVEOAKEOtT6ebO+wMAokRMNd10c MUjQ== X-Gm-Message-State: AOJu0YwbvFreDmAIFXKwwLFBsouWADiez/kVOoEUlLl6wBD9o5UTMgt4 mA17/QlKfR0YDmgg9sAvaYgsAEqR0qerPMTPr1pBy5HBcj1oXhLzIBBJbcMh9Q== X-Gm-Gg: AfdE7cmbpULF10uNMmepDT0ssQhnk4hltlg4QW21/SGY9PK/lccFtqa/pAgiOEriMk2 ZKCgZ5BJUjZtcdn8x3ubRiqgR7K/unMZtpF8EwFFzJcMZ4yr/31CqTpHDJJoyplYsa8JIfT8cX4 WyQRtJbgDv+GgG4R5W4SBjHeTkPj1Kn2RKos1iUVFso2v+otwpq09Kg/TrEeKoE6w7imwPs3DRg nzbVS4Q/9A9djhBVB0jFvx6gQArFkywbhcMUuAhaLfKKyugsd7vdb5xzKo5dKZeJcDkLU1+m63A S3gyoKYRUNKwe0bIQHwAYTtknmeTK9UnGHwp5x3um8bWDdn1DSWy42Fvonz1Z485Qo1TfQnXVxG LYCXPWz47/tYwdS2PE5tAxt3TGO9ok/THJqXs/+YJmAhn4QF9Ory9NBi3jHOe/eCX48DEtzeYS+ J0I2ynzlnlXTHbHqEMrh1nNpfD67yo4/K5Jbpp5Q0ia4PK5LfUHlg6hPw2EBusLaTtsEhKnTEIZ 3H99QN6qok= X-Received: by 2002:a05:600c:4f8b:b0:490:b00c:8e6a with SMTP id 5b1f17b1804b1-4953c286e42mr2343455e9.28.1784060682718; Tue, 14 Jul 2026 13:24:42 -0700 (PDT) Received: from Mein-PC (p200300ed8f164c0058c3c3c49641d90f.dip0.t-ipconnect.de. [2003:ed:8f16:4c00:58c3:c3c4:9641:d90f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4950a322dc6sm104879295e9.10.2026.07.14.13.24.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jul 2026 13:24:42 -0700 (PDT) From: Oleg Tolmatcev To: binutils@sourceware.org Cc: Oleg Tolmatcev Subject: [PATCH v4] PE/COFF: raise normal PE section limit safely Date: Tue, 14 Jul 2026 22:23:49 +0200 Message-ID: <20260714202348.1105-2-oleg.tolmatcev@gmail.com> X-Mailer: git-send-email 2.55.0.windows.1 MIME-Version: 1.0 X-Spam-Status: No, score=-10.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, RCVD_IN_PBL, SPF_HELO_NONE, SPF_PASS, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org PE/COFF stores symbol section numbers in a 16-bit field. Binutils used signed 16-bit handling there, which limited normal PE objects to 32767 sections even though MSVC and Clang already accept a larger unsigned range. Raise the normal PE section limit to 65279, while keeping the PE/COFF special section-number values for undefined, absolute and debug symbols working correctly. Do this by decoding and encoding normal PE symbol section numbers as unsigned values in the ordinary range, but preserving the reserved PE constants explicitly. Also add a gas test that exercises a normal PE object above the old 32767-section limit and checks that objdump reports the high section number correctly. bfd/ChangeLog: * coffcode.h (COFF_DEFAULT_MAX_NSCNS): Define. (bfd_coff_std_swap_table): Use it for the default maximum section count. (ticoff0_swap_table): Likewise. (ticoff1_swap_table): Likewise. * peXXigen.c (pe_decode_sym_section_number): New function. (pe_encode_sym_section_number): New function. (_bfd_XXi_swap_sym_in): Use pe_decode_sym_section_number. (_bfd_XXi_swap_sym_out): Use pe_encode_sym_section_number. include/ChangeLog: * coff/pe.h (IMAGE_SYM_UNDEFINED): Define. (IMAGE_SYM_ABSOLUTE): Define. (IMAGE_SYM_DEBUG): Define. (IMAGE_SYM_SECTION_MAX): Define. gas/ChangeLog: * testsuite/gas/pe/pe.exp: Run large-obj-normal. * testsuite/gas/pe/large-obj-normal.s: New test. * testsuite/gas/pe/large-obj-normal.d: New test. Signed-off-by: Oleg Tolmatcev --- bfd/coffcode.h | 12 +++++-- bfd/peXXigen.c | 46 +++++++++++++++++++++++-- gas/testsuite/gas/pe/large-obj-normal.d | 17 +++++++++ gas/testsuite/gas/pe/large-obj-normal.s | 16 +++++++++ gas/testsuite/gas/pe/pe.exp | 1 + include/coff/pe.h | 5 +++ 6 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 gas/testsuite/gas/pe/large-obj-normal.d create mode 100644 gas/testsuite/gas/pe/large-obj-normal.s diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 12cc7c3ca7..267c6ce278 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -376,6 +376,12 @@ extern const bfd_target TARGET_SYM_BIG; # define COFF_WITH_EXTENDED_RELOC_COUNTER #endif +#if defined(COFF_WITH_PE) && !defined(COFF_IMAGE_WITH_PE) +# define COFF_DEFAULT_MAX_NSCNS (IMAGE_SYM_SECTION_MAX + 1) +#else +# define COFF_DEFAULT_MAX_NSCNS 32768 +#endif + #if defined (COFF_LONG_SECTION_NAMES) /* Needed to expand the inputs to BLANKOR1TOODD. */ #define COFFLONGSECTIONCATHELPER(x,y) x ## y @@ -5615,7 +5621,7 @@ static const bfd_coff_backend_data bfd_coff_std_swap_table ATTRIBUTE_UNUSED = #else 2, #endif - 32768, + COFF_DEFAULT_MAX_NSCNS, coff_SWAP_filehdr_in, coff_SWAP_aouthdr_in, coff_SWAP_scnhdr_in, coff_SWAP_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook, coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook, @@ -5656,7 +5662,7 @@ static const bfd_coff_backend_data ticoff0_swap_table = #else 2, #endif - 32768, + COFF_DEFAULT_MAX_NSCNS, coff_SWAP_filehdr_in, coff_SWAP_aouthdr_in, coff_SWAP_scnhdr_in, coff_swap_reloc_v0_in, ticoff0_bad_format_hook, coff_set_arch_mach_hook, coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook, @@ -5698,7 +5704,7 @@ static const bfd_coff_backend_data ticoff1_swap_table = #else 2, #endif - 32768, + COFF_DEFAULT_MAX_NSCNS, coff_SWAP_filehdr_in, coff_SWAP_aouthdr_in, coff_SWAP_scnhdr_in, coff_SWAP_reloc_in, ticoff1_bad_format_hook, coff_set_arch_mach_hook, coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook, diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c index bdb23dcbca..dbd30f8747 100644 --- a/bfd/peXXigen.c +++ b/bfd/peXXigen.c @@ -109,6 +109,48 @@ #define SetHighBit(val) ((val) | 0x80000000) #define WithoutHighBit(val) ((val) & 0x7fffffff) +static int +pe_decode_sym_section_number (bfd *abfd, const char *raw_scnum) +{ + unsigned int scnum = H_GET_16 (abfd, raw_scnum); + + switch (scnum) + { + case IMAGE_SYM_UNDEFINED: + return N_UNDEF; + case IMAGE_SYM_ABSOLUTE: + return N_ABS; + case IMAGE_SYM_DEBUG: + return N_DEBUG; + default: + return scnum; + } +} + +static void +pe_encode_sym_section_number (bfd *abfd, int scnum, char *raw_scnum) +{ + unsigned int encoded_scnum; + + switch (scnum) + { + case N_UNDEF: + encoded_scnum = IMAGE_SYM_UNDEFINED; + break; + case N_ABS: + encoded_scnum = IMAGE_SYM_ABSOLUTE; + break; + case N_DEBUG: + encoded_scnum = IMAGE_SYM_DEBUG; + break; + default: + encoded_scnum = scnum; + break; + } + + H_PUT_16 (abfd, encoded_scnum, raw_scnum); +} + void _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1) { @@ -124,7 +166,7 @@ _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1) memcpy (in->_n._n_name, ext->e.e_name, SYMNMLEN); in->n_value = H_GET_32 (abfd, ext->e_value); - in->n_scnum = (short) H_GET_16 (abfd, ext->e_scnum); + in->n_scnum = pe_decode_sym_section_number (abfd, ext->e_scnum); if (sizeof (ext->e_type) == 2) in->n_type = H_GET_16 (abfd, ext->e_type); @@ -262,7 +304,7 @@ _bfd_XXi_swap_sym_out (bfd * abfd, void * inp, void * extp) } H_PUT_32 (abfd, in->n_value, ext->e_value); - H_PUT_16 (abfd, in->n_scnum, ext->e_scnum); + pe_encode_sym_section_number (abfd, in->n_scnum, ext->e_scnum); if (sizeof (ext->e_type) == 2) H_PUT_16 (abfd, in->n_type, ext->e_type); diff --git a/gas/testsuite/gas/pe/large-obj-normal.d b/gas/testsuite/gas/pe/large-obj-normal.d new file mode 100644 index 0000000000..e9009e5795 --- /dev/null +++ b/gas/testsuite/gas/pe/large-obj-normal.d @@ -0,0 +1,17 @@ +#objdump: -h -t +#name: PE large normal object after raising the normal section limit + +# This only becomes meaningful once normal PE/COFF is allowed past the +# old 32767-section cutoff. Before that, BFD errors out or auto-promotes +# to bigobj before the normal 16-bit symbol-section encoding is exercised. + +.*: *file format pe-(aarch64-little|i386|x86-64) + +Sections: +#... +40002 +\.data\$a39999 .* + CONTENTS, ALLOC, LOAD, DATA + +SYMBOL TABLE: +#... +.*\(sec 40003\).*\(scl +2\).*\) 0x[0-9a-f]+ a39999$ diff --git a/gas/testsuite/gas/pe/large-obj-normal.s b/gas/testsuite/gas/pe/large-obj-normal.s new file mode 100644 index 0000000000..254733023d --- /dev/null +++ b/gas/testsuite/gas/pe/large-obj-normal.s @@ -0,0 +1,16 @@ + .file "large-obj-normal.s" + + .irp n,0,1,2,3 + .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 82f217cf94..600fd2425a 100644 --- a/gas/testsuite/gas/pe/pe.exp +++ b/gas/testsuite/gas/pe/pe.exp @@ -71,6 +71,7 @@ if {[istarget "aarch64-*-pe*"] || [istarget "aarch64-*-mingw*"]} { if { [istarget "aarch64-*-*"] || ([istarget "i*86-*-*"] && ![istarget "*-*-interix*"]) || [istarget "x86_64-*-*"] } then { + run_dump_test "large-obj-normal" run_dump_test "big-obj" run_dump_test "big-obj-auto" } diff --git a/include/coff/pe.h b/include/coff/pe.h index ece4bf25db..133548ff4b 100644 --- a/include/coff/pe.h +++ b/include/coff/pe.h @@ -388,6 +388,11 @@ struct external_SYMBOL_EX char e_numaux[1]; } ATTRIBUTE_PACKED ; +#define IMAGE_SYM_UNDEFINED 0 +#define IMAGE_SYM_ABSOLUTE 0xffff +#define IMAGE_SYM_DEBUG 0xfffe +#define IMAGE_SYM_SECTION_MAX 0xfeff + #define SYMENT_BIGOBJ struct external_SYMBOL_EX #define SYMESZ_BIGOBJ 20