From patchwork Wed Mar 25 15:56:26 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 132290 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 1E9684BB588D for ; Wed, 25 Mar 2026 15:59:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1E9684BB588D Authentication-Results: sourceware.org; dkim=pass (2048-bit key, secure) header.d=adacore.com header.i=@adacore.com header.a=rsa-sha256 header.s=google header.b=J8BVSO23 X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by sourceware.org (Postfix) with ESMTPS id 6155C4BB58C6 for ; Wed, 25 Mar 2026 15:57:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6155C4BB58C6 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 6155C4BB58C6 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::42e ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774454246; cv=none; b=rWikJ1WQnFAX81nwVZRNsGLBgsCeTeAzCOU/JLq7Qc24gVWWw+fLiO++s5F+IRxdIBV7BueL8tVRviv7HihfG160DveywSsb/dTlNX29YYuV1lv4gn054pxAPTko+Sty9bufndj+Rm0E+I+FsLHLQWoJMrJ5f0Aj0MbkMroxRy0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774454246; c=relaxed/simple; bh=K2FMsv/rCjOErw/+mEE0AYiYUttXfeSWkHuOsXtFrCI=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=LwvQQJ9X0o1RmqsR5GCK/s2QqbLV2bNDvv6RUyZr519pvxz9r6JeynQ88NMPrtZpAElkA+Yxt3/YRB77MuPWHJ9wR5a/A5IwsHxLgGSR75jwvNNIP/o2pzkebQM93ZaNFnldpTR7G8fywGHq06PJ3pMrN8L/KzXbLjiy6AmDh0M= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6155C4BB58C6 Received: by mail-wr1-x42e.google.com with SMTP id ffacd0b85a97d-439b9b190easo2036016f8f.2 for ; Wed, 25 Mar 2026 08:57:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore.com; s=google; t=1774454245; x=1775059045; darn=sourceware.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=HXbNXWNdNcFHOL/OZesgjAJL49ksyJnyiuS5wCY+TXg=; b=J8BVSO23jNxwjUKJGRHvZoOca8reUQdg1xPLf+WoOQ6fbZUz1IXjTsVqj0aJJi8fnZ CD9W4pDfDse8C90e5rb5CFrDvPYg8CNbJBAVVK5aTjLBFmPCUrl/IQ5ycnLSLcnRonLT uWzXW8ltB4hdoYb22INo7XfjGGIA7RKmsvbFyWXRlNvLLsRvzU77ibPJUDh043jL52Pc aXvMPjwm2jO0PNdqkUmBeAiYd3DUmTxDLxGJM94ASUejLXB78Ni/29X0mzvJ8bufJMEU JWpV/fe6qudn7ztEmnRCLcKm8O2wCUvemyE2An0Qvi0hmxDzDbQrzYcOw7xsgw/P3qkT bfRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774454245; x=1775059045; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=HXbNXWNdNcFHOL/OZesgjAJL49ksyJnyiuS5wCY+TXg=; b=WA9BxeuamroLaOtt+19OKCbWu0Qqnb3WRpqamNMBXuakGBveQLeE+nwvWyhfPad6PY EH0JFQR91OwbgqlByfqxgbiAnEMcMFZRwp8zwiVbrY5sxoArd8UXaE/8mgpOY1YbCxaz JBbWELP43xk8fZ8mzLvLjNxnoHQdiy2E5Zfoc+t8tLVmAqwj0GtXj5jAmUrkqSgRyDyZ jJtD0BxS3jzIFrQ0wp9uIifO8F+Hv2t4YiM5WpbQtiAI3RsbAJCDg/M7HjMZ5zFJ+OU1 VfxRoR8w3WYh5AX1wizm0KA9f3Um2oXTGA3b2smafVbhq4bCR9G6h07KjR98ahGu6DEG 5yPQ== X-Gm-Message-State: AOJu0YyDti2KOolEc/j99Q7SZMbTV9C9q9J5Ym5TcKfnZXE5LcN2NZTk mOH2bU5UJznbmO+NYnvohdS7MXw9PFXS/xhuaRKJew6Dx4Ly3EVc00yF+TDjz8pNRkJN45o5lSg IkSw= X-Gm-Gg: ATEYQzxrp9Dd8e3q3Cu8UwvYexs7K9kcbZmu5urCY8D5QHMEItx047aDjvlZndgWCv/ 2h/IXJE/GtvqvGzKYXs/D3E4uL8/rt+Q1ztbA1O2r8FiHTa5oDXpx8AjwCoFSvIFbLKmCTwRhXX sFiuaT7lessrf1l5m3ce9CJ2JlZvGbW+3zcljRm7ZlZUf8Mk1tsmTabSBq7IyqmG5YSVqkohN/h KBq4JvzDH6ENCRzN17lnvOQQ4ZzEKzOPYMGTuozcYYw9B4vODJF8rlBWn2cRIA/bPk3R3bfKsF1 7vDJ+99tIuFk49H9ezf5xFDbs5TSvbHA50DpVDffQIAhTzljbFeYwcEluxFZEbWqtCAqNWYzbgZ LQnmfCuD08AdZgGe+iLPnJrGF3SAafvrHMsQn+oywz4y7hIIzLAZtvSbBelJ0fuSnGoiGd6lMA/ RU/oKePhsNjxCr69HO48UY6e5vJij4588kIhEA X-Received: by 2002:a5d:6449:0:b0:43b:8fa4:1953 with SMTP id ffacd0b85a97d-43b8fa41ab0mr2389620f8f.11.1774454245129; Wed, 25 Mar 2026 08:57:25 -0700 (PDT) Received: from fomalhaut.localnet ([2a01:e0a:107c:2f10:e654:e8ff:fe8f:2ce6]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43b9192e3e8sm766919f8f.5.2026.03.25.08.57.24 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Mar 2026 08:57:24 -0700 (PDT) From: Eric Botcazou X-Google-Original-From: Eric Botcazou To: binutils@sourceware.org Subject: [PATCH] PE-COFF: Fix link failure of C++ code with debug info after partial linking Date: Wed, 25 Mar 2026 16:56:26 +0100 Message-ID: <2696145.Lt9SDvczpP@fomalhaut> MIME-Version: 1.0 X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLOCKED 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 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? 2026-03-25 Eric Botcazou bfd/ * cofflink.c (_bfd_coff_link_input_bfd): For a relocatable output, relocate section symbols for input sections that are not going to be emitted because they are duplicate of another one in the link. ld/ * scripttempl/pe.sc (.debug_frame): Do not glob all .debug_frame* sections together when not relocating. (.zdebug_frame): Likewise for .zdebug_frame* sections. * scripttempl/pep.sc (.debug_frame): Likewise. (.zdebug_frame): Likewise. diff --git a/bfd/cofflink.c b/bfd/cofflink.c index 02b68814ab4..e7adab2f0d8 100644 --- a/bfd/cofflink.c +++ b/bfd/cofflink.c @@ -1857,12 +1857,28 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd) /* Compute new symbol location. */ if (isym.n_scnum > 0) { - isym.n_scnum = (*secpp)->output_section->target_index; - isym.n_value += (*secpp)->output_offset; + asection *s; + + /* Relocate section symbols for sections that are not going to + be emitted because they are duplicate of another one. */ + if (bfd_link_relocatable (flaginfo->info) + && isym.n_sclass == C_STAT + && isym.n_type == T_NULL + && isym.n_numaux > 0 + && ((*secpp)->output_section == bfd_abs_section_ptr + || bfd_section_removed_from_list + (output_bfd, (*secpp)->output_section)) + && (*secpp)->kept_section) + s = (*secpp)->kept_section; + else + s = *secpp; + + isym.n_scnum = s->output_section->target_index; + isym.n_value += s->output_offset; if (! obj_pe (input_bfd)) - isym.n_value -= (*secpp)->vma; + isym.n_value -= s->vma; if (! obj_pe (flaginfo->output_bfd)) - isym.n_value += (*secpp)->output_section->vma; + isym.n_value += s->output_section->vma; } break; diff --git a/ld/scripttempl/pe.sc b/ld/scripttempl/pe.sc index f8d7c8ef6e7..a669f279eda 100644 --- a/ld/scripttempl/pe.sc +++ b/ld/scripttempl/pe.sc @@ -364,11 +364,11 @@ SECTIONS .debug_frame ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} : { - *(.debug_frame*) + *(.debug_frame${RELOCATING+*}) } .zdebug_frame ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} : { - *(.zdebug_frame*) + *(.zdebug_frame${RELOCATING+*}) } .debug_str ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} : diff --git a/ld/scripttempl/pep.sc b/ld/scripttempl/pep.sc index a5b4679544c..45e785492c5 100644 --- a/ld/scripttempl/pep.sc +++ b/ld/scripttempl/pep.sc @@ -373,11 +373,11 @@ SECTIONS .debug_frame ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} : { - *(.debug_frame*) + *(.debug_frame${RELOCATING+*}) } .zdebug_frame ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} : { - *(.zdebug_frame*) + *(.zdebug_frame${RELOCATING+*}) } .debug_str ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :