<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 - -fsanitize=cfi-icall inhibits dead code stripping for mixed ThinLTO/native builds"
   href="https://bugs.llvm.org/show_bug.cgi?id=37474">37474</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>-fsanitize=cfi-icall inhibits dead code stripping for mixed ThinLTO/native builds
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </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>Interprocedural Optimizations
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>vlad@tsyrklevich.net
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>vlad@tsyrklevich.net
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>kcc@google.com, llvm-bugs@lists.llvm.org, peter@pcc.me.uk
          </td>
        </tr></table>
      <p>
        <div>
        <pre>This issue is causing the size regression noted in
<a href="https://bugs.chromium.org/p/chromium/issues/detail?id=841916">https://bugs.chromium.org/p/chromium/issues/detail?id=841916</a> when enabling
-fsanitize=cfi-icall. This regression is caused by 1. nacl_helper pulling in
lots of code it doesn't seem to use and later strips (e.g. ffmpeg), 2. ThinLTO
not being able to determine what is live outside of ThinLTO compiled bitcode
(e.g. in native object files generated from assembly), and 3. LowerTypeTests
emitting references to dead address-taken functions in those native object
files. Normally the dead functions would be removed by -Wl,-gc-sections but
because CFI jumptables can be reached in the liveness analysis the dead
functions referenced by that jumptable are now live.

Here's a simplified example where just having a dead function in a ThinLTO
build address-take a dead function in a native object file will cause the
native object's dead function to be retained:
$ cat bitcode.c 
#include <stdio.h>

void native_dead(void *);
void* bitcode_dead(void) { return &native_dead; }

// Has the same type signature as native_dead
void addr_taken(void *ptr) { }

int main() {
  void *fptr = &addr_taken;
  ((void(*)(void*))fptr)(NULL);
}

$ cat native.c 
void native_dead() { }

$ clang -c -o native.o native.c
$ clang -flto=thin -fvisibility=hidden -fsanitize=cfi-icall -c -o bitcode.o
bitcode.c
$ clang -flto=thin -fvisibility=hidden -fsanitize=cfi-icall -fuse-ld=lld
-Wl,-gc-sections -o exe.icall bitcode.o native.o
$ nm exe.icall | grep dead
00000000002010e0 T native_dead
0000000000201178 t native_dead.cfi_jt

$ clang -flto=thin -fvisibility=hidden -c -o bitcode.o bitcode.c
$ clang -flto=thin -fvisibility=hidden -fuse-ld=lld -Wl,-gc-sections -o
exe.no-icall bitcode.o native.o
$ nm exe.no-icall | grep dead
$

This occurs because even though bitcode_dead is stripped, native_dead is not
removed from CfiFunctionDecls and a CFI jumptable entry is created for it. The
nacl_helper example is more complicated because there can be multiple
references from bitcode objects to native objects that reference bitcode
objects and back that cause multiple native symbols to be retained.

I spoke with Peter and the idea to fix this is to 1. change the ThinLTO summary
information to mark CfiFunctionDecls/CfiFunctionDefs with the function the
reference was created from, 2. change lld to perform a global liveness analysis
before LTO runs using ThinLTO summary information and looking at native objects
and mark dead objects non-prevailing (right now the analysis is local to just
the LTO bitcode objects), and 3. ignore CfiFunctionDecl/CfiFunctionDefs that
come from functions that will be ThinLTO dead stripped (e.g. non-prevailing.)
Implementing #1 and #3 alone should fix the example above, with #2 required to
handle bitcode->native->bitcode->native reference chains.</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>