<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 - ThinLTO doesn't import .symver directives"
   href="https://bugs.llvm.org/show_bug.cgi?id=48214">48214</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>ThinLTO doesn't import .symver directives
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>new-bugs
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </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>enhancement
          </td>
        </tr>

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

        <tr>
          <th>Component</th>
          <td>new bugs
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>hans@chromium.org
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Consider this example:

$ cat /tmp/a.c
extern int foo();

int main(int argc, char **argv) {
  return foo(argc);
}

$ cat /tmp/b.c
#include <math.h>

__asm__(".symver pow, <a href="mailto:pow@GLIBC_2.2.5">pow@GLIBC_2.2.5</a>");

int foo(int x) {
  return (int)pow(3, x);
}


What the code is doing is that b.c uses the pow() symbol from glibc, but
instead of the default version (GLIBC_2.29 on my system), it uses the .symver
directive to request a specific version:

$ bin/clang -O2 -fuse-ld=lld /tmp/a.c /tmp/b.c -lm -o foo && objdump -T foo |
grep pow
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 pow


However, with ThinLTO that no longer works:

$ bin/clang -O2 -fuse-ld=lld -flto=thin /tmp/a.c /tmp/b.c -lm -o foo && objdump
-T foo | grep pow
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.29  pow
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 pow


I believe what's happening here is that when ThinLTO imports foo() into the IR
Module for a.c, it also imports the pow() declaration, but it doesn't import
the inline asm string, and so the .symver directive isn't applied in that
module.


We hit this in Chromium, which adds these directives to math.h in its sysroot
in order to control what versions of these symbols to link against.
(crbug.com/1105253)

I understand this is a somewhat unorthodox use of the directive -- normally
.symver is used on function definitions when building a shared library, not on
function declarations. However
<a href="https://sourceware.org/binutils/docs/as/Symver.html#Symver">https://sourceware.org/binutils/docs/as/Symver.html#Symver</a> does make it sound
like this is a supported use: "If the symbol /name/ is not defined within the
file being assembled, all references to /name/ will be changed to
name2@nodename."</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>