[PATCH] PE-COFF: Fix link failure of C++ code with debug info after partial linking
Jan Beulich
jbeulich@suse.com
Fri Mar 27 14:33:11 GMT 2026
On 25.03.2026 16:56, Eric Botcazou wrote:
> Hi,
>
> if you apply the following recipe to the attached C/C++ files with a PE-COFF
> toolchain, you get the specified output:
>
> 1. g++ -c clib.cpp cpplib.cpp test.c -g
> 2. g++ -o pl.o clib.o cpplib.o -nostdlib -Wl,-r
> 3. objcopy pl.o
> objcopy.exe: pl.o: warning: COMDAT symbol
> '.debug_frame$_ZNSt12_Vector_baseIiSaIiEE12_Vector_implD1Ev' does not match
> section name '.debug_frame'
> 4. g++ -o test test.o pl.o
> ld.exe: pl.o: warning: COMDAT symbol
> '.debug_frame$_ZNSt12_Vector_baseIiSaIiEE12_Vector_implD1Ev' does not match
> section name '.debug_frame'
> pl.o:clib.cpp:(.pdata$_ZNSt12_Vector_baseIiSaIiEE13_M_deallocateEPiy+0x0):
> relocation truncated to fit: IMAGE_REL_AMD64_ADDR32NB against
> `.text$_ZNSt12_Vector_baseIiSaIiEE13_M_deallocateEPiy'
> pl.o:clib.cpp:(.pdata$_ZNSt12_Vector_baseIiSaIiEE13_M_deallocateEPiy+0x4):
> relocation truncated to fit: IMAGE_REL_AMD64_ADDR32NB against
> `.text$_ZNSt12_Vector_baseIiSaIiEE13_M_deallocateEPiy'
> pl.o:clib.cpp:(.pdata$_ZNSt12_Vector_baseIiSaIiEE19_M_get_Tp_allocatorEv+0x0):
> relocation truncated to fit: IMAGE_REL_AMD64_ADDR32NB against
> `.text$_ZNSt12_Vector_baseIiSaIiEE19_M_get_Tp_allocatorEv'
> pl.o:clib.cpp:(.pdata$_ZNSt12_Vector_baseIiSaIiEE19_M_get_Tp_allocatorEv+0x4):
> relocation truncated to fit: IMAGE_REL_AMD64_ADDR32NB against
> `.text$_ZNSt12_Vector_baseIiSaIiEE19_M_get_Tp_allocatorEv'
> pl.o:clib.cpp:(.pdata$_ZNSt15__new_allocatorIiE10deallocateEPiy+0x0):
> relocation truncated to fit: IMAGE_REL_AMD64_ADDR32NB against
> `.text$_ZNSt15__new_allocatorIiE10deallocateEPiy'
> pl.o:clib.cpp:(.pdata$_ZNSt15__new_allocatorIiE10deallocateEPiy+0x4):
> relocation truncated to fit: IMAGE_REL_AMD64_ADDR32NB against
> `.text$_ZNSt15__new_allocatorIiE10deallocateEPiy'
> collect2.exe: error: ld returned 1 exit status
>
> The problem pertains to section symbols generated for COMDAT sections: they
> are marked as local symbols as per Microsoft's PE-COFF specification, but
> partial linking discards the duplicate COMDAT sections without being able
> to either merge them, or remove them when they are used in a relocation.
>
> So they end up as undefined local symbols after the partial link, which in
> turn may cause the final link to fail (in practice you need e.g. a call to
> objcopy in between, because it moves them to the end of the symbol list).
>
> This change instructs the linker to "relocate" them instead, that is to say
> to attach them to the one COMDAT section that is output among the multiple
> COMDAT sections that are duplicate. It also prevents partial linking from
> prematurely globing the .[z]debug_frame* sections together, as already done
> for the .eh_frame* sections.
>
> Tested on x86_64-w64-mingw32, OK for the mainline?
Yes, albeit preferably with a few small adjustments (can't comment very well
on a patch that comes only as attachment): The new variable wants to be
pointer-to-const (unless I'm overlooking a reason why it cannot be), and it
would likely help the code if the variable had *secpp as initializer, such
that in place of the three (*secpp) the local variable can then be used.
Jan
More information about the Binutils
mailing list