Bug 48200

Summary: Implement function attribute for symbol versioning (.symver)
Product: gcc Reporter: Zeev Tarantov <zeev.tarantov>
Component: ltoAssignee: Jan Hubicka <hubicka>
Status: ASSIGNED ---    
Severity: normal CC: amodra, bergner, crrodriguez, dimhen, egallager, fw, hubicka, mark, pageexec, sjames, slyich, wcohen, zack+srcbugz
Priority: P3 Keywords: lto, patch
Version: 4.6.0   
Target Milestone: ---   
URL: https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01334.html
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59893
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60160
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57703
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95194
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/278
https://github.com/llvm/llvm-project/issues/85585
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2011-03-21 12:58:42
Attachments: sources, object files and two shared objects: one good, one bad (resulted from linking with LTO)
Patch to add symver attribute, highly experimental, C++ only
symverp

Description Zeev Tarantov 2011-03-19 01:13:42 UTC
The library is libpci.so.3.1.7, released 2010-01-31, part of every linux distro.
Homepage is: http://mj.ucw.cz/pciutils.html, source repository is: http://www.kernel.org/git/?p=utils/pciutils/pciutils.git;a=shortlog

Object files compiled with CFLAGS: "-O2 -fPIC -Wall -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -flto".

If linked with: gcc -shared -Wl,-O1 -Wl,--as-needed -Wl,-soname,libpci.so.3 -Wl,--version-script=libpci.ver -o libpci.so.3.1.7 init.o access.o generic.o dump.o names.o filter.o names-hash.o names-parse.o names-net.o names-cache.o params.o caps.o sysfs.o proc.o i386-ports.o  -lz -lresolv

Then (as expected): objdump -T libpci.so.3.1.7 | grep pci_fill_info
00000000000032f0 g    DF .text  000000000000006c (LIBPCI_3.0) pci_fill_info
00000000000032f0 g    DF .text  000000000000006c  LIBPCI_3.1  pci_fill_info

But if linked with LTO: gcc -shared -Wl,-O1 -Wl,--as-needed -Wl,-flto -Wl,-soname,libpci.so.3 -Wl,--version-script=libpci.ver -o libpci.so.3.1.7 init.o access.o generic.o dump.o names.o filter.o names-hash.o names-parse.o names-net.o names-cache.o params.o caps.o sysfs.o proc.o i386-ports.o  -lz -lresolv

Then: objdump -T libpci.so.3.1.7 | grep pci_fill_info

No such symbol.

gcc (Gentoo SVN) 4.6.0-pre9999 20110318 (prerelease) rev. 171169
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

GNU ld (Linux/GNU Binutils) 2.21.51.0.7.20110306
Copyright 2011 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

I don't know enough to tell whether the problem is in pciutils, binutils or gcc. If this is invalid and I'm just spamming, I apologize. Please kindly point me in the right direction to fix this issue.

Preproccessed source is (relevant parts):

int pci_fill_info(struct pci_dev *, int flags) __attribute__((visibility("default")));
# 170 "pci.h"

int pci_fill_info_v30(struct pci_dev *, int flags) __attribute__((visibility("default")));
int pci_fill_info_v31(struct pci_dev *, int flags) __attribute__((visibility("default")));


int
pci_fill_info_v31(struct pci_dev *d, int flags)
{
  if (flags & 0x10000)
    {
      flags &= ~0x10000;
      d->known_fields = 0;
      pci_free_caps(d);
    }
  if (flags & ~d->known_fields)
    d->known_fields |= d->methods->fill_info(d, flags & ~d->known_fields);
  return d->known_fields;
}


;
extern int pci_fill_info_v30(struct pci_dev *d, int flags) __attribute__((alias("pci_fill_info_v31")));
asm(".symver " "pci_fill_info_v30" "," "pci_fill_info@LIBPCI_3.0");
asm(".symver " "pci_fill_info_v31" "," "pci_fill_info@@LIBPCI_3.1");
Comment 1 Richard Biener 2011-03-21 12:58:42 UTC
This is not enough to reproduce the issue, even making the source compile
ends up failing with

/usr/bin/ld: t.o: version node not found for symbol pci_fill_info@LIBPCI_3.0
/usr/bin/ld: failed to set dynamic section sizes: Bad value
collect2: ld returned 1 exit status

please provide a complete compilable testcase.  Thanks.
Comment 2 Zeev Tarantov 2011-03-21 18:18:26 UTC
Created attachment 23740 [details]
sources, object files and two shared objects: one good, one bad (resulted from linking with LTO)
Comment 3 Zeev Tarantov 2011-03-21 18:26:46 UTC
I am sorry but I don't know which parts are relevant. The source is GPL2, I just ran "make SHARED=yes CFLAGS="-fPIC -O2 -flto" lib/libpci.so.3.1.7" and then linked the SO a second time with -Wl,-flto (as if it was in the LDFLAGS) and attached a tarball with the result. You can compare the two (renamed) shared objects, built from the same object files and version script.

I'll try to construct a minimal (single file, single symbol) test case.
Comment 4 Zeev Tarantov 2011-03-21 22:40:12 UTC
I've constructed a trivial example, the bug did not reproduce in it.
I've tried -save-temps and -Wl,--verbose but those did not reveal anything.
I do not have a nicer testcase than comment #2.
Comment 5 Richard Biener 2011-03-22 10:02:24 UTC
Confirmed.

I think what happens is that the symver global asms get partitioned away
from the function definitions.  With -flto-partition=none it works for me.

> grep pci_fill_info libpci.so.3.1.7.ltrans?.s
libpci.so.3.1.7.ltrans0.s:      .symver pci_fill_info_v30,pci_fill_info@LIBPCI_3.0
libpci.so.3.1.7.ltrans0.s:      .symver pci_fill_info_v31,pci_fill_info@@LIBPCI_3.1
libpci.so.3.1.7.ltrans1.s:      call    pci_fill_info_v31@PLT
libpci.so.3.1.7.ltrans1.s:      .globl  pci_fill_info_v31
libpci.so.3.1.7.ltrans1.s:      .type   pci_fill_info_v31, @function
libpci.so.3.1.7.ltrans1.s:pci_fill_info_v31:
libpci.so.3.1.7.ltrans1.s:      .size   pci_fill_info_v31, .-pci_fill_info_v31
libpci.so.3.1.7.ltrans1.s:      .globl  pci_fill_info_v30
libpci.so.3.1.7.ltrans1.s:      .set    pci_fill_info_v30,pci_fill_info_v31
libpci.so.3.1.7.ltrans2.s:      call    pci_fill_info_v31@PLT

so indeed that is what happens (-save-temps appended to the link command
produces those intermediate files).

We can't really know better (we do not parse asm strings), -flto-partition=none
is a workaround.  A fix would be to not use toplevel asms, but I'm not sure
a different way for the symvers exists (maybe it's possible to do entirely
in the linker script ...).
Comment 6 Richard Biener 2011-03-22 10:13:49 UTC
Btw, the minimal partition size is quite small (1000), 10 times smaller
than our large-unit-insns inline limit and 2.7 times smaller than our
large function inline limit.  Upping that limit by a factor of 10 magically
solves this problem by only using a single partition automagically
(it looks to me that it should be similar to large-unit-insns anyway).
Comment 7 Jan Hubicka 2011-03-22 23:04:08 UTC
Well, upping it only workarounds the problem and you loose parallelizm linking
small files.  I did bit of tunning on this compiling one of spec2k benchmarks
(twolf?) to get smallest time with the cpus I had (4 if I remember)

Honza
Comment 8 Richard Biener 2011-03-23 10:06:17 UTC
(In reply to comment #7)
> Well, upping it only workarounds the problem and you loose parallelizm linking
> small files.  I did bit of tunning on this compiling one of spec2k benchmarks
> (twolf?) to get smallest time with the cpus I had (4 if I remember)

Well ... I suppose this also heavily depends on your I/O speed.  Nevetheless
the number _looks_ awfully low compared to those others.
Comment 9 Jan Hubicka 2011-03-23 13:12:37 UTC
> Well ... I suppose this also heavily depends on your I/O speed.  Nevetheless
> the number _looks_ awfully low compared to those others.
Well, totally minimizing compilation of small unit is not very worthwhile.  It was from time I was
trying to stress whopr to get issues like this one soon.

It does not matter if we build application in 1/100th of second or 1/200th of
second and too much parallelizm could slow down build of many small binaries.
I guess we could shoot for resonable user response. UI guys thinks it is about
1/3rd of second, so I would not mind tuning number up until compilation on not
terribly high end system approximately gets to this time.

I don't think this is however terribly related to large unit sizes and inliner stuff.

Honza
Comment 10 Roman Khimov 2014-06-16 14:28:02 UTC
I can confirm the same bug with pciutils 3.2.1 and GCC 4.9.0, although now it's pci_fill_info_v32().
Comment 11 Alan Modra 2014-08-05 07:19:29 UTC
There's a similar issue when compiling libgcc for powerpc64. libgcc/config/rs6000/ibm-ldouble.c has these aliases:
__asm__ (".symver __gcc_qadd,_xlqadd@GCC_3.4\n\t"
	 ".symver __gcc_qsub,_xlqsub@GCC_3.4\n\t"
	 ".symver __gcc_qmul,_xlqmul@GCC_3.4\n\t"
	 ".symver __gcc_qdiv,_xlqdiv@GCC_3.4\n\t"
	 ".symver .__gcc_qadd,._xlqadd@GCC_3.4\n\t"
	 ".symver .__gcc_qsub,._xlqsub@GCC_3.4\n\t"
	 ".symver .__gcc_qmul,._xlqmul@GCC_3.4\n\t"
	 ".symver .__gcc_qdiv,._xlqdiv@GCC_3.4");

Which seem to get dropped if you use -flto.
Comment 12 Xi Ruoyao 2018-05-03 08:18:57 UTC
This issue makes the shared libraries (libstdc++.so etc.) unusable if GCC is bootstrapped with C{XX,}FLAGS_FOR_TARGET="-flto -O3".
Comment 13 Jan Hubicka 2018-05-03 08:25:58 UTC
Concerning comment #11, if you have toplevel asms you need to disable LTO for that unit, as there is no way to tell for gcc what the asm statement is doing. Perhaps attribute would be better way to do this?

What is status of this bug in general? I must admit I thought we have issues long solved here :(
Comment 14 Xi Ruoyao 2018-05-03 09:37:29 UTC
(In reply to Jan Hubicka from comment #13)
> What is status of this bug in general? I must admit I thought we have issues
> long solved here :(

It still exists in 8.1.  Libstdc++ uses top level asm statement for symbol versioning.  Then symbol std::istream::ignore(long)@GLIBCXX_3_4 just disappears, and libstdc++.so can't be used (this symbol becomes *UND*).
Comment 15 Xi Ruoyao 2018-05-03 09:50:50 UTC
(In reply to Jan Hubicka from comment #13)
> Concerning comment #11, if you have toplevel asms you need to disable LTO
> for that unit, as there is no way to tell for gcc what the asm statement is
> doing. Perhaps attribute would be better way to do this?

Well then this is PR 57703.   Should we mark duplicate? :(
Comment 16 Richard Biener 2018-05-03 10:08:30 UTC
(In reply to Xi Ruoyao from comment #15)
> (In reply to Jan Hubicka from comment #13)
> > Concerning comment #11, if you have toplevel asms you need to disable LTO
> > for that unit, as there is no way to tell for gcc what the asm statement is
> > doing. Perhaps attribute would be better way to do this?
> 
> Well then this is PR 57703.   Should we mark duplicate? :(

I think the bug is sufficiently different and should have different workarounds.

We might want to add a function attribute to allow to specify symver, so like

int pci_fill_info_v31(struct pci_dev *d, int flags) __attribute__((alias("pci_fill_info"), symver("@LIBPCI_3.0"));

or similar (combine alias and symver as symver_alias?).  Or simply
recognize @ in alias.
Comment 17 Xi Ruoyao 2018-05-03 11:33:35 UTC
(In reply to Richard Biener from comment #16)

> We might want to add a function attribute to allow to specify symver, so like
> 
> int pci_fill_info_v31(struct pci_dev *d, int flags)
> __attribute__((alias("pci_fill_info"), symver("@LIBPCI_3.0"));
> 
> or similar (combine alias and symver as symver_alias?).  Or simply
> recognize @ in alias.

But a normal alias is

int pci_fill_info(struct pci_dev *, int) __attribute__((alias("pci_fill_info_v31")));

The exported name is the function declare name, and the actual name is in alias attribute.

I prefer

int pci_fill_info(struct pci_dev *, int) __attribute__((symver_alias("@LIBPCI_3.0", "pci_fill_info_v31")));
Comment 18 Xi Ruoyao 2018-05-03 12:51:56 UTC
(In reply to Xi Ruoyao from comment #17)

> I prefer
> 
> int pci_fill_info(struct pci_dev *, int)
> __attribute__((symver_alias("@LIBPCI_3.0", "pci_fill_info_v31")));

But then what should we do for

int pci_fill_info(struct pci_dev *, int)
__attribute__((symver_alias("@LIBPCI_3.0", "pci_fill_info_v31")));

int pci_fill_info(struct pci_dev *, int)
__attribute__((symver_alias("@LIBPCI_3.1", "pci_fill_info_v32")));
Comment 19 Xi Ruoyao 2018-05-10 15:05:03 UTC
I think the best result would be like FMV, for e.g.

int foo(void) __attribute__((symver("@1.1")))
{
  return 0;
}

int foo(void) __attribute__((symver("@@1.2")))
{
  return 1;
}

Would produce two symbols "foo.symver.1.1" and "foo.symver.1.2", and

.symver foo.symver.1.1 foo@1.1
.symver foo.symver.1.2 foo@@1.2

And we can also use

int foo(void) __attribute__((symver("@1.0"), alias("foo_old")));

But this seems difficult in C FE, it tends to complain the "redefine" of foo - note that FMV is still only for C++ until now.
Comment 20 Martin Liška 2018-05-11 13:45:49 UTC
(In reply to Xi Ruoyao from comment #19)
> I think the best result would be like FMV, for e.g.
> 
> int foo(void) __attribute__((symver("@1.1")))
> {
>   return 0;
> }
> 
> int foo(void) __attribute__((symver("@@1.2")))
> {
>   return 1;
> }
> 
> Would produce two symbols "foo.symver.1.1" and "foo.symver.1.2", and
> 
> .symver foo.symver.1.1 foo@1.1
> .symver foo.symver.1.2 foo@@1.2
> 
> And we can also use
> 
> int foo(void) __attribute__((symver("@1.0"), alias("foo_old")));
> 
> But this seems difficult in C FE, it tends to complain the "redefine" of foo
> - note that FMV is still only for C++ until now.

Sounds reasonable to me. I have some experience with MVC so I will work on that in this stage1.
Comment 21 Xi Ruoyao 2018-05-14 08:13:59 UTC
I made up a (highly immature) patch in the days.

This "thing" works with simple source code files but I believe there are many bugs in the patch.

And I suggest to make "weakref" attribute to output ".symver" directive for arguments with "@" in it.  For e.g.

static void *old_memcpy (void *, void *, size_t) __attribute__((weakref("memcpy@GLIBC_2.2.5")));

should produce

.symver old_memcpy memcpy@GLIBC_2.2.5

So we can "import" old functions.
Comment 22 Xi Ruoyao 2018-05-14 08:17:38 UTC
Created attachment 44126 [details]
Patch to add symver attribute, highly experimental, C++ only
Comment 23 Martin Liška 2018-05-14 08:20:34 UTC
(In reply to Xi Ruoyao from comment #22)
> Created attachment 44126 [details]
> Patch to add symver attribute, highly experimental, C++ only

That's great you did the prototype. I'll take a look.
Comment 24 Eric Gallager 2018-06-15 18:05:13 UTC
(In reply to Richard Biener from comment #16)
> (In reply to Xi Ruoyao from comment #15)
> > (In reply to Jan Hubicka from comment #13)
> > > Concerning comment #11, if you have toplevel asms you need to disable LTO
> > > for that unit, as there is no way to tell for gcc what the asm statement is
> > > doing. Perhaps attribute would be better way to do this?
> > 
> > Well then this is PR 57703.   Should we mark duplicate? :(
> 
> I think the bug is sufficiently different and should have different
> workarounds.
> 

Still worth putting under "See Also" at least...
Comment 25 Xi Ruoyao 2018-07-29 07:45:02 UTC
This attribute should also apply to objects.
Comment 26 Zack Weinberg 2018-08-06 14:21:19 UTC
/subscribe

I've tripped over this problem myself in the context of the new password-hashing library, libxcrypt (see https://github.com/besser82/libxcrypt/issues/24 )  Our symbol-versioning techniques are lifted from glibc (see https://github.com/besser82/libxcrypt/blob/aae4c1baea534d2e4c9dfe2faf42ee0c5f7a6f22/crypt-port.h#L122 ).  Function attributes seem like a good replacement to me, although I'd ask that people think about how a library author might write macros that will seamlessly fall back to the older technique.
Comment 27 Martin Liška 2018-11-13 15:13:11 UTC
Assigning to Honza at will require usage of transparent aliases, so some extra work will be needed.
Comment 28 Florian Weimer 2019-01-04 20:39:31 UTC
It seems that using symbol aliases (via .symver) in conjunction with LTO and a version script which has a local: * clause causes the LTO plugin to assume that the aliased function definitions are not (externally) referenced, so GCC will elide them.  The workaround for now appears to be to put __attribute__ ((externally_visible)) on the aliased functions, so that GCC assumes that there is a reference to them that it cannot see.

-flto-partition=none may also be needed.
Comment 29 Xi Ruoyao 2019-02-05 11:38:07 UTC
I'm sure -flto-parition=none is needed for workaround, now.
It keeps .symver directive and the function definition in the same assembly file.
Unfortunately for large codebase -flto-partition leads to OOM.
Comment 30 Xi Ruoyao 2019-07-11 19:05:09 UTC
Pick up this again...

Now __asm__(".symver a, b@@ver") is used for two different purposes:

1. Mark a function/object *definition* as the specified version.
2. "Import" a symbol (function/object) with the specified version.

If we make up two attributes for those two purposes, life will be easier.  For 1 we can emit ".symver" directive when the definition is emited.  For 2 we can borrow the logic from .weakref and do minimal change.
Comment 31 Martin Liška 2019-07-17 07:27:27 UTC
*** Bug 91186 has been marked as a duplicate of this bug. ***
Comment 32 Andrew Pinski 2019-09-27 10:25:57 UTC
>I'm sure -flto-parition=none is needed for workaround, now.

This does not always work.  I think if the symver was done in an archive.
Comment 33 Andrew Pinski 2019-09-27 10:26:37 UTC
See https://mails.dpdk.org/archives/dev/2019-September/144749.html also.
Comment 34 Tomasz Kłoczko 2019-11-12 15:12:48 UTC
Any progress on that issue?
Just hit that issue trying to build NetworkManager

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/278
Comment 35 Jan Hubicka 2019-11-12 17:55:50 UTC
> Any progress on that issue?
> Just hit that issue trying to build NetworkManager
> 
> https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/278

I am working on a patch for symver attribute, hope to have it done this
week.

Honza
Comment 36 Tomasz Kłoczko 2019-11-12 20:09:03 UTC
Thanks for update.

Please let me know when you will have working version of your patch.
I have ready to use gcc build in which after about two hours (my gcc compile time) I would be able to to try to help you test that patch :)

Just point to exact patch in git or attach the patch here.
Comment 37 Jan Hubicka 2019-11-14 21:17:00 UTC
*** Bug 66825 has been marked as a duplicate of this bug. ***
Comment 38 Jan Hubicka 2019-11-14 21:28:25 UTC
Created attachment 47268 [details]
symverp

Hi,
I am attaching prototype patch.  It implements "symver" attribute which
can be attached to a definition such as:

hubicka@lomikamen-jh:/aux/hubicka/trunk5/build4/gcc$ cat t.c
__attribute__ ((symver("bar@2.2")))
int t()
{
}
hubicka@lomikamen-jh:/aux/hubicka/trunk5/build4/gcc$ ./xgcc -B ./ -O2 t.c -S
hubicka@lomikamen-jh:/aux/hubicka/trunk5/build4/gcc$ cat t.s
        .file   "t.c"
        .text
        .p2align 4
        .globl  t
        .type   t, @function
t:
.LFB0:
        .cfi_startproc
        ret
        .cfi_endproc
.LFE0:
        .size   t, .-t
        .symver t, bar@2.2
        .ident  "GCC: (GNU) 10.0.0 20191114 (experimental)"
        .section        .note.GNU-stack,"",@progbits

Internally it defines a new kind of alias (symver alias) with assembler
name "bar@2.2" so LTO symbol table match ELF symbol table for the unit:

hubicka@lomikamen-jh:/aux/hubicka/trunk5/build4/gcc$ nm t.o
0000000000000000 T bar@2.2
0000000000000000 T t
hubicka@lomikamen-jh:/aux/hubicka/trunk5/build4/gcc$ ./xgcc -B ./ -O2
t.c -c -flto
hubicka@lomikamen-jh:/aux/hubicka/trunk5/build4/gcc$ gcc-nm t.o
00000000 T bar@2.2
00000000 T t

Internally in GCC the symver is handled just as normal alias only output
differntly.  I think GCC, just like static linker, does not really need
to understand the versions because there are no direct ways to bind to
those symbols.

I wonder if someone sees limitations to this design (in particular
attaching the symver directly to the definition). 

In PR66825 Carlos proposed "version_def" attribute which can be
implemented too (I suppose all I need is to concatenate the strings into
the actual name).  I wonder what would be preferred and easier for
users?

Also Carlos proposes "version_ref" that can be used for external
definitions.  I am not quite sure how to do that with existing GAS and
LTO since different translation units can reffer to different versions.
But my understnading is that for LTO it is critical to implement the def
part.

Hopefully I can turn this into a patch proposal tomorrow to meet the
stage1 deadline, so comments are welcome especially if they come really
soon :)

Honza
Comment 39 Xi Ruoyao 2019-11-14 21:47:22 UTC
(In reply to Jan Hubicka from comment #38)

> Internally in GCC the symver is handled just as normal alias only output
> differntly.  I think GCC, just like static linker, does not really need
> to understand the versions because there are no direct ways to bind to
> those symbols.
> 
> I wonder if someone sees limitations to this design (in particular
> attaching the symver directly to the definition). 

I think this design is correct.  "symver" attribute is introduced to "bind" a symver to a definition.  If they can be seperated LTO will do stupid things.

I prefer "symver" than "version_def".
Comment 40 Jan Hubicka 2019-11-15 09:05:51 UTC
I posted initial patch here
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01334.html
Comment 41 Xi Ruoyao 2019-12-16 04:44:36 UTC
(In reply to Jan Hubicka from comment #40)
> I posted initial patch here
> https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01334.html

I applied it into gcc-9.2.0 and it works.  But, unfortunately, the problem with LTO and symver is not fixed.

A simple testcase fails:

$ cat foo.c
__attribute__ ((__symver__ ("foo@VERS_1")))
int foo_v1 (void)
{
	return 1;
}

__attribute__ ((__symver__ ("foo@@VERS_2")))
int foo_v2 (void)
{
	return 2;
}
$ cat version.map
VERS_1 {
global:
	foo;
local:
	*;
};

VERS_2 {
} VERS_1;
$ gcc foo.c -flto -Wl,--version-script -Wl,version.map -shared -Wl,--as-needed --save-temp
$ cat foo.res
1
foo.o 4
211 93dd820662070d19 PREVAILING_DEF_IRONLY foo_v1
213 93dd820662070d19 PREVAILING_DEF_IRONLY foo@VERS_1
222 93dd820662070d19 PREVAILING_DEF_IRONLY foo_v2
224 93dd820662070d19 PREVAILING_DEF_IRONLY foo@@VERS_2
$ grep symver cc*.s || echo "no symver"
no symver
Comment 42 Xi Ruoyao 2019-12-17 06:42:13 UTC
I just sent a patch making symver attribute "really" useful for LTO.

https://gcc.gnu.org/ml/gcc-patches/2019-12/msg01162.html
Comment 43 Mark Wielaard 2020-04-15 12:46:47 UTC
It looks there is now some support for a symver function attribute. But it only accepts the single and double @ forms. This makes things a little awkward when using a symbol foo itself for foo@@DEFAULT_VERSION. It causes the (non-versioned) foo symbol to still appear in the object, which doesn't work very nicely when combined with linker version scripts.

For elfutils I had to workaround that by adding foo also to a non-exported version section, so that the assembler and linker didn't both try to create a default version for foo:
https://sourceware.org/pipermail/elfutils-devel/2020q2/002609.html

It works, but feels like a hack. Please also support the @@@ symver variant.
Comment 44 Jan Hubicka 2020-05-06 13:45:41 UTC
Thanks, I am happy we now have real-world use of symver attribute.  I have WIP patch for better control over the symbol visibility, but I have run into problems with gas limitations which was fixed by HJ about two weeks ago.
I will try to update the patch and aim for backporting to gcc 10.2.
Comment 45 Mark Wielaard 2021-01-04 09:41:21 UTC
Note that the hack in comment 43 doesn't really work with elfutils since the .symver attribute doesn't work exactly like the assembly construct with @@@. The @@@ symver variant see https://sourceware.org/binutils/docs/as/Symver.html

The third usage of the .symver directive is:

.symver name, name2@@@nodename

When name is not defined within the file being assembled, it is treated as name2@nodename. When name is defined within the file being assembled, the symbol name, name, will be changed to name2@@nodename. 

Which means it is renamed, so that it doesn't clash when used in a version map file.
Comment 46 Andrew Pinski 2021-08-30 04:35:39 UTC
LTO was fixed at r10-5568.

I think we can close this as fixed for GCC 10.
Comment 47 Andrew Pinski 2021-08-30 04:37:32 UTC
(In reply to Mark Wielaard from comment #45)
> Note that the hack in comment 43 doesn't really work with elfutils since the
> .symver attribute doesn't work exactly like the assembly construct with @@@.
> The @@@ symver variant see
> https://sourceware.org/binutils/docs/as/Symver.html
> 
> The third usage of the .symver directive is:
> 
> .symver name, name2@@@nodename
> 
> When name is not defined within the file being assembled, it is treated as
> name2@nodename. When name is defined within the file being assembled, the
> symbol name, name, will be changed to name2@@nodename. 
> 
> Which means it is renamed, so that it doesn't clash when used in a version
> map file.

Reopen for this part of the discussion since I misunderstood it at first.