[PATCH v3] elf: Don't set its DT_VERSYM entry for unversioned symbol
Fangrui Song
maskray@sourceware.org
Wed Nov 12 06:37:40 GMT 2025
On Tue, Nov 11, 2025 at 3:47 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Wed, Nov 12, 2025 at 6:38 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Tue, Nov 11, 2025 at 6:46 PM Andreas Schwab <schwab@suse.de> wrote:
> > >
> > > On Okt 31 2025, H.J. Lu wrote:
> > >
> > > > 1. Referenced symbol without '@' has no version.
> > > > 2. Defined symbol without the .symver directive has no version if there
> > > > is no linker version script.
> > > >
> > > > Symbol without version shouldn't have the base version in its DT_VERSYM
> > > > entry. Instead, its DT_VERSYM entry should be all zero to indicate that
> > > > the symbol doesn't have a version.
> > >
> > > This breaks the testsuite of mold:
> > >
> >
> > Why should ld change impact mold tests?
> >
> > > 38/428 Test #38: x86_64-arch-x86_64-reloc ..............................***Failed 0.09 sec
> > > ++ dirname /home/abuild/rpmbuild/BUILD/mold-2.40.4.60.gad08999-build/mold-2.40.4.60.gad08999/test/arch-x86_64-reloc.sh
> > > + . /home/abuild/rpmbuild/BUILD/mold-2.40.4.60.gad08999-build/mold-2.40.4.60.gad08999/test/common.inc
> > > ++ export LC_ALL=C
> > > ++ LC_ALL=C
> > > ++ '[' -z x86_64 ']'
> > > ++ '[' -z '' ']'
> > > ++ TESTDIR=out/test/x86_64
> > > ++ CC=cc
> > > ++ CXX=c++
> > > ++ GCC=gcc
> > > ++ GXX=g++
> > > ++ OBJDUMP=objdump
> > > ++ OBJCOPY=objcopy
> > > ++ STRIP=strip
> > > ++ QEMU=
> > > +++ basename /home/abuild/rpmbuild/BUILD/mold-2.40.4.60.gad08999-build/mold-2.40.4.60.gad08999/test/arch-x86_64-reloc.sh .sh
> > > ++ testname=arch-x86_64-reloc
> > > ++ t=out/test/x86_64/arch-x86_64-reloc
> > > ++ mkdir -p out/test/x86_64/arch-x86_64-reloc
> > > ++ case $MACHINE in
> > > ++ tlsdesc_opt=-mtls-dialect=gnu2
> > > +++ uname
> > > ++ '[' Linux = FreeBSD ']'
> > > ++ trap 'on_error $LINENO' ERR
> > > ++ trap on_exit EXIT
> > > ++ echo -n 'Testing arch-x86_64-reloc ... '
> > > Testing arch-x86_64-reloc ... ++ set -o pipefail
> > > ++ set -x
> > > + cat
> > > + cc -fPIC -c -o out/test/x86_64/arch-x86_64-reloc/a.o -x assembler -
> > > + cc -fPIC -c -o out/test/x86_64/arch-x86_64-reloc/b.o -xc -
> > > + cat
> > > + cc -shared -o out/test/x86_64/arch-x86_64-reloc/c.so out/test/x86_64/arch-x86_64-reloc/a.o out/test/x86_64/arch-x86_64-reloc/b.o -Wl,-z,noexecstack
> > > + cat
> > > + cc -B. -o out/test/x86_64/arch-x86_64-reloc/exe out/test/x86_64/arch-x86_64-reloc/c.so out/test/x86_64/arch-x86_64-reloc/d.s -no-pie
> > > mold: error: undefined symbol: print
> > > >>> referenced by /tmp/ccfsY4zd.o:(.text)
> > > >>> /tmp/ccfsY4zd.o
> > > collect2: error: ld returned 1 exit status
> > > ++ on_error 43
> > > ++ code=1
> > > ++ echo 'command failed: 43: $CC -B. -o $t/exe $t/c.so $t/d.s -no-pie'
> > > command failed: 43: $CC -B. -o $t/exe $t/c.so $t/d.s -no-pie
> > > ++ trap - EXIT
> > > ++ exit 1
> > >
> > > Is this a bug in mold?
> >
> > Does
> >
> > $ cc -o out/test/x86_64/arch-x86_64-reloc/exe
> > out/test/x86_64/arch-x86_64-reloc/c.so
> > out/test/x86_64/arch-x86_64-reloc/d.s -no-pie
> >
> > fail with ld? "print" isn't a function in libc.
> >
> > 1. Where is it defined?
> > 2. What does
> > "readelf -DsW" with
> >
> > commit 2be0f2da2100cc2b5047f5d055cd039ac494d563
> > Author: H.J. Lu <hjl.tools@gmail.com>
> > Date: Thu Nov 6 08:20:26 2025 +0800
> >
> > readelf: Display the base symbol version as empty string
> >
> > report on the object where "print" is defined.
> > 3. Which linker is used to generate it?
> >
>
> I opened:
>
> https://github.com/rui314/mold/issues/1534
>
> --
> H.J.
ISTM new code will be needed across all Linux linkers to support this change.
I think the old linker behavior, which kept undefined unversioned
symbols at version 1, was more sensible.
This is because version 0 (VER_NDX_LOCAL) used to be exclusively for
defined symbols, but now it can be applied to undefined ones.
This change breaks the simple rule that an absent symbol versioning
section (like .gnu.version) meant everything was version 1.
Now, a symbol's default version depends on whether it's defined.
The fact that version index 1 in the .gnu.version_d section specifies
the library name (SONAME) shouldn't be a reason to default undefined
symbols to version 0.
Is it worth changing the reasonable behavior for 26+ years?
Could the objdump output be updated to stop printing "BASE" for
undefined symbols?
The comment is also posted at
https://sourceware.org/bugzilla/show_bug.cgi?id=33577#c16
More information about the Binutils
mailing list