Bug 20543 - Please move from .gnu.linkonce to comdat
Summary: Please move from .gnu.linkonce to comdat
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.32
: P2 normal
Target Milestone: 2.32
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-08-31 21:45 UTC by Rafael Ávila de Espíndola
Modified: 2026-09-07 15:52 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
Project(s) to access:
ssh public key:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Rafael Ávila de Espíndola 2016-08-31 21:45:16 UTC
sysdeps/i386/sysdep.h still has

.section .gnu.linkonce.t.GET_PC_THUNK(reg),"ax",@progbits;

The gcc produced code to get the pc these days is

        .section        .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
        .globl  __x86.get_pc_thunk.ax
        .hidden __x86.get_pc_thunk.ax
        .type   __x86.get_pc_thunk.ax, @function
__x86.get_pc_thunk.ax:
.LFB1:
        .cfi_startproc
        movl    (%esp), %eax
        ret
        .cfi_endproc
Comment 1 Fangrui Song 2019-08-07 03:10:00 UTC
Bump. sysdeps/i386/sysdep.h stills has .gnu.linkonce.t code.

glibc requires GCC>=6 and binutils>=2.25 now. .gnu.linkonce.t should not be needed.
Comment 2 Florian Weimer 2019-08-07 07:15:38 UTC
Why do you request this change?  The answer to that will help us to prioritize this bug.
Comment 3 Rafael Ávila de Espíndola 2019-08-12 18:13:58 UTC
While working in lld this was the only case of linkonce I remember hitting. Linkonce logic has been implemented in lld, but this is probably the one case in a linux distro where anyone or any tool has to know what linkonce is.
Comment 4 Florian Weimer 2019-08-12 19:57:42 UTC
Thanks.  The problem here is that this affects the startup code.  In the past, we wanted to support older toolchains for linking.  In theory, it should still be possible to do this by passing the right assembler options (presumably -Wa,-mrelax-relocations=no) to avoid generating newer relocations.

But isn't COMDAT support quite old, from 2005 or so?  So making this change might not be a problem after all.  And usually, using a newer linker isn't a problem.
Comment 5 Fangrui Song 2020-02-13 17:37:46 UTC
Found https://patches.linaro.org/patch/90572/ (via https://github.com/ClangBuiltLinux/linux/issues/432) that Adhemerval Zanella has a patch that is ignored.
Comment 6 Sourceware Commits 2020-02-28 17:02:16 UTC
The master branch has been updated by Adhemerval Zanella <azanella@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=b5b7fb76e15c0db545aa11a3ce88f836e5d01a19

commit b5b7fb76e15c0db545aa11a3ce88f836e5d01a19
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Fri Feb 28 10:46:14 2020 -0300

    i386: Use comdat instead of .gnu.linkonce for i386 setup pic register (BZ #20543)
    
    GCC has moved from using .gnu.linkonce for i386 setup pic register with
    minimum current version (as for binutils minimum binutils that support
    comdat).
    
    Trying to pinpoint when binutils has added comdat support for i686, it
    seems it was around 2004 [1].  I also checking with some ancient
    binutils older than 2.16 I see:
    
    test.o: In function `__x86.get_pc_thunk.bx':
    test.o(.text.__x86.get_pc_thunk.bx+0x0): multiple definition of `__x86.get_pc_thunk.bx'
    /usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/crti.o(.gnu.linkonce.t.__x86.get_pc_thunk.bx+0x0): first defined here
    
    Which seems that such version can not handle either comdat at all or
    a mix of linkonce and comdat.  For binutils 2.16.1 I am getting a
    different issue trying to link a binary with and more recent
    ctri.o (unrecognized relocation (0x2b) in section `.init', which is
    R_386_GOT32X and old binutils won't generate it anyway).
    
    So I think that either unlikely someone will use an older binutils than
    the one used to glibc and even this scenario may fail with some issue
    as the R_386_GOT32X.  Also, 2.16.1 is quite old and not really supported
    (glibc itself required 2.25).
    
    Checked on i686-linux-gnu.
    
    [1] https://gcc.gnu.org/ml/gcc/2004-05/msg00030.html
Comment 7 Adhemerval Zanella 2020-02-28 17:08:12 UTC
Fixed on 2.32.
Comment 8 Sourceware Commits 2020-03-24 11:50:56 UTC
The release/2.30/master branch has been updated by Adhemerval Zanella <azanella@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=1ce16683d9efa1cc611ed4632645e16742699d10

commit 1ce16683d9efa1cc611ed4632645e16742699d10
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Fri Feb 28 10:46:14 2020 -0300

    i386: Use comdat instead of .gnu.linkonce for i386 setup pic register (BZ #20543)
    
    GCC has moved from using .gnu.linkonce for i386 setup pic register with
    minimum current version (as for binutils minimum binutils that support
    comdat).
    
    Trying to pinpoint when binutils has added comdat support for i686, it
    seems it was around 2004 [1].  I also checking with some ancient
    binutils older than 2.16 I see:
    
    test.o: In function `__x86.get_pc_thunk.bx':
    test.o(.text.__x86.get_pc_thunk.bx+0x0): multiple definition of `__x86.get_pc_thunk.bx'
    /usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/crti.o(.gnu.linkonce.t.__x86.get_pc_thunk.bx+0x0): first defined here
    
    Which seems that such version can not handle either comdat at all or
    a mix of linkonce and comdat.  For binutils 2.16.1 I am getting a
    different issue trying to link a binary with and more recent
    ctri.o (unrecognized relocation (0x2b) in section `.init', which is
    R_386_GOT32X and old binutils won't generate it anyway).
    
    So I think that either unlikely someone will use an older binutils than
    the one used to glibc and even this scenario may fail with some issue
    as the R_386_GOT32X.  Also, 2.16.1 is quite old and not really supported
    (glibc itself required 2.25).
    
    Checked on i686-linux-gnu.
    
    [1] https://gcc.gnu.org/ml/gcc/2004-05/msg00030.html
    
    (cherry picked from commit 35200fd3892f6caf867bf89bc8048e553906af28)
Comment 9 Sourceware Commits 2026-09-07 15:52:22 UTC
The master branch has been updated by Adhemerval Zanella <azanella@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=9ef758c501fe8c7eaa8bb4f377a766cab7a63fcf

commit 9ef758c501fe8c7eaa8bb4f377a766cab7a63fcf
Author: Matt Turner <mattst88@gmail.com>
Date:   Sun Sep 6 17:11:49 2026 -0400

    alpha: Use a comdat group for the shared divide-by-zero handler [BZ #20543]
    
    DO_DIVBYZERO placed __divbyzero in .gnu.linkonce.t.divbyzero so that,
    when building the PIC libc.so, every divide routine's copy collapses to
    one. .gnu.linkonce is a pre-comdat-group GNU convention that no current
    toolchain emits and that upstream lld has declined to support in full
    generality, since a linked-to section from outside a group is not valid
    ELF and every non-GNU-as producer has used SHT_GROUP comdat groups
    instead for 25+ years.
    
    BZ #20543 tracked this migration across glibc; i386's PIC-thunk section
    was converted, but alpha's divide-by-zero handler was missed. Switch it
    to the same "axG",@progbits,<sym>,comdat idiom already used by the i386
    and sparc PIC-thunk sections, so it is deduplicated via a real ELF group
    rather than section-name matching.
    
    Divide routines reach the handler via `beq Y, DIVBYZERO`, a 21-bit
    word-displacement branch (+-4MB range). The old .gnu.linkonce.t.* name
    put the section in the default linker script's last .text bucket,
    guaranteeing it trailed all other code; .text.__divbyzero lands one
    bucket earlier alongside other .text.* input sections, so "last in
    .text" is no longer guaranteed (PIC libc.so only; libc.a keeps per-file
    copies). Measured on an alpha-unknown-linux-gnu build, __divbyzero
    landed a few hundred bytes from the end of a ~1.6MB .text. An
    out-of-range branch would fail the link with "relocation truncated to
    fit" rather than produce a silently broken libc.
    
    Reviewed-by: H.J. Lu <hjl.tools@gmail.com>