Re: [PATCH] PE/COFF: raise normal PE section limit safely
Jan Beulich <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
On 30.06.2026 22:59, Oleg Tolmatcev wrote: > 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 <[email protected]> Looks largely okay to me, there's just one concern I have: > --- a/bfd/peXXigen.c > +++ b/bfd/peXXigen.c > @@ -109,6 +109,49 @@ > #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; > + } > +} When coming here for objcopy, upon reading the input we blindly accept any other values in the reserved range. Then ... > +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: > + BFD_ASSERT (scnum > 0 && (unsigned int) scnum <= IMAGE_SYM_SECTION_MAX); ... upon writing we'd stumble over this assertion. Assertions really should be about internal state only, not about input we consumed. Jan