Bug 25295 - Gas should have way to define symbol version without exporting its target
Summary: Gas should have way to define symbol version without exporting its target
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: 2.35
: P2 normal
Target Milestone: 2.35
Assignee: H.J. Lu
URL:
Keywords:
: 23840 (view as bug list)
Depends on:
Blocks:
 
Reported: 2019-12-19 09:48 UTC by Jan Hubicka
Modified: 2021-07-31 20:09 UTC (History)
8 users (show)

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


Attachments
A patch to extend .symver directive (1.61 KB, patch)
2020-04-06 18:37 UTC, H.J. Lu
Details | Diff
The updated patch (3.28 KB, patch)
2020-04-06 22:10 UTC, H.J. Lu
Details | Diff
Another update (3.82 KB, patch)
2020-04-06 23:45 UTC, H.J. Lu
Details | Diff
A patch (3.86 KB, patch)
2020-04-07 01:24 UTC, H.J. Lu
Details | Diff
The new patch with documentation (4.68 KB, patch)
2020-04-07 12:08 UTC, H.J. Lu
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Hubicka 2019-12-19 09:48:38 UTC
GCC now support symver attribute.  However in order to make

.symver sym, name@nodename

to work, sym needs to be declared as .globl (already .hidden break things).
In order to produce symbol version one thus need to export also SYM and if that is not part of DSO API the mapfile needs to hide it. This is in conflict with -fvisiblity=hidden and other GCC features.  

For

.symver sym, name@@nodename

we can produce the following:
.type	foo_v2, @function
foo_v2:
.LFB1:
	.cfi_startproc
	movl	$2, %eax
	ret
	.cfi_endproc
.LFE1:
	.size	foo_v2, .-foo_v2
	.globl	.LSYMVER0
	.set	.LSYMVER0,foo_v2
	.symver	.LSYMVER0, foo@@@VERS_2

which seems to have the intdeded behaviour of only exporitng foo@@@VERS_2 from the .o file, but there seems to be no way to to this for foo@VERS_2.
Also it is ugly to require additional symbol.
Comment 1 Jan Hubicka 2019-12-19 14:30:28 UTC
I was looking into the problem bit more.  We want to support

__attribute__((symver("foo@VERS_1"))
int foo()
{
}

which will export foo as foo@VERS_1.  I would also like things like calling foo work as expected, i.e. call foo@VERS_1

Because foo@VERS_1 is not a valid name I need to produce other symbol name (foo.symver1) that will be used at this place, but at the same time I do not want it to be public in the .o symbol table and required to be explicitly hidden by the user via map file (which seems to be common practice now).
Comment 2 Martin Liška 2020-04-06 09:53:01 UTC
(In reply to Jan Hubicka from comment #0)
> GCC now support symver attribute.  However in order to make
> 
> .symver sym, name@nodename
> 
> to work, sym needs to be declared as .globl (already .hidden break things).
> In order to produce symbol version one thus need to export also SYM and if
> that is not part of DSO API the mapfile needs to hide it. This is in
> conflict with -fvisiblity=hidden and other GCC features. 

Are you talking about GAS rejecting such assembly?
Or is it a run-time error where a DSO has broken symbol versions?
Anyway, please provide a self-contained test-case.
Comment 3 Jan Hubicka 2020-04-06 13:09:01 UTC
self contained testcase is in comment #1.
Compiling it leads to following assembly:
        .file   "t.c"
        .text
        .p2align 4
        .globl  foo
        .type   foo, @function
foo:
.LFB0:
        .cfi_startproc
        ret
        .cfi_endproc
.LFE0:
        .size   foo, .-foo
        .symver foo, foo@VERS_1
        .ident  "GCC: (GNU) 10.0.1 20200404 (experimental)"
        .section        .note.GNU-stack,"",@progbits

which translates object file defining both foo and foo@VERS_1

0000000000000000 T foo
0000000000000000 T foo@VERS_1

that in turn require user to hide foo in the linker script.

This is bad since foo must be user defined name and we thus can not support things like multiple symver aliases on one definition.

.symver does two things
 - define syntactic alias that says that whenever foo appears in source file we really refer to foo@VERS_1
 - export foo and foo@VERS_1

I think we want new pseudo that does only the first (but it is not clear to me why symver was implemented this was at first place).
Comment 4 Andreas Schwab 2020-04-06 13:34:18 UTC
Where do you see "export foo and foo@VERS_1"?  All I see is that the alias gets the same attributes as the original symbol, thus it will be external iff the original symbol is.
Comment 5 hubicka 2020-04-06 14:02:23 UTC
> Where do you see "export foo and foo@VERS_1"?  All I see is that the alias gets
> the same attributes as the original symbol, thus it will be external iff the
> original symbol is.
Yes, but I want to implement only foo@VERS_1 in the unit, not foo, so I
do not want to see foo in the symbol table, just foo@VERS_1 and this
does not seem to be possible with current .symver
(there is @@@ vairant that does that for default defs)

Honza
Comment 6 Andreas Schwab 2020-04-06 14:24:14 UTC
What you are looking for is a .globl that accepts a versioned symbol to globalize it, not a variant .symver.
Comment 7 H.J. Lu 2020-04-06 14:42:20 UTC
(In reply to Andreas Schwab from comment #6)
> What you are looking for is a .globl that accepts a versioned symbol to
> globalize it, not a variant .symver.

I don't think it works well with

foo:
        ret
       .size   foo, .-foo
Comment 8 H.J. Lu 2020-04-06 14:47:41 UTC
(In reply to hubicka from comment #5)
> > Where do you see "export foo and foo@VERS_1"?  All I see is that the alias gets
> > the same attributes as the original symbol, thus it will be external iff the
> > original symbol is.
> Yes, but I want to implement only foo@VERS_1 in the unit, not foo, so I
> do not want to see foo in the symbol table, just foo@VERS_1 and this
> does not seem to be possible with current .symver
> (there is @@@ vairant that does that for default defs)
> 
> Honza

How abou

.symver foo, foo@VERS_1, hidden

It will mark foo as hidden.
Comment 9 H.J. Lu 2020-04-06 18:37:13 UTC
Created attachment 12439 [details]
A patch to extend .symver directive

[hjl@gnu-cfl-2 pr25295]$ cat x.s
	.text
	.globl  foo
	.type   foo, %function
foo:
        ret
	.symver foo, foo@VERS_1, hidden
[hjl@gnu-cfl-2 pr25295]$ make x.o
./as   -o x.o x.s
[hjl@gnu-cfl-2 pr25295]$ readelf -sW x.o

Symbol table '.symtab' contains 6 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 FUNC    GLOBAL HIDDEN     1 foo
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT    1 foo@VERS_1
[hjl@gnu-cfl-2 pr25295]$ cat y.s
	.text
	.globl  foo
	.type   foo, %function
foo:
        ret
	.symver foo, foo@VERS_1, local
[hjl@gnu-cfl-2 pr25295]$ make y.o
./as   -o y.o y.s
[hjl@gnu-cfl-2 pr25295]$ readelf -sW y.o

Symbol table '.symtab' contains 6 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 FUNC    LOCAL  DEFAULT    1 foo
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT    1 foo@VERS_1
[hjl@gnu-cfl-2 pr25295]$
Comment 10 Fangrui Song 2020-04-06 20:02:06 UTC
Thanks for CCing me. I'm interested on this topic.

I expressed my feelings on https://sourceware.org/pipermail/binutils/2019-November/108784.html
and https://sourceware.org/bugzilla/show_bug.cgi?id=23840

My idea is that we should treat `.symver foo, bar@V1` as "renaming foo to bar@V1" (
https://reviews.llvm.org/rL369233; This should be the same as Comment #3),
just like what we do with the 3-@ variant `.symver foo, bar@@@V1`

https://sourceware.org/pipermail/binutils/2019-November/108784.html(In reply to H.J. Lu from comment #8)
> (In reply to hubicka from comment #5)
> > > Where do you see "export foo and foo@VERS_1"?  All I see is that the alias gets
> > > the same attributes as the original symbol, thus it will be external iff the
> > > original symbol is.
> > Yes, but I want to implement only foo@VERS_1 in the unit, not foo, so I
> > do not want to see foo in the symbol table, just foo@VERS_1 and this
> > does not seem to be possible with current .symver
> > (there is @@@ vairant that does that for default defs)
> > 
> > Honza
> 
> How abou
> 
> .symver foo, foo@VERS_1, hidden
> 
> It will mark foo as hidden.

I would hope we just rename the symbol (i.e. drop foo).
Comment 11 H.J. Lu 2020-04-06 20:39:58 UTC
(In reply to Fangrui Song from comment #10)
> Thanks for CCing me. I'm interested on this topic.
> 
> I expressed my feelings on
> https://sourceware.org/pipermail/binutils/2019-November/108784.html
> and https://sourceware.org/bugzilla/show_bug.cgi?id=23840
> 
> My idea is that we should treat `.symver foo, bar@V1` as "renaming foo to
> bar@V1" (
> https://reviews.llvm.org/rL369233; This should be the same as Comment #3),
> just like what we do with the 3-@ variant `.symver foo, bar@@@V1`
> 
> https://sourceware.org/pipermail/binutils/2019-November/108784.html(In reply
> to H.J. Lu from comment #8)
> > (In reply to hubicka from comment #5)
> > > > Where do you see "export foo and foo@VERS_1"?  All I see is that the alias gets
> > > > the same attributes as the original symbol, thus it will be external iff the
> > > > original symbol is.
> > > Yes, but I want to implement only foo@VERS_1 in the unit, not foo, so I
> > > do not want to see foo in the symbol table, just foo@VERS_1 and this
> > > does not seem to be possible with current .symver
> > > (there is @@@ vairant that does that for default defs)
> > > 
> > > Honza
> > 
> > How abou
> > 
> > .symver foo, foo@VERS_1, hidden
> > 
> > It will mark foo as hidden.
> 
> I would hope we just rename the symbol (i.e. drop foo).

Rename won't work with:

.symver foo, bar@V1
.symver foo, baz@V2
Comment 12 Fangrui Song 2020-04-06 21:54:49 UTC
(In reply to H.J. Lu from comment #11)
> (In reply to Fangrui Song from comment #10)
> > Thanks for CCing me. I'm interested on this topic.
> > 
> > I expressed my feelings on
> > https://sourceware.org/pipermail/binutils/2019-November/108784.html
> > and https://sourceware.org/bugzilla/show_bug.cgi?id=23840
> > 
> > My idea is that we should treat `.symver foo, bar@V1` as "renaming foo to
> > bar@V1" (
> > https://reviews.llvm.org/rL369233; This should be the same as Comment #3),
> > just like what we do with the 3-@ variant `.symver foo, bar@@@V1`
> > 
> > https://sourceware.org/pipermail/binutils/2019-November/108784.html(In reply
> > to H.J. Lu from comment #8)
> > > (In reply to hubicka from comment #5)
> > > > > Where do you see "export foo and foo@VERS_1"?  All I see is that the alias gets
> > > > > the same attributes as the original symbol, thus it will be external iff the
> > > > > original symbol is.
> > > > Yes, but I want to implement only foo@VERS_1 in the unit, not foo, so I
> > > > do not want to see foo in the symbol table, just foo@VERS_1 and this
> > > > does not seem to be possible with current .symver
> > > > (there is @@@ vairant that does that for default defs)
> > > > 
> > > > Honza
> > > 
> > > How abou
> > > 
> > > .symver foo, foo@VERS_1, hidden
> > > 
> > > It will mark foo as hidden.
> > 
> > I would hope we just rename the symbol (i.e. drop foo).
> 
> Rename won't work with:
> 
> .symver foo, bar@V1
> .symver foo, baz@V2

This just means we cannot reuse `foo`. Each non-default version requires a fresh dummy name, e.g.

.symver foo_V1, bar@V1
.symver foo_V2, bar@V2

The rename is postponed to a very late state.

Very few (probably only 2) pieces of software actually depend on the behavior that the original name exists in the object file.
Comment 13 H.J. Lu 2020-04-06 22:09:25 UTC
*** Bug 23840 has been marked as a duplicate of this bug. ***
Comment 14 H.J. Lu 2020-04-06 22:10:25 UTC
Created attachment 12440 [details]
The updated patch

Also support

[hjl@gnu-cfl-2 pr25295]$ cat a.s
	.global foo
foo:
	ret
	.symver foo, bar@V1
	.symver foo, baz@V2
[hjl@gnu-cfl-2 pr25295]$ make a.o
./as   -o a.o a.s
[hjl@gnu-cfl-2 pr25295]$ readelf -sW a.o

Symbol table '.symtab' contains 7 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 foo
     5: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 bar@V1
     6: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 baz@V2
[hjl@gnu-cfl-2 pr25295]$
Comment 15 Fangrui Song 2020-04-06 23:18:40 UTC
(In reply to H.J. Lu from comment #14)
> Created attachment 12440 [details]
> The updated patch
> 
> Also support
> 
> [hjl@gnu-cfl-2 pr25295]$ cat a.s
> 	.global foo
> foo:
> 	ret
> 	.symver foo, bar@V1
> 	.symver foo, baz@V2
> [hjl@gnu-cfl-2 pr25295]$ make a.o
> ./as   -o a.o a.s
> [hjl@gnu-cfl-2 pr25295]$ readelf -sW a.o
> 
> Symbol table '.symtab' contains 7 entries:
>    Num:    Value          Size Type    Bind   Vis      Ndx Name
>      0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
>      1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
>      2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
>      3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
>      4: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 foo
>      5: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 bar@V1
>      6: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 baz@V2
> [hjl@gnu-cfl-2 pr25295]$

Thanks for your efforts to clean up .symver mess. In particular, I am very happy that in 2000 (https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=79082ff0c6032d8e1e832fe35cc69b3b46d4bd91) you invented @@@ to fix @@ deficiency.

Fundamentally I am not against the following

  .symver foo,foo@v1
  .symver foo,foo@v2

but I suspect it can make implementation difficult. The renaming semantics can probably simplify GNU ld bfd_link_hash_indirect as well.


If the intention is to make a symbol available simultaneously as foo@v1 and foo@v2, the renaming semantics can work with a .set directive:

  globl foo_v1
  .symver foo_v1, foo@v1
  foo_v1:

  .globl foo_v2
  .set foo_v2, foo_v1
  .symver foo_v2, foo@v2

>      4: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 foo

I still hope we can remove `foo` from the symbol table, which is also Comment #3's request.
It is just very inconvenient for an archive user if the symbol remains in the symbol table.
Comment 16 H.J. Lu 2020-04-06 23:45:36 UTC
Created attachment 12441 [details]
Another update

[hjl@gnu-cfl-2 pr25295]$ cat f.s
	.text
	.globl  foo
	.type   foo, %function
foo:
        ret
	.symver foo, foo@VERS_1, fake
[hjl@gnu-cfl-2 pr25295]$ make f.o
./as   -o f.o f.s
[hjl@gnu-cfl-2 pr25295]$ readelf -sW f.o

Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT    1 foo@VERS_1
[hjl@gnu-cfl-2 pr25295]$
Comment 17 H.J. Lu 2020-04-06 23:46:21 UTC
(In reply to Fangrui Song from comment #15)

> I still hope we can remove `foo` from the symbol table, which is also
> Comment #3's request.
> It is just very inconvenient for an archive user if the symbol remains in
> the symbol table.

I added ".symver foo, foo@VERS_1, fake" support.
Comment 18 H.J. Lu 2020-04-07 01:24:27 UTC
Created attachment 12442 [details]
A patch

Change "fake" to "remove".
Comment 19 H.J. Lu 2020-04-07 12:08:19 UTC
Created attachment 12444 [details]
The new patch with documentation
Comment 20 cvs-commit@gcc.gnu.org 2020-04-21 12:37:48 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6914be53bd662eefd979d0c82d2e20e108c4ee66

commit 6914be53bd662eefd979d0c82d2e20e108c4ee66
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue Apr 21 05:33:04 2020 -0700

    gas: Extend .symver directive
    
    Extend .symver directive to update visibility of the original symbol and
    assign one original symbol to different versioned symbols:
    
      .symver foo, foo@VERS_1, local    # Change foo to a local symbol.
      .symver foo, foo@VERS_2, hidden   # Change foo to a hidden symbol.
      .symver foo, foo@@VERS_3, remove  # Remove foo from symbol table.
      .symver foo, bar@V1               # Assign foo to bar@V1 and baz@V2.
      .symver foo, baz@V2
    
            PR gas/23840
            PR gas/25295
            * NEWS: Mention .symver extension.
            * config/obj-elf.c (obj_elf_find_and_add_versioned_name): New
            function.
            (obj_elf_symver): Call obj_elf_find_and_add_versioned_name to
            add a version name.  Add local, hidden and remove visibility
            support.
            (elf_frob_symbol): Handle the list of version names.  Update the
            original symbol to local, hidden or remove it from the symbol
            table.
            (elf_frob_file_before_adjust): Handle the list of version names.
            * config/obj-elf.h (elf_visibility): New.
            (elf_versioned_name_list): Likewise.
            (elf_obj_sy): Change local to bitfield. Add rename, bad_version
            and visibility.  Change versioned_name pointer to struct
            elf_versioned_name_list.
            * doc/as.texi: Update .symver directive.
            * testsuite/gas/symver/symver.exp: Run all *.d tests.  Add more
            error checking tests.
            * testsuite/gas/symver/symver6.d: New file.
            * testsuite/gas/symver/symver7.d: Likewise.
            * testsuite/gas/symver/symver7.s: Likewise.
            * testsuite/gas/symver/symver8.d: Likewise.
            * testsuite/gas/symver/symver8.s: Likewise.
            * testsuite/gas/symver/symver9.s: Likewise.
            * testsuite/gas/symver/symver9a.d: Likewise.
            * testsuite/gas/symver/symver9b.d: Likewise.
            * testsuite/gas/symver/symver10.s: Likewise.
            * testsuite/gas/symver/symver10a.d: Likewise.
            * testsuite/gas/symver/symver10b.d: Likewise.
            * testsuite/gas/symver/symver11.d: Likewise.
            * testsuite/gas/symver/symver11.s: Likewise.
            * testsuite/gas/symver/symver12.d: Likewise.
            * testsuite/gas/symver/symver12.s: Likewise.
            * testsuite/gas/symver/symver13.d: Likewise.
            * testsuite/gas/symver/symver13.s: Likewise.
            * testsuite/gas/symver/symver14.d: Likewise.
            * testsuite/gas/symver/symver14.l: Likewise.
            * testsuite/gas/symver/symver15.d: Likewise.
            * testsuite/gas/symver/symver15.l: Likewise.
            * testsuite/gas/symver/symver6.l: Removed.
            * testsuite/gas/symver/symver6.s: Updated.
Comment 21 H.J. Lu 2020-04-21 12:58:21 UTC
Fixed for 2.35.
Comment 22 Fangrui Song 2020-12-31 18:24:03 UTC
I believe the "local" and "hidden" optional arguments will never be useful.

.symver foo, foo@VERS_1, local
.symver foo, foo@VERS_2, hidden

For @@ definition, users already have `.symver foo, foo@@@VERS_1`

This PR addresses the lingering symbol problem for @ with "remove".


However, I think adding a new directive is probably better to fix all the confusion around @@@ and local/hidden/remove. The new directive should just do
symbol renaming. (https://maskray.me/blog/2020-11-26-all-about-symbol-versioning#Assembler-behavior )
Comment 23 Fangrui Song 2021-07-31 20:09:08 UTC
.symver *, *, remove

The original symbol cannot be used in relocations. This limits `, remove`'s usage. I filed PR gas/28157