[llvm-bugs] [Bug 37474] New: -fsanitize=cfi-icall inhibits dead code stripping for mixed ThinLTO/native builds
via llvm-bugs
llvm-bugs at lists.llvm.org
Tue May 15 12:56:02 PDT 2018
https://bugs.llvm.org/show_bug.cgi?id=37474
Bug ID: 37474
Summary: -fsanitize=cfi-icall inhibits dead code stripping for
mixed ThinLTO/native builds
Product: libraries
Version: trunk
Hardware: PC
OS: Linux
Status: NEW
Severity: enhancement
Priority: P
Component: Interprocedural Optimizations
Assignee: vlad at tsyrklevich.net
Reporter: vlad at tsyrklevich.net
CC: kcc at google.com, llvm-bugs at lists.llvm.org,
peter at pcc.me.uk
This issue is causing the size regression noted in
https://bugs.chromium.org/p/chromium/issues/detail?id=841916 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.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20180515/e31951af/attachment.html>
More information about the llvm-bugs
mailing list