Skip to content
  • Bill Wendling's avatar
    The internalize pass can be dangerous for LTO. · 4f60125d
    Bill Wendling authored
    Consider the following program:
    
    $ cat main.c
    void foo(void) { }
    
    int main(int argc, char *argv[]) {
        foo();
        return 0;
    }
    $ cat bundle.c 
    extern void foo(void);
    
    void bar(void) {
         foo();
    }
    $ clang -o main main.c
    $ clang -o bundle.so bundle.c -bundle -bundle_loader ./main
    $ nm -m bundle.so
    0000000000000f40 (__TEXT,__text) external _bar
                     (undefined) external _foo (from executable)
                     (undefined) external dyld_stub_binder (from libSystem)
    $ clang -o main main.c -O4
    $ clang -o bundle.so bundle.c -bundle -bundle_loader ./main
    Undefined symbols for architecture x86_64:
      "_foo", referenced from:
          _bar in bundle-elQN6d.o
    ld: symbol(s) not found for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    
    The linker was told that the 'foo' in 'main' was 'internal' and had no uses, so
    it was dead stripped.
    
    Another situation is something like:
    
    define void @foo() {
      ret void
    }
    
    define void @bar() {
      call asm volatile "call _foo" ...
      ret void
    }
    
    The only use of 'foo' is inside of an inline ASM call. Since we don't look
    inside those for uses of functions, we don't specify this as a "use."
    
    Get around this by not invoking the 'internalize' pass by default. This is an
    admitted hack for LTO correctness.
    <rdar://problem/11185386>
    
    llvm-svn: 154124
    4f60125d
Loading