<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - symbol version "has undefined version error" when all symbols with version are hidden."
   href="https://bugs.llvm.org/show_bug.cgi?id=36295">36295</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>symbol version "has undefined version error" when all symbols with version are hidden.
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>lld
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>ELF
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>peter.smith@linaro.org
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>While attempting to build the Android dynamic linker on Arm I ran into many
errors of the form:
"out/soong/.intermediates/bionic/libc/libc_nomalloc/android_arm_armv7-a_static_core/libc_nomalloc.a(__aeabi.o):
symbol __aeabi_memcpy@LIBC_PRIVATE has undefined version LIBC_PRIVATE"
"error:
out/soong/.intermediates/bionic/libc/libc_nomalloc/android_arm_armv7-a_static_core/libc_nomalloc.a(__aeabi.o):
symbol __aeabi_memmove8@@LIBC_N has undefined version LIBC_N"

I did not get these errors with ld.gold, although I did get them with ld.bfd.
The errors are only Arm specific on the dynamic linker because the file
__aeabi.o is Arm specific.

It turns out that there was indeed no version script [*] so the LIBC_PRIVATE
and LIBC_N were not defined. However the dynamic linker links with the flag
"--exclude-libs ALL" which prevents symbols in the library from being exported
into the dynamic symbol table.

A simplified reproducer on x86:
t.s:
        .globl foo_impl2
foo_impl2:
        ret

        .symver foo_impl, foo@@LIBC_N
        .symver foo_impl2, foo@LIBC_PRIVATE
t2.s:
        .text
        .globl foo
        .globl _start
_start:        
        ret

        .data
        .quad foo
clang -fPIC t.s t2.s -c
ld.gold --shared t2.o t.a -o t2.so --exclude-libs ALL # All works fine
ld.bfd --shared t2.o t.a -o t2.so --exclude-libs ALL
t2.so: version node not found for symbol foo@LIBC_PRIVATE
ld.lld --shared t2.o t.a -o t2.so --exclude-libs ALL 
ld.lld: error: t.a(t.o): symbol foo@@LIBC_N has undefined version LIBC_N
ld.lld: error: t.a(t.o): symbol foo@LIBC_PRIVATE has undefined version
LIBC_PRIVATE


Something like "--exclude-libs ALL" is important to get this past gold as the
.symver foo_impl, foo@@VERSION will always create the symbol foo with
STV_DEFAULT visibility.

I don't think that there is a clear answer in the symbol versioning
specification as to whether the linker should give an error in this case. It is
true that the version isn't defined, but if the symbol isn't in the dynamic
symbol table then do we care? Gold will give an error message if a symbol
definition in the dynamic symbol table has an undefined version. Personally I
have some sympathy for Gold's view, for example lld doesn't give an error
message for an undefined version in an executable.

For what it is worth, and this could be a separate PR, I noticed that when I
wrote a simple symbol version script for LLD to force the symbols local, they
were exported into the dynamic symbol table with default visibility:

LIBC_PRIVATE
{
local:
  foo;
};

LIBC_N
{
local:
 foo;
};
ld.lld --shared t2.o t.a -o t2.so --exclude-libs ALL --version-script=t.version
readelf --dyn-syms t2.so
Symbol table '.dynsym' contains 4 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000001000     0 NOTYPE  GLOBAL DEFAULT    8 _start
     2: 0000000000001004     0 NOTYPE  GLOBAL DEFAULT    8 foo@@LIBC_N
     3: 0000000000001005     0 NOTYPE  GLOBAL DEFAULT    8 foo@LIBC_PRIVATE

My understanding of local: was that it was supposed to prevent symbols from
being exported into the symbol table, and this is the behaviour I see from gold
and bfd. It could be that my symbol version script is wrong though.

I think that there are potentially two changes that could be made:
- Do not error if there is no version defined for a symbol that isn't in the
dynamic symbol table.
- LLD's local: implementation doesn't seem to be working for the version script
above. 

[*] The libc_nomalloc.a library is used in the bionic libc library where LIBC_N
and LIBC_PRIVATE are defined in a version script, and in the dynamic linker
where there are no definitions.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>