Bug 27210 - ld: Don't suppress foo if foo@v1 is defined
Summary: ld: Don't suppress foo if foo@v1 is defined
Status: RESOLVED NOTABUG
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-01-19 22:31 UTC by Fangrui Song
Modified: 2021-01-20 16:00 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Fangrui Song 2021-01-19 22:31:48 UTC
cat > a.s <<eof
.globl foo
.symver foo, foo@v1
foo: nop
eof
echo 'v1 {};' > a.ver
cat > b.s <<eof
.globl  foo_v1
foo_v1: nop
.symver foo_v1, foo@v1
eof

exit


GNU ld has a special rule removing foo if foo@v1 is defined. gold and LLD don't have the special rule.
I think the gold/LLD behavior makes more sense.

Building glibc does not need the GNU ld special rule. The 30000+ FreeBSD ports work with the LLD behavior.
People know that non-default versions should use a different original symbol name.
So dropping the special rule is likely safe.

% gcc -shared -fuse-ld=bfd a.s -nostdlib -Wl,--version-script=a.ver -o a.bfd.so && readelf -W --dyn- a.bfd.so

Symbol table '.dynsym' contains 4 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000001000     0 NOTYPE  GLOBAL DEFAULT    7 foo@v1
     2: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS v1
     3: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS v2

% gcc -shared -fuse-ld=gold a.s -nostdlib -Wl,--version-script=a.ver -o a.gold.so && readelf -W --dyn- a.gold.so

Symbol table '.dynsym' contains 8 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000002000     0 NOTYPE  GLOBAL DEFAULT    8 _end
     2: 0000000000002000     0 NOTYPE  GLOBAL DEFAULT    8 _edata
     3: 000000000000034c     0 NOTYPE  GLOBAL DEFAULT    7 foo@v1
     4: 000000000000034c     0 NOTYPE  GLOBAL DEFAULT    7 foo
     5: 0000000000002000     0 NOTYPE  GLOBAL DEFAULT    8 __bss_start
     6: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS v1
     7: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS v2

For b.s, both foo_v1 and foo@v1 are present.
Comment 1 H.J. Lu 2021-01-19 23:00:53 UTC
(In reply to Fangrui Song from comment #0)
> cat > a.s <<eof
> .globl foo
> .symver foo, foo@v1
> foo: nop
> eof
> echo 'v1 {};' > a.ver
> cat > b.s <<eof
> .globl  foo_v1
> foo_v1: nop
> .symver foo_v1, foo@v1
> eof
> 
> exit
> 
> 
> GNU ld has a special rule removing foo if foo@v1 is defined. gold and LLD

This is done on purpose. A single '@' defines a 'hidden' versioned symbol,
which is intended for dynamic linker and shouldn't be used by ld to satisfy
the unversioned reference.  ld behavior is correct.
Comment 2 Fangrui Song 2021-01-19 23:36:03 UTC
(In reply to H.J. Lu from comment #1)
> (In reply to Fangrui Song from comment #0)
> > cat > a.s <<eof
> > .globl foo
> > .symver foo, foo@v1
> > foo: nop
> > eof
> > echo 'v1 {};' > a.ver
> > cat > b.s <<eof
> > .globl  foo_v1
> > foo_v1: nop
> > .symver foo_v1, foo@v1
> > eof
> > 
> > exit
> > 
> > 
> > GNU ld has a special rule removing foo if foo@v1 is defined. gold and LLD
> 
> This is done on purpose. A single '@' defines a 'hidden' versioned symbol,
> which is intended for dynamic linker and shouldn't be used by ld to satisfy
> the unversioned reference.  ld behavior is correct.

I disagree. This interpretation does not explain why foo_v1 is not suppressed.

The special rule for foo should just be dropped.
Comment 3 Fangrui Song 2021-01-19 23:46:07 UTC
Reopen
Comment 4 Alan Modra 2021-01-20 00:05:36 UTC
HJ is correct.
Comment 5 Fangrui Song 2021-01-20 01:11:56 UTC
The explanation is not convincing. foo and foo@v1 are two different symbols. 
My example does not use an undefined symbol so I don't see how

> shouldn't be used by ld to satisfy the unversioned reference.

is relevant.
Comment 6 H.J. Lu 2021-01-20 02:17:22 UTC
(In reply to Fangrui Song from comment #5)
> The explanation is not convincing. foo and foo@v1 are two different symbols. 
> My example does not use an undefined symbol so I don't see how
> 
> > shouldn't be used by ld to satisfy the unversioned reference.
> 
> is relevant.

In a DSO, only foo and foo@@VERSION can point to the same definition
in .dynsym.
Comment 7 Fangrui Song 2021-01-20 03:18:35 UTC
(In reply to H.J. Lu from comment #6)
> (In reply to Fangrui Song from comment #5)
> > The explanation is not convincing. foo and foo@v1 are two different symbols. 
> > My example does not use an undefined symbol so I don't see how
> > 
> > > shouldn't be used by ld to satisfy the unversioned reference.
> > 
> > is relevant.
> 
> In a DSO, only foo and foo@@VERSION can point to the same definition
> in .dynsym.

Other versioned dynamic symbols can have the same st_value as well.

% nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep -v U | awk '{if ($1 in s) print s[$1], $3; else s[$1]=$3}'
__adjtimex@@GLIBC_2.2.5 adjtimex@@GLIBC_2.2.5
alphasort@@GLIBC_2.2.5 alphasort64@@GLIBC_2.2.5
__arch_prctl@@GLIBC_2.2.5 arch_prctl@@GLIBC_2.2.5
__argz_count@@GLIBC_2.2.5 argz_count@@GLIBC_2.2.5
__argz_next@@GLIBC_2.2.5 argz_next@@GLIBC_2.2.5
__argz_stringify@@GLIBC_2.2.5 argz_stringify@@GLIBC_2.2.5
__asprintf@@GLIBC_2.2.5 asprintf@@GLIBC_2.2.5
__backtrace@@GLIBC_2.2.5 backtrace@@GLIBC_2.2.5
__backtrace_symbols@@GLIBC_2.2.5 backtrace_symbols@@GLIBC_2.2.5
__backtrace_symbols_fd@@GLIBC_2.2.5 backtrace_symbols_fd@@GLIBC_2.2.5
__bzero@@GLIBC_2.2.5 bzero@@GLIBC_2.2.5
clock_getcpuclockid@GLIBC_2.2.5 clock_getcpuclockid@@GLIBC_2.17
...



ld producing both 'foo' and 'foo@v1' is totally fine. It may not have explainable runtime behavior (say foo@@v2 exists) so the user should do something (usually via a local: pattern in a version script) to suppress 'foo'. ld does not need to work around the user bug by suppressing 'foo' when 'foo@v1' is defined.
Comment 8 H.J. Lu 2021-01-20 16:00:54 UTC
I opened an lld bug:

https://bugs.llvm.org/show_bug.cgi?id=48820