Here is a simple example to reproduce the problem: foo.cc ====== extern "C" int foo() { return 0; } __asm__ (".symver foo, foo@VERS_1.1"); foo.map ======= VERS_1.1 { global: foo; }; Now, use BFD linker: $ g++ -B<path to bfd linker> foo.cc -fPIC -shared -Wl,--version-script=./foo.map -o libfoo.so $ nm libfoo.so | grep foo 0000000000000700 T foo@VERS_1.1 The symbol is versioned. Now, use gold linker and repeat: $ g++ -B<path to gold linker> foo.cc -fPIC -shared -Wl,--version-script=./foo.map -o libfoo.so $ nm libfoo.so | grep foo 0000000000000740 T foo The symbol is not versioned. This affects building libgcc_s.so in trunk GCC with gold as symbol __cpu_indicator_init is versioned in the exact manner as described.
You're looking at the linker symbol table with nm. (And nm does not show versioning information from the .gnu.version* sections.) When I build this with gold, readelf -Vs shows: Symbol table '.dynsym' contains 13 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 3: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (3) 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses 6: 00000000000006f5 11 FUNC GLOBAL DEFAULT 12 foo@@VERS_1.1 7: 0000000000002018 0 NOTYPE GLOBAL DEFAULT ABS _edata 8: 0000000000002019 0 NOTYPE GLOBAL DEFAULT ABS _end 9: 00000000000005c0 0 FUNC GLOBAL DEFAULT 10 _init 10: 0000000000002018 0 NOTYPE GLOBAL DEFAULT ABS __bss_start 11: 0000000000000700 0 FUNC GLOBAL DEFAULT 13 _fini 12: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS VERS_1.1 ... Version symbols section '.gnu.version' contains 13 entries: Addr: 0000000000000458 Offset: 0x000458 Link: 2 (.dynsym) 000: 0 (*local*) 0 (*local*) 0 (*local*) 3 (GLIBC_2.2.5) 004: 0 (*local*) 0 (*local*) 2 (VERS_1.1) 1 (*global*) 008: 1 (*global*) 1 (*global*) 1 (*global*) 1 (*global*) 00c: 2 (VERS_1.1) Version definition section '.gnu.version_d' contains 2 entries: Addr: 0x0000000000000474 Offset: 0x000474 Link: 3 (.dynstr) 000000: Rev: 1 Flags: BASE Index: 1 Cnt: 1 Name: ver1.so 0x001c: Rev: 1 Flags: none Index: 2 Cnt: 1 Name: VERS_1.1 Version needs section '.gnu.version_r' contains 1 entries: Addr: 0x00000000000004ac Offset: 0x0004ac Link: 3 (.dynstr) 000000: Version: 1 File: libc.so.6 Cnt: 1 0x0010: Name: GLIBC_2.2.5 Flags: none Version: 3 I think this is working as intended, although comparing with Gnu ld output, I see that gold defines it as a default version ("@@") where Gnu ld does not. I'm not sure what the logic ought to be for that. Without the __asm__ in the .c file, Gnu ld also makes it a default version.
On Tue, Jul 21, 2015 at 11:03 AM, ccoutant at gmail dot com <sourceware-bugzilla@sourceware.org> wrote: > https://sourceware.org/bugzilla/show_bug.cgi?id=18703 > > --- Comment #1 from Cary Coutant <ccoutant at gmail dot com> --- > You're looking at the linker symbol table with nm. (And nm does not show > versioning information from the .gnu.version* sections.) > > When I build this with gold, readelf -Vs shows: > > Symbol table '.dynsym' contains 13 entries: > Num: Value Size Type Bind Vis Ndx Name > 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND > 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ > 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND > _ITM_deregisterTMCloneTab > 3: 0000000000000000 0 FUNC WEAK DEFAULT UND > __cxa_finalize@GLIBC_2.2.5 (3) > 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND > _ITM_registerTMCloneTable > 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses > 6: 00000000000006f5 11 FUNC GLOBAL DEFAULT 12 foo@@VERS_1.1 > 7: 0000000000002018 0 NOTYPE GLOBAL DEFAULT ABS _edata > 8: 0000000000002019 0 NOTYPE GLOBAL DEFAULT ABS _end > 9: 00000000000005c0 0 FUNC GLOBAL DEFAULT 10 _init > 10: 0000000000002018 0 NOTYPE GLOBAL DEFAULT ABS __bss_start > 11: 0000000000000700 0 FUNC GLOBAL DEFAULT 13 _fini > 12: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS VERS_1.1 > > ... > > Version symbols section '.gnu.version' contains 13 entries: > Addr: 0000000000000458 Offset: 0x000458 Link: 2 (.dynsym) > 000: 0 (*local*) 0 (*local*) 0 (*local*) 3 (GLIBC_2.2.5) > 004: 0 (*local*) 0 (*local*) 2 (VERS_1.1) 1 (*global*) > 008: 1 (*global*) 1 (*global*) 1 (*global*) 1 (*global*) > 00c: 2 (VERS_1.1) > > Version definition section '.gnu.version_d' contains 2 entries: > Addr: 0x0000000000000474 Offset: 0x000474 Link: 3 (.dynstr) 000000: Rev: 1 > Flags: BASE Index: 1 Cnt: 1 Name: ver1.so > 0x001c: Rev: 1 Flags: none Index: 2 Cnt: 1 Name: VERS_1.1 > > Version needs section '.gnu.version_r' contains 1 entries: > Addr: 0x00000000000004ac Offset: 0x0004ac Link: 3 (.dynstr) > 000000: Version: 1 File: libc.so.6 Cnt: 1 > 0x0010: Name: GLIBC_2.2.5 Flags: none Version: 3 > > I think this is working as intended, although comparing with Gnu ld output, I > see that gold defines it as a default version ("@@") where Gnu ld does not. I'm > not sure what the logic ought to be for that. Without the __asm__ in the .c > file, Gnu ld also makes it a default version. Some context: https://gcc.gnu.org/ml/gcc-patches/2015-04/msg00878.html This was used to hide symbols __cpu_indicator_init and __cpu_model defined in libgcc_s.so so that this symbol is always obtained from libgcc.a. Now, this works with GNU ld and not with gold. Isnt this an incompatibility. If this is not well defined, is there another well defined way of achieving the same result? Thanks Sri > > -- > You are receiving this mail because: > You reported the bug.
Sorry, I need more context than that. You've said that the symbol is not versioned, but in fact it is. The only differences between the two linkers that I see are: (1) The name that appears in the linker symbol table, which shouldn't matter to the loader at all. If this is causing a problem, can you point to the section in the linker manual that describes the correct behavior? I don't think gold was designed with the intent of propagating @-style version information into the output binary. We only use the version sections, and, as far as I know, the dynamic loader only uses version sections. (2) Gold defines the symbol as a default version, while Gnu ld doesn't. If this is the problem, I'll need to understand what the proper logic is for determining whether a symbol should be marked as the default version. You said this affects building libgcc_s.so in trunk, but you haven't said what is actually failing. -cary On Tue, Jul 21, 2015 at 4:51 PM, tmsriram at google dot com <sourceware-bugzilla@sourceware.org> wrote: > https://sourceware.org/bugzilla/show_bug.cgi?id=18703 > > --- Comment #2 from Sriraman Tallam <tmsriram at google dot com> --- > On Tue, Jul 21, 2015 at 11:03 AM, ccoutant at gmail dot com > <sourceware-bugzilla@sourceware.org> wrote: >> https://sourceware.org/bugzilla/show_bug.cgi?id=18703 >> >> --- Comment #1 from Cary Coutant <ccoutant at gmail dot com> --- >> You're looking at the linker symbol table with nm. (And nm does not show >> versioning information from the .gnu.version* sections.) >> >> When I build this with gold, readelf -Vs shows: >> >> Symbol table '.dynsym' contains 13 entries: >> Num: Value Size Type Bind Vis Ndx Name >> 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND >> 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ >> 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND >> _ITM_deregisterTMCloneTab >> 3: 0000000000000000 0 FUNC WEAK DEFAULT UND >> __cxa_finalize@GLIBC_2.2.5 (3) >> 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND >> _ITM_registerTMCloneTable >> 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses >> 6: 00000000000006f5 11 FUNC GLOBAL DEFAULT 12 foo@@VERS_1.1 >> 7: 0000000000002018 0 NOTYPE GLOBAL DEFAULT ABS _edata >> 8: 0000000000002019 0 NOTYPE GLOBAL DEFAULT ABS _end >> 9: 00000000000005c0 0 FUNC GLOBAL DEFAULT 10 _init >> 10: 0000000000002018 0 NOTYPE GLOBAL DEFAULT ABS __bss_start >> 11: 0000000000000700 0 FUNC GLOBAL DEFAULT 13 _fini >> 12: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS VERS_1.1 >> >> ... >> >> Version symbols section '.gnu.version' contains 13 entries: >> Addr: 0000000000000458 Offset: 0x000458 Link: 2 (.dynsym) >> 000: 0 (*local*) 0 (*local*) 0 (*local*) 3 (GLIBC_2.2.5) >> 004: 0 (*local*) 0 (*local*) 2 (VERS_1.1) 1 (*global*) >> 008: 1 (*global*) 1 (*global*) 1 (*global*) 1 (*global*) >> 00c: 2 (VERS_1.1) >> >> Version definition section '.gnu.version_d' contains 2 entries: >> Addr: 0x0000000000000474 Offset: 0x000474 Link: 3 (.dynstr) 000000: Rev: 1 >> Flags: BASE Index: 1 Cnt: 1 Name: ver1.so >> 0x001c: Rev: 1 Flags: none Index: 2 Cnt: 1 Name: VERS_1.1 >> >> Version needs section '.gnu.version_r' contains 1 entries: >> Addr: 0x00000000000004ac Offset: 0x0004ac Link: 3 (.dynstr) >> 000000: Version: 1 File: libc.so.6 Cnt: 1 >> 0x0010: Name: GLIBC_2.2.5 Flags: none Version: 3 >> >> I think this is working as intended, although comparing with Gnu ld output, I >> see that gold defines it as a default version ("@@") where Gnu ld does not. I'm >> not sure what the logic ought to be for that. Without the __asm__ in the .c >> file, Gnu ld also makes it a default version. > > Some context: > > https://gcc.gnu.org/ml/gcc-patches/2015-04/msg00878.html > > This was used to hide symbols __cpu_indicator_init and __cpu_model > defined in libgcc_s.so so that this symbol is always obtained from > libgcc.a. Now, this works with GNU ld and not with gold. Isnt this an > incompatibility. If this is not well defined, is there another well > defined way of achieving the same result? > > Thanks > Sri > > >> >> -- >> You are receiving this mail because: >> You reported the bug. > > -- > You are receiving this mail because: > You are on the CC list for the bug. > You are the assignee for the bug.
(In reply to Cary Coutant from comment #1) > I think this is working as intended, although comparing with Gnu ld output, > I see that gold defines it as a default version ("@@") where Gnu ld does > not. I'm not sure what the logic ought to be for that. Without the __asm__ > in the .c file, Gnu ld also makes it a default version. From "info as": Another usage of the '.symver' directive is: .symver NAME, NAME2@@NODENAME In this case, the symbol NAME must exist and be defined within the file being assembled. It is similar to NAME2@NODENAME. The difference is NAME2@@NODENAME will also be used to resolve references to NAME2 by the linker. Linker shouldn't use foo@VERS_1.1 to resolve references to foo.
From "info ld": To do this, you must use multiple '.symver' directives in the source file. Here is an example: __asm__(".symver original_foo,foo@"); __asm__(".symver old_foo,foo@VERS_1.1"); __asm__(".symver old_foo1,foo@VERS_1.2"); __asm__(".symver new_foo,foo@@VERS_2.0"); In this example, 'foo@' represents the symbol 'foo' bound to the unspecified base version of the symbol. The source file that contains this example would define 4 C functions: 'original_foo', 'old_foo', 'old_foo1', and 'new_foo'. When you have multiple definitions of a given symbol, there needs to be some way to specify a default version to which external references to this symbol will be bound. You can do this with the 'foo@@VERS_2.0' type of '.symver' directive. You can only declare one version of a symbol as the default in this manner; otherwise you would effectively have multiple definitions of the same symbol.
> Another usage of the '.symver' directive is: > .symver NAME, NAME2@@NODENAME > In this case, the symbol NAME must exist and be defined within the > file being assembled. It is similar to NAME2@NODENAME. The difference > is NAME2@@NODENAME will also be used to resolve references to NAME2 by > the linker. > > Linker shouldn't use foo@VERS_1.1 to resolve references to foo. Yes, I understand that much. The example given uses: .symver foo, foo@VERS_1.1 where the original symbol and the versioned symbol both have the same name. This produces two symbols in the .o file named "foo": 0000000000000000 T foo 0000000000000000 T foo@VERS_1.1 With the version script, gold sees the first of those (plain "foo") and makes it the default version (as, I think, it should). The second one is just seen as a second declaration, but it's already been marked the default. If I change Sri's example to use ".symver orig_foo, foo@VERS_1.1" and rename "foo" to "orig_foo", I get the following in the dynamic symbol table: 6: 0000000000000725 11 FUNC GLOBAL DEFAULT 12 foo@VERS_1.1 7: 0000000000000725 11 FUNC GLOBAL DEFAULT 12 orig_foo If it's the "@@" vs. "@" that's causing the problem, then there's your fix. -cary
(In reply to Cary Coutant from comment #6) > > Another usage of the '.symver' directive is: > > .symver NAME, NAME2@@NODENAME > > In this case, the symbol NAME must exist and be defined within the > > file being assembled. It is similar to NAME2@NODENAME. The difference > > is NAME2@@NODENAME will also be used to resolve references to NAME2 by > > the linker. > > > > Linker shouldn't use foo@VERS_1.1 to resolve references to foo. > > Yes, I understand that much. The example given uses: > > .symver foo, foo@VERS_1.1 > > where the original symbol and the versioned symbol both have the same > name. This produces two symbols in the .o file named "foo": > > 0000000000000000 T foo > 0000000000000000 T foo@VERS_1.1 > > With the version script, gold sees the first of those (plain "foo") > and makes it the default version (as, I think, it should). The second > one is just seen as a second declaration, but it's already been marked > the default. > foo is versioned and only version specified is VERS_1.1, which is not default version. It is wrong to create a default foo without being asked to do so.
On Tue, Jul 21, 2015 at 5:07 PM, ccoutant at gmail dot com <sourceware-bugzilla@sourceware.org> wrote: > https://sourceware.org/bugzilla/show_bug.cgi?id=18703 > > --- Comment #3 from Cary Coutant <ccoutant at gmail dot com> --- > Sorry, I need more context than that. You've said that the symbol is > not versioned, but in fact it is. The only differences between the two > linkers that I see are: Hi Cary, I am just learning symbol versioning after running into this bug so apologies if I misunderstood. The particular bug I am running into this. I am looking at libgcc_s.so.1 linked with GNU-ld and linked with the gold linker. Based on your comments, I think I understand this a little better so let me atleast try to get explain my problem: With GNU ld linked libgcc_s.so.1, symbol __cpu_indicator_init looks like this in the .dynsym: 4: 0000000000002bb0 815 FUNC GLOBAL DEFAULT 11 __cpu_indicator_init@GCC_4.8.0 whereas with gold linked libgcc_s.so.1, symbol __cpu_indicator_init shows up as: 15: 0000000000002c10 783 FUNC GLOBAL DEFAULT 12 __cpu_indicator_init@@GCC_4.8.0 I see the extra "@" now, I almost missed it last time as I did not know about this! What is happening because of this subtle change is a bug with function multi-versioning and shared objects. foomv.cc ----------- __attribute__((target("default"))) void foo() { printf("This is default\n"); } __attribute__((target("avx"))) void foo() { printf("This is AVX\n"); } int callfoo() { foo(); } If I use the GNU ld linked libgcc_s.so.1, $ g++ -fPIC -shared foomv.cc -o libfoomv.so -Wl,-z,now -Wl,-y,__cpu_indicator_init libgcc_s.so.1: definition of __cpu_indicator_init libgcc.a(cpuinfo.o): definition of __cpu_indicator_init The definition of __cpu_indicator_init always comes from libgcc.a even if it found libgcc_s.so.1 earlier. whereas if I use gold linked libgcc_s.so.1 $ g++ -fPIC -shared foomv.cc -o libfoomv.so -Wl,-z,now -Wl,-y,__cpu_indicator_init libgcc_s.so.1: definition of __cpu_indicator_init it uses the definition in the shared object. The problem with this is it creates a plt entry for __cpu_indicator_init and __cpu_indicator_init gets called from an ifunc function before the DSO can be relocated leading to a seg fault. From your later comments, it does look like the difference is because of the extra "@" added by gold to make it the default symbol. Thanks Sri > > (1) The name that appears in the linker symbol table, which shouldn't > matter to the loader at all. If this is causing a problem, can you > point to the section in the linker manual that describes the correct > behavior? I don't think gold was designed with the intent of > propagating @-style version information into the output binary. We > only use the version sections, and, as far as I know, the dynamic > loader only uses version sections. > > (2) Gold defines the symbol as a default version, while Gnu ld > doesn't. If this is the problem, I'll need to understand what the > proper logic is for determining whether a symbol should be marked as > the default version. > > You said this affects building libgcc_s.so in trunk, but you haven't > said what is actually failing. > > -cary > > > On Tue, Jul 21, 2015 at 4:51 PM, tmsriram at google dot com > <sourceware-bugzilla@sourceware.org> wrote: >> https://sourceware.org/bugzilla/show_bug.cgi?id=18703 >> >> --- Comment #2 from Sriraman Tallam <tmsriram at google dot com> --- >> On Tue, Jul 21, 2015 at 11:03 AM, ccoutant at gmail dot com >> <sourceware-bugzilla@sourceware.org> wrote: >>> https://sourceware.org/bugzilla/show_bug.cgi?id=18703 >>> >>> --- Comment #1 from Cary Coutant <ccoutant at gmail dot com> --- >>> You're looking at the linker symbol table with nm. (And nm does not show >>> versioning information from the .gnu.version* sections.) >>> >>> When I build this with gold, readelf -Vs shows: >>> >>> Symbol table '.dynsym' contains 13 entries: >>> Num: Value Size Type Bind Vis Ndx Name >>> 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND >>> 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ >>> 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND >>> _ITM_deregisterTMCloneTab >>> 3: 0000000000000000 0 FUNC WEAK DEFAULT UND >>> __cxa_finalize@GLIBC_2.2.5 (3) >>> 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND >>> _ITM_registerTMCloneTable >>> 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses >>> 6: 00000000000006f5 11 FUNC GLOBAL DEFAULT 12 foo@@VERS_1.1 >>> 7: 0000000000002018 0 NOTYPE GLOBAL DEFAULT ABS _edata >>> 8: 0000000000002019 0 NOTYPE GLOBAL DEFAULT ABS _end >>> 9: 00000000000005c0 0 FUNC GLOBAL DEFAULT 10 _init >>> 10: 0000000000002018 0 NOTYPE GLOBAL DEFAULT ABS __bss_start >>> 11: 0000000000000700 0 FUNC GLOBAL DEFAULT 13 _fini >>> 12: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS VERS_1.1 >>> >>> ... >>> >>> Version symbols section '.gnu.version' contains 13 entries: >>> Addr: 0000000000000458 Offset: 0x000458 Link: 2 (.dynsym) >>> 000: 0 (*local*) 0 (*local*) 0 (*local*) 3 (GLIBC_2.2.5) >>> 004: 0 (*local*) 0 (*local*) 2 (VERS_1.1) 1 (*global*) >>> 008: 1 (*global*) 1 (*global*) 1 (*global*) 1 (*global*) >>> 00c: 2 (VERS_1.1) >>> >>> Version definition section '.gnu.version_d' contains 2 entries: >>> Addr: 0x0000000000000474 Offset: 0x000474 Link: 3 (.dynstr) 000000: Rev: 1 >>> Flags: BASE Index: 1 Cnt: 1 Name: ver1.so >>> 0x001c: Rev: 1 Flags: none Index: 2 Cnt: 1 Name: VERS_1.1 >>> >>> Version needs section '.gnu.version_r' contains 1 entries: >>> Addr: 0x00000000000004ac Offset: 0x0004ac Link: 3 (.dynstr) >>> 000000: Version: 1 File: libc.so.6 Cnt: 1 >>> 0x0010: Name: GLIBC_2.2.5 Flags: none Version: 3 >>> >>> I think this is working as intended, although comparing with Gnu ld output, I >>> see that gold defines it as a default version ("@@") where Gnu ld does not. I'm >>> not sure what the logic ought to be for that. Without the __asm__ in the .c >>> file, Gnu ld also makes it a default version. >> >> Some context: >> >> https://gcc.gnu.org/ml/gcc-patches/2015-04/msg00878.html >> >> This was used to hide symbols __cpu_indicator_init and __cpu_model >> defined in libgcc_s.so so that this symbol is always obtained from >> libgcc.a. Now, this works with GNU ld and not with gold. Isnt this an >> incompatibility. If this is not well defined, is there another well >> defined way of achieving the same result? >> >> Thanks >> Sri >> >> >>> >>> -- >>> You are receiving this mail because: >>> You reported the bug. >> >> -- >> You are receiving this mail because: >> You are on the CC list for the bug. >> You are the assignee for the bug. > > -- > You are receiving this mail because: > You reported the bug.
(In reply to Sriraman Tallam from comment #8) > > From your later comments, it does look like the difference is because > of the extra "@" added by gold to make it the default symbol. > Linker shouldn't add the extra "@" when being asked not to do so explicitly.
>> 0000000000000000 T foo >> 0000000000000000 T foo@VERS_1.1 >> >> With the version script, gold sees the first of those (plain "foo") >> and makes it the default version (as, I think, it should). The second >> one is just seen as a second declaration, but it's already been marked >> the default. > > foo is versioned and only version specified is VERS_1.1, which is not > default version. It is wrong to create a default foo without being asked > to do so. In this example, "foo" is both unversioned and versioned. In response to the unversioned one, gold is creating a default version, as directed by the linker script. If "foo@VERS_1.1" were the only version of "foo" in this file, gold would not make it a default version. If you don't want a default version, get rid of the first, unversioned, "foo", and gold will do what you expect. I've played around with a bunch of different combinations, and I can't even begin to unravel the logic behind Gnu ld's behavior when there are multiple instances of versioned and unversioned symbols. I have no desire to try to reproduce its behavior beyond what's described in the documentation. -cary
(In reply to Cary Coutant from comment #10) > > In this example, "foo" is both unversioned and versioned. In response > to the unversioned one, gold is creating a default version, as > directed by the linker script. If "foo@VERS_1.1" were the only version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Linker script only specifies a version of VERS_1.1 and input file has VERS_1.1 as the non-default version. Linker shouldn't change VERS_1.1 from non-default to default. > of "foo" in this file, gold would not make it a default version. > > If you don't want a default version, get rid of the first, > unversioned, "foo", and gold will do what you expect. > > I've played around with a bunch of different combinations, and I can't > even begin to unravel the logic behind Gnu ld's behavior when there > are multiple instances of versioned and unversioned symbols. I have no > desire to try to reproduce its behavior beyond what's described in the > documentation. The documentation can have some improvements. But ld.bfd behavior is well-defined as shown by testcases in ld/testsuite/ld-elfvers.
> The documentation can have some improvements. But ld.bfd behavior is > well-defined as shown by testcases in ld/testsuite/ld-elfvers. If you're going to maintain that ".symver foo,foo@VER" is valid, then I think the assembler needs to be fixed so that it doesn't assume that the original name and the versioned name don't have the same base. In obj-elf.c, elf_frob_symbol seems to be written with the assumption that they are different. The following patch fixes that so that we don't get the duplicate symbol: diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 78dc6d9..8668be0 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -2182,6 +2182,11 @@ elf_frob_symbol (symbolS *symp, int *puntp) memmove (&p[2], &p[3], l); S_SET_NAME (symp, sy_obj->versioned_name); } + else if (strncmp (S_GET_NAME (symp), sy_obj->versioned_name, + strlen (S_GET_NAME (symp))) == 0) + { + S_SET_NAME (symp, sy_obj->versioned_name); + } else { symbolS *symp2; (testsuite/gas/elf/symver.d and testsuite/gas/symver/symver1.d will also need adjusting.) With that patch to gas, gold now has the same behavior for Sri's test case (and it also passes the vers27d1.c test case in the ld testsuite). Shall I forward this bug to gas? As long as gas is emitting an unversioned symbol, I'm going to maintain that gold is doing the right thing in assigning it a default version.
Change assembler may break existing code. I think gold should behave the same as ld on this.
I created users/hjl/gold-test branch and added ld-elfvers/vers-gold.exp to run ld symbol version tests with gold: [hjl@gnu-6 ld]$ make check RUNTESTFLAGS="vers-gold.exp" ... Running /export/gnu/import/git/sources/binutils-gdb/ld/testsuite/ld-elfvers/vers-gold.exp ... FAIL: vers1 FAIL: vers2 FAIL: vers3 FAIL: vers6 FAIL: vers8 ERROR: tcl error sourcing library file /export/gnu/import/git/sources/binutils-gdb/ld/testsuite/lib/../ld-elfvers/vers.exp. cp: cannot stat 'tmpdir/vers1.so': No such file or directory cp: cannot stat 'tmpdir/vers1.so': No such file or directory while executing "exec cp $tmpdir/$srclib $tmpdir/$libname.so" (procedure "test_strip_vers_lib" line 11) invoked from within "test_strip_vers_lib "vers14" vers1.so vers14 vers1.ver vers1.dsym" (file "/export/gnu/import/git/sources/binutils-gdb/ld/testsuite/lib/../ld-elfvers/vers.exp" line 893) invoked from within "source /export/gnu/import/git/sources/binutils-gdb/ld/testsuite/lib/../ld-elfvers/vers.exp" ("uplevel" body line 1) invoked from within "uplevel #0 source /export/gnu/import/git/sources/binutils-gdb/ld/testsuite/lib/../ld-elfvers/vers.exp" invoked from within "catch "uplevel #0 source ${dir}/${initfile}" error" Makefile:3506: recipe for target 'check-DEJAGNU' failed make[3]: *** [check-DEJAGNU] Error 1 make[3]: Leaving directory '/export/build/gnu/binutils-gold/build-x86_64-linux/ld' Makefile:1852: recipe for target 'check-am' failed make[2]: *** [check-am] Error 2 make[2]: Leaving directory '/export/build/gnu/binutils-gold/build-x86_64-linux/ld' Makefile:1699: recipe for target 'check-recursive' failed make[1]: *** [check-recursive] Error 1 make[1]: Leaving directory '/export/build/gnu/binutils-gold/build-x86_64-linux/ld' Makefile:1854: recipe for target 'check' failed make: *** [check] Error 2 [hjl@gnu-6 ld]$ The first failure is: /export/build/gnu/binutils-gold/build-x86_64-linux/ld/../gold/ld-new -o tmpdir/vers1.so --shared --no-undefined-version tmpdir/vers1.o --version-script /export/gnu/import/git/sources/binutils-gdb/ld/testsuite/ld-elfvers/vers1.map Executing on host: sh -c {/export/build/gnu/binutils-gold/build-x86_64-linux/ld/../gold/ld-new -o tmpdir/vers1.so --shared --no-undefined-version tmpdir/vers1.o --version-script /export/gnu/import/git/sources/binutils-gdb/ld/testsuite/ld-elfvers/vers1.map 2>&1} /dev/null ld.tmp (timeout = 300) spawn [open ...]^M /export/build/gnu/binutils-gold/build-x86_64-linux/ld/../gold/ld-new: error: symbol show_foo has undefined version /export/build/gnu/binutils-gold/build-x86_64-linux/ld/../gold/ld-new: error: symbol show_foo has undefined version FAIL: vers1 I don't think you can expect gold will always generate the working output when symbol version is used.
On Tue, Jul 21, 2015 at 5:35 PM, ccoutant at gmail dot com <sourceware-bugzilla@sourceware.org> wrote: > https://sourceware.org/bugzilla/show_bug.cgi?id=18703 > > --- Comment #6 from Cary Coutant <ccoutant at gmail dot com> --- >> Another usage of the '.symver' directive is: >> .symver NAME, NAME2@@NODENAME >> In this case, the symbol NAME must exist and be defined within the >> file being assembled. It is similar to NAME2@NODENAME. The difference >> is NAME2@@NODENAME will also be used to resolve references to NAME2 by >> the linker. >> >> Linker shouldn't use foo@VERS_1.1 to resolve references to foo. > > Yes, I understand that much. The example given uses: > > .symver foo, foo@VERS_1.1 > > where the original symbol and the versioned symbol both have the same > name. This produces two symbols in the .o file named "foo": > > 0000000000000000 T foo > 0000000000000000 T foo@VERS_1.1 > > With the version script, gold sees the first of those (plain "foo") > and makes it the default version (as, I think, it should). The second > one is just seen as a second declaration, but it's already been marked > the default. > > If I change Sri's example to use ".symver orig_foo, foo@VERS_1.1" and > rename "foo" to "orig_foo", I get the following in the dynamic symbol > table: > > 6: 0000000000000725 11 FUNC GLOBAL DEFAULT 12 foo@VERS_1.1 > 7: 0000000000000725 11 FUNC GLOBAL DEFAULT 12 orig_foo > > If it's the "@@" vs. "@" that's causing the problem, then there's your fix. H.J. : Can we use Cary's idea to fix libgcc/config/i386/cpuinfo.c to make libgcc_s.so.1 do the right thing with gold too until this issue is resolved in some manner? Thanks Sri > > -cary > > -- > You are receiving this mail because: > You reported the bug.
(In reply to Sriraman Tallam from comment #15) > > H.J. : Can we use Cary's idea to fix libgcc/config/i386/cpuinfo.c to > make libgcc_s.so.1 do the right thing with gold too until this issue > is resolved in some manner? > You can pass -fuse-ld=bfd to build libgcc_s.so.1 on Linux: diff --git a/libgcc/config/i386/t-linux b/libgcc/config/i386/t-linux index 11bb46e..12aab16 100644 --- a/libgcc/config/i386/t-linux +++ b/libgcc/config/i386/t-linux @@ -3,4 +3,8 @@ # t-slibgcc-elf-ver and t-linux SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/i386/libgcc-glibc.ver +# Work around gold bug: +# https://sourceware.org/bugzilla/show_bug.cgi?id=18703 +SHLIB_LDFLAGS += -fuse-ld=bfd + HOST_LIBGCC2_CFLAGS += -mlong-double-80 -DUSE_ELF_SYMVER Or you have to make sure those symbols in both libgcc.a and libgcc.so.1 are correct.
On Wed, Jul 22, 2015 at 11:24 AM, hjl.tools at gmail dot com <sourceware-bugzilla@sourceware.org> wrote: > https://sourceware.org/bugzilla/show_bug.cgi?id=18703 > > --- Comment #16 from H.J. Lu <hjl.tools at gmail dot com> --- > (In reply to Sriraman Tallam from comment #15) >> >> H.J. : Can we use Cary's idea to fix libgcc/config/i386/cpuinfo.c to >> make libgcc_s.so.1 do the right thing with gold too until this issue >> is resolved in some manner? >> > > You can pass -fuse-ld=bfd to build libgcc_s.so.1 on Linux: > > diff --git a/libgcc/config/i386/t-linux b/libgcc/config/i386/t-linux > index 11bb46e..12aab16 100644 > --- a/libgcc/config/i386/t-linux > +++ b/libgcc/config/i386/t-linux > @@ -3,4 +3,8 @@ > # t-slibgcc-elf-ver and t-linux > SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/i386/libgcc-glibc.ver > > +# Work around gold bug: > +# https://sourceware.org/bugzilla/show_bug.cgi?id=18703 > +SHLIB_LDFLAGS += -fuse-ld=bfd > + > HOST_LIBGCC2_CFLAGS += -mlong-double-80 -DUSE_ELF_SYMVER > > Or you have to make sure those symbols in both libgcc.a and libgcc.so.1 > are correct. Thanks this works. However, i ran into another problem. Our GCC build does not use -fvisibility=hidden to build libgcc.a. So, __cpu_indicator_init is GLOBAL in libgcc.a and not LOCAL. Which means any shared object that references __cpu_indicator_init will still create a PLT entry for it and fail at run-time. This is not directly related to this bug but thought I would mention it here while we are fixing this problem. Thanks Sri > > -- > You are receiving this mail because: > You reported the bug.
Another change you can make is to remove "foo" from the version script entirely. If foo.map is just this: VERS_1.1 { }; then both linkers will put "foo@VERS_1.1" into the dynamic symbol table (no default version). If you're going to use .symver to set the version, there's really no point in also using a version script to do the same thing. It just sets up a conflicting situation where different linkers might give different behaviors. -cary
> FAIL: vers1 This is because gold does not handle "sym@" properly. Working on it. > FAIL: vers2 > FAIL: vers3 > FAIL: vers6 > FAIL: vers8 These look like the same root problem. > ERROR: tcl error sourcing library file > /export/gnu/import/git/sources/binutils-gdb/ld/testsuite/lib/../ld-elfvers/ > vers.exp. > cp: cannot stat 'tmpdir/vers1.so': No such file or directory > cp: cannot stat 'tmpdir/vers1.so': No such file or directory > while executing > "exec cp $tmpdir/$srclib $tmpdir/$libname.so" > (procedure "test_strip_vers_lib" line 11) > invoked from within > "test_strip_vers_lib "vers14" vers1.so vers14 vers1.ver vers1.dsym" > (file > "/export/gnu/import/git/sources/binutils-gdb/ld/testsuite/lib/../ld-elfvers/ > vers.exp" line 893) > invoked from within > "source > /export/gnu/import/git/sources/binutils-gdb/ld/testsuite/lib/../ld-elfvers/ > vers.exp" > ("uplevel" body line 1) > invoked from within > "uplevel #0 source > /export/gnu/import/git/sources/binutils-gdb/ld/testsuite/lib/../ld-elfvers/ > vers.exp" > invoked from within > "catch "uplevel #0 source ${dir}/${initfile}" error" > Makefile:3506: recipe for target 'check-DEJAGNU' failed Not sure what this is. Looks more like a problem with the dejagnu script?
The master branch has been updated by Cary Coutant <ccoutant@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b45e00b3ed40589af75b8a36a67905ae265a20f8 commit b45e00b3ed40589af75b8a36a67905ae265a20f8 Author: Cary Coutant <ccoutant@gmail.com> Date: Mon Jul 27 15:09:08 2015 -0700 Fix symbol versioning problems in PR 18703. If a symbol is defined with ".symver foo,foo@VER", the assembler creates two symbols in the object: one unversioned, and one with the (non-default) version "VER". If foo is listed in a version script, gold would then make the first of those symbols the default version, and would ignore the second symbol as a duplicate, without making it a non-default version. While this is arguably reasonable behavior, it doesn't match Gnu ld behavior, so this patch fixes that by allowing the second definition to override the first by resetting the "default version" indication. Several test cases from the Gnu ld testsuite also exposed another related problem, where a symbol defined with ".symver foo,foo@", placed into a shared library, is not handled properly by gold. This patch also fixes that case, binding the symbol to the base version. gold/ PR gold/18703 * dynobj.cc (Versions::record_version): Handle symbol defined with base version. (Versions::symbol_section_contents): Likewise. * symtab.h (Symbol::set_is_not_default): New class method. (Symbol_table::resolve): Add is_default_version parameter. (Symbol_table::should_override): Likewise. * resolve.cc (Symbol_table::resolve): Add is_default_version parameter, and pass to should_override. Adjust all callers and explicit instantiations. (Symbol_table::should_override): Add is_default_value parameter; allow default version in a dynamic object to override existing definition from same object. * symtab.cc (Symbol_table::add_from_object): Handle case where same symbol is defined as unversioned and non-default version in the same object. * testsuite/Makefile.am (ver_test_13): New test case. * testsuite/Makefile.in: Regenerate. * testsuite/ver_test_4.cc: Add test for symbol with base version. * testsuite/ver_test_4.sh: Likewise. * testsuite/ver_test_13.c: New source file. * testsuite/ver_test_13.script: New version script. * testsuite/ver_test_13.sh: New test case.
Fixed on trunk.
The master branch has been updated by Cary Coutant <ccoutant@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3ac0a36c297a7bb3325c6efa756cccc40572dbdb commit 3ac0a36c297a7bb3325c6efa756cccc40572dbdb Author: Cary Coutant <ccoutant@gmail.com> Date: Tue Aug 25 17:53:53 2015 -0700 Fix regression introduced by fix for PR 18703. When a user object overrides a versioned definition in a shared object, it's possible to trigger an internal error because the versioned definition we saw didn't override the unversioned definition. This was introduced by the fix for PR 18703. This patch fixes the problem by reordering the tests so that we do not check ret->is_default() until we're confident that the symbol is in fact versioned. gold/ PR gold/18866 PR gold/18703 * symtab.cc (Symbol_table): Reorder conditions to avoid internal error.
*** Bug 13521 has been marked as a duplicate of this bug. ***