https://sourceware.org/bugzilla/show_bug.cgi?id=33577

--- Comment #43 from Ali Bahrami <ali_swbugzilla at emvision dot com> ---
(In reply to Michael Matz from comment #42)
> We noted that here:
>   https://sourceware.org/pipermail/binutils/2025-November/145608.html
> with reply here:
>   https://sourceware.org/pipermail/binutils/2025-November/145643.html .

I see, and I agree with the comment in the second one that those
words were a relatively later addition, though they do reflect how
the Solaris ld has always done it. My fuzzy memory of this
is that I added them while working on

    PSARC 2008/603 ELF objects to adopt GNU-style Versym indexes

The Sun style originally did not put version indexes for externally
defined symbols into the versym section, setting those values all
to 0, so while one could deduce that an object had a version dependency
on another object, we could not discern specifically which symbols
were responsible. We decided to adopt that part of the GNU extensions,
and in doing that work, it dawned on me that index 0 has implications
beyond local symbols, leading to questions, and a doc update.


> I don't think any independendness comes into play here.  The ones arguing
> for changing the GNU versioning implementation ultimately always come from
> reading the current Solaris docu, i.e. with the clarifications of NDX_LOCAL.

Great to know. I continue to be grateful for how closely GNU has
stuck to ELF, as well as to these Sun additions, but I try not to
take it for granted.

> Btw, people also try to read into it that it's fine to use NDX_LOCAL also
> for _defined_ symbols.  AFAICS even the clarification in the Solaris>=11
> docu only accepts that when there's no verdef section in the defining file.

The use of NDX_LOCAL for globals is very limited.
One might might interpret this as a license:

    - A global symbol defined within an object that does
      not have a SHT_SUNW_verdef version definition section.

However, I think that rule is intended to describe a dependency
that doesn't have a verdef. Note that the text below this
list goes on to say:

    Versions defined by an object are assigned version indexes
    starting at 1 and incremented by 1 for each version. Index 1
    is reserved for the first global version. If the object does
    not have a SHT_SUNW_verdef version definition section, then
    all the global symbols defined by the object receive index 1.
    If the object does have a version definition section, then
    VER_NDX_GLOBAL simply refers to the first such version

Forgive the verbosity, but a concrete example might be useful.
This hello world program is not itself versioned, but it links
to libc, which is, and so, all of its own definitions end up
in version 1 even though it, itself, does not have a verdef,

    % cc hello.c
    % elfdump -v a.out

    Version Needed Section:  .SUNW_version
      index  file       version    
        [2]  libc.so.1  SYSVABI_1.3

    % elfdump -sN.dynsym a.out

    Symbol Table Section:  .dynsym
      index      value size  type bind oth ver shndx    name
        [0]          0    0  NOTY LOCL  D    0 UNDEF    
        [1]  0x8060d7c  0x4  OBJT GLOB  X    1 .data    __xargc
        [2]  0x8050968    0  FUNC GLOB  D    2 UNDEF    printf
        [3]  0x8050918    0  OBJT GLOB  D    1 .plt        
_PROCEDURE_LINKAGE_TABLE_
        [4]  0x8060d5c  0x4  OBJT WEAK  X    1 .data    environ
        [5]  0x8060c04    0  OBJT GLOB  D    1 .dynamic _DYNAMIC
        [6]  0x8060db0    0  OBJT GLOB  D    1 .data    _edata
        [7]  0x8060d78  0x4  OBJT GLOB  X    1 .data    ___Argv
        [8]  0x8050b90 0x1b  FUNC GLOB  D    1 .init    _init
        [9]  0x8050bc7    0  OBJT GLOB  D    1 .fini    _etext
       [10]          0    0  NOTY GLOB  D    1 ABS      __fsr_init_value
       [11]  0x8050b60 0x2f  FUNC GLOB  D    1 .text    main
       [12]  0x8060d5c  0x4  OBJT GLOB  X    1 .data    _environ
       [13]  0x8060bc8    0  OBJT GLOB  P    1 .got     _GLOBAL_OFFSET_TABLE_
       [14]  0x8060d80  0x4  OBJT GLOB  X    1 .data    __xargv
       [15]  0x8060da8  0x4  OBJT GLOB  D    1 .data    __xpg4
       [16]  0x80508fc  0x4  OBJT GLOB  X    1 .rodata  _lib_version
       [17]  0x8050958    0  FUNC GLOB  D    2 UNDEF    _exit
       [18]  0x8050948    0  FUNC GLOB  D    2 UNDEF    atexit
       [19]  0x8050928    0  FUNC GLOB  D    2 UNDEF    __fpstart
       [20]  0x8060dac  0x4  OBJT GLOB  D    1 .data    __xpg6
       [21]  0x8050938    0  FUNC GLOB  D    2 UNDEF    exit
       [22]  0x8060db0    0  OBJT GLOB  D    1 .data    _end
       [23]  0x8050980 0x86  FUNC GLOB  X    1 .text    _start
       [24]  0x8050bac 0x1b  FUNC GLOB  D    1 .fini    _fini
       [25]  0x8060d60 0x18  OBJT GLOB  X    1 .data    __environ_lock
       [26]  0x8060d84  0x4  OBJT GLOB  X    1 .data    __longdouble_used

As long as versioning is in play, global definitions that
are not otherwise directed to a different version via a
mapfile/linker-script, end up in version 1. And since nearly
everything has a dependency on libc, which is versioned, it's
hard to make an object on Solaris that doesn't assign these
cases to index 1

Note that Rainer manages some modern Solaris systems in the
gcc test farm, and it should be possible to get shell access
in order to poke at these details if that would be useful.


> What's your take on that?  Is a NDX_LOCAL, defined STB_GLOBAL symbol in
> a file that has the verdef section (GNU or Sun variant) available to resolve
> against, or not?  Should it be?

I'm not sure those symbols are useful. Consider the case that
Rainer presented at the start of this, a weak reference, for which
no definition was found during the link-edit. If symbol resolution
is done for it, nothing will be found. However, it seems that we
do support it.

    % cc -m64 -Kpic -G -o vers33.so vers33.c -Mvers33.map
    % elfdump -L vers33.so

    Procedure Linkage Table Section:  .plt
      index   addr  GOT-index  GOT-addr
        [1]  0x960        [4]  0x100a08  show_undef_weak

    % dis -F foo vers33.so 
    disassembly for vers33.so

    foo()
        foo:                    55                 pushq  %rbp
        foo+0x1:                48 8b ec           movq   %rsp,%rbp
        foo+0x4:                48 8b 05 75 00 10  movq   +0x100075(%rip),%rax 
    <0x100a00>
                                00 
        foo+0xb:                48 85 c0           testq  %rax,%rax
        foo+0xe:                74 05              je     +0x5      <foo+0x15>
        foo+0x10:               e8 cb ff ff ff     call   -0x35     <0x960>
        foo+0x15:               c9                 leave  

I created a hello world program to call foo(), and
debugging diagnostics show that we chase it and
fail to find anything:

    % LD_DEBUG=symbols ./a.out |& grep show_undef
    09599: symbol=show_undef_weak;  lookup in file=a.out  [ ELF ]
    09599: symbol=show_undef_weak;  lookup in file=./vers33.so  [ ELF ]
    09599: symbol=show_undef_weak;  lookup in file=/lib/64/libc.so.1  [ ELF ]

I think this says that such symbols are resolved, but
there's likely no resulting benefit.

-----

I'd also like to say that I fully agree that these changes
to the GNU toolchain do need to be phased in over time, seeding
the capability and then waiting for awhile before switching over
to using it. The chaos of an abrupt switch for such a small thing
just isn't worth the cost, but it would be nice to get there gradually.
Our original ask, that is be changed immediately, was due to thinking
it was just a minor bookkeeping matter. We've since been educated to
its much larger impact.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to