Open Quuxplusone opened 9 years ago
Bugzilla Link | PR23007 |
Status | NEW |
Importance | P normal |
Reported by | Peter Collingbourne (peter@pcc.me.uk) |
Reported on | 2015-03-24 13:41:19 -0700 |
Last modified on | 2021-06-21 11:41:55 -0700 |
Version | trunk |
Hardware | PC All |
CC | dexonsmith@apple.com, hiraditya@msn.com, jsweval@arxan.com, kledzik@apple.com, llvm-bugs@lists.llvm.org, mwoodard@arxan.com, nicolasweber@gmx.de |
Fixed by commit(s) | |
Attachments | |
Blocks | |
Blocked by | |
See also |
Note that reverting those patches only helps in an LLVM built without assertions, otherwise the assertion removed in r209227 fails.
There is something really odd going on here:
$ cat main.ll
target triple = "x86_64-apple-macosx10.10.0"
define i32 @main() {
ret i32 0
}
$ cat foo.ll
target triple = "x86_64-apple-macosx10.10.0"
%0 = type opaque
%struct._objc_method = type { i8*, i8*, i8* }
%struct._protocol_t = type { i8*, i8*, %struct._objc_protocol_list*,
%struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*,
%struct.__method_list_t*, %struct._prop_list_t*, i32, i32, i8** }
%struct._objc_protocol_list = type { i64, [0 x %struct._protocol_t*] }
%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] }
%struct._prop_list_t = type { i32, i32, [0 x %struct._prop_t] }
%struct._prop_t = type { i8*, i8* }
@zed = global %struct._protocol_t { i8* null, i8* null,
%struct._objc_protocol_list* null, %struct.__method_list_t* null,
%struct.__method_list_t* null, %struct.__method_list_t* null,
%struct.__method_list_t* null, %struct._prop_list_t* null, i32 80, i32 0, i8**
null }, section "__DATA,__datacoal_nt,coalesced", align 8
@bar = global %0* bitcast (%struct._protocol_t* @zed to %0*), section "__DATA,
__objc_protorefs, coalesced, no_dead_strip"
@llvm.compiler.used = appending global [1 x i8*] [ i8* bitcast (%0** @bar to
i8*)], section "llvm.metadata"
define zeroext i1 @_Z3fooP8NSObject() {
ret i1 false
}
$ export DYLD_LIBRARY_PATH=/Users/espindola/llvm/build/lib/
$ ./build/bin/llvm-as foo.ll -o foo.o
$ ./build/bin/llvm-as main.ll -o main.o
$ rm -rf libfoo.a
$ ar cru libfoo.a foo.o
$ ./build/bin/clang main.o libfoo.a -o t -Wl,-ObjC
$ ./build/bin/clang main.o foo.o -o t -Wl,-ObjC -Wl,-dead_strip
$ ./build/bin/clang main.o libfoo.a -o t -Wl,-ObjC -Wl,-dead_strip
ld: warning: '__Z3fooP8NSObject' is implemented in bitcode, but it was loaded
too late
Why is the file being in an archive makes a difference? Why it is even fetched
from the archive to begin with?
A guess is that internalize should ignore objc sections
("__DATA,__datacoal_nt,coalesced" in this case), but I really don't know what
ld64 is trying to do in here.
The "is implemented in bitcode, but it was loaded too late" warning is there to shed light on some libLTO/ld64 issues. Early in the link, the linker asks libLTO about all the symbols it will need, and the linker loads as needed to resolve those symbols. But sometimes the resulting codegen'ed mach-o needs some symbols that libLTO never told the linker about. This usually happens with "lib" routines that the backend decided to use (e.g. memcpy) and there was no explicit reference that libLTO could have reported to the linker.
The -Objc linker flag tells the linker to force load all archive members that define ObjC classes or categories. In this reduced case, there are no classes or categories defined (just a protocol), so the linker does not force load libfoo.a(foo.o). Perhaps is should detect protocols too...
This is a perhaps related case that, strangely enough, does not involve ObjC
code. Reverting 209227 and 207979 does not seem to help here. The issue also
seems to be present in "Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM
3.5svn)".
$ cat main.c
int main() {}
$ cat fad.ii
class A {
public:
A();
} a;
int b;
$ clang++ -c -flto fad.ii
$ clang -c -flto main.c
$ rm -f libfad.a
$ ar cru libfad.a fad.o
$ clang -flto -Wl,-ObjC -Wl,-dead_strip main.o libfad.a
ld: warning: '_b' is implemented in bitcode, but it was loaded too late
Undefined symbols for architecture x86_64:
"_a", referenced from:
__GLOBAL__I_a in lto.o
import-atom in libfad.a(fad.o)
"A::A()", referenced from:
__GLOBAL__I_a in lto.o
import-atom in libfad.a(fad.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I am reasonably sure that this is a bug in the linker, ld64. I have a (quick and dirty) patch for ld64 that fixes my minimal test cases, and appears to let me link Chromium.
This might not be the correct forum to discuss changes to ld64, though. Nick, is there a more appropriate forum?
Unfortunately my patch was not sufficient. I discovered that the ld64 code for identifying which object files belong to Objective C classes does not support LTO objects, and this seems rather more complicated to fix.
For now I've worked around the issue by passing -all_load when using LTO, and I've filed http://openradar.appspot.com/radar?id=5888585047736320 with Apple.
Does not repro anymore. I came to this bug because i'm getting similar error
but the examples here do not repro the error message anymore.
ld: warning: '_create_id' is implemented in bitcode, but it was loaded too late
ld: warning: '_trace_begin' is implemented in bitcode, but it was loaded too
late
ld: warning: '_trace_end' is implemented in bitcode, but it was loaded too late
ld: warning: '___cyg_profile_func_enter' is implemented in bitcode, but it was
loaded too late
ld: warning: '___cyg_profile_func_exit' is implemented in bitcode, but it was
loaded too late
ld: warning: '___cyg_profile_func_enter_bare' is implemented in bitcode, but it
was loaded too late
Undefined symbols for architecture x86_64:
...
...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
------------------------------------------------------------
Stack trace:
------------------------------------------------------------
ld: warning: '_create_id' is implemented in bitcode, but it was loaded too late
ld: warning: '_trace_begin' is implemented in bitcode, but it was loaded too
late
ld: warning: '_trace_end' is implemented in bitcode, but it was loaded too late
ld: warning: '___cyg_profile_func_enter' is implemented in bitcode, but it was
loaded too late
ld: warning: '___cyg_profile_func_exit' is implemented in bitcode, but it was
loaded too late
ld: warning: '___cyg_profile_func_enter_bare' is implemented in bitcode, but it
was loaded too late
0 0x10fe381cc __assert_rtn + 123
1 0x10fe40f80
ld::tool::HeaderAndLoadCommandsAtom<x86_64>::sectionFlags(ld::Internal::FinalSection*)
const (.cold.4) + 0
2 0x10fdced9a
ld::tool::HeaderAndLoadCommandsAtom<x86_64>::sectionFlags(ld::Internal::FinalSection*)
const + 744
3 0x10fdce31b
ld::tool::HeaderAndLoadCommandsAtom<x86_64>::copySegmentLoadCommands(unsigned
char*, unsigned char*) const + 1069
4 0x10fdccf7f
ld::tool::HeaderAndLoadCommandsAtom<x86_64>::copyRawContent(unsigned char*)
const + 295
5 0x10fd838f3 ld::tool::OutputFile::writeAtoms(ld::Internal&, unsigned char*)
+ 321
6 0x10fd7a88d ld::tool::OutputFile::writeOutputFile(ld::Internal&) + 821
7 0x10fd71e69 ld::tool::OutputFile::write(ld::Internal&) + 189
8 0x10fcf06e3 main + 774
9 0x7fff20432f5d start + 1
A linker snapshot was created at:
/tmp/Library/Foo#iphonesimulator-x86_64-214806.ld-snapshot
ld: Assertion failed: (0 && "typeTempLTO should not make it to final linked
image"), function sectionFlags, file
/Library/Caches/com.apple.xbs/Sources/ld64/ld64-
650.9/src/ld/HeaderAndLoadCommands.hpp, line 866.
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The linker invocation does have both
-dead_strip and -ObjC though.
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
-demangle -application_extension -lto_library
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libLTO.dylib
-dynamic -arch x86_64 -dead_strip -ios_simulator_version_min 10.0.0 -syslibroot
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk
-e _NSExtensionMain -ObjC ...
So here is the repro.
$ cat test.c
int foo() { return 0; }
$ cat main.c
int foo();
int main() {
foo();
return 0;
}
$ cat trace.cpp
#include <atomic>
#include <stdio.h>
extern "C" {
typedef uint64_t counter_type;
std::atomic<counter_type> id;
__attribute__((no_instrument_function)) counter_type create_id()
{
return id++;
}
__attribute__((no_instrument_function)) void __cyg_profile_func_enter_bare(void
*func, void *caller)
{
counter_type c = create_id();
fprintf(stdout, "e %p %p %llu\n", func, caller, c);
}
}
$ cat crash.sh
clang -c main.c
clang -flto=thin -finstrument-function-entry-bare test.c -c
ar cru libtest.a test.o
clang++ -flto=thin trace.cpp -c
ar cru libtest.a trace.o
clang++ -flto=thin main.o libtest.a
ld: warning: '_create_id' is implemented in bitcode, but it was loaded too late
ld: warning: '___cyg_profile_func_enter_bare' is implemented in bitcode, but it
was loaded too late
ld: warning: '_id' is implemented in bitcode, but it was loaded too late
0 0x10b8cd1cc __assert_rtn + 123
1 0x10b8d5f80
ld::tool::HeaderAndLoadCommandsAtom<x86_64>::sectionFlags(ld::Internal::FinalSection*)
const (.cold.4) + 0
2 0x10b863d9a
ld::tool::HeaderAndLoadCommandsAtom<x86_64>::sectionFlags(ld::Internal::FinalSection*)
const + 744
3 0x10b86331b
ld::tool::HeaderAndLoadCommandsAtom<x86_64>::copySegmentLoadCommands(unsigned
char*, unsigned char*) const + 1069
4 0x10b861f7f
ld::tool::HeaderAndLoadCommandsAtom<x86_64>::copyRawContent(unsigned char*)
const + 295
5 0x10b8188f3 ld::tool::OutputFile::writeAtoms(ld::Internal&, unsigned char*)
+ 321
6 0x10b80f88d ld::tool::OutputFile::writeOutputFile(ld::Internal&) + 821
7 0x10b806e69 ld::tool::OutputFile::write(ld::Internal&) + 189
8 0x10b7856e3 main + 774
9 0x7fff20432f5d start + 1
A linker snapshot was created at:
/tmp/a.out-2021-05-20-224729.ld-snapshot
ld: Assertion failed: (0 && "typeTempLTO should not make it to final linked
image"), function sectionFlags, file
/Library/Caches/com.apple.xbs/Sources/ld64/ld64-
650.9/src/ld/HeaderAndLoadCommands.hpp, line 866.
clang: error: linker command failed with exit code 1 (use -v to see invocation)
If the linker has a warning:
'_foo' is implemented in bitcode, but it was loaded too late
Then either you need to:
1) not implement _foo in bitcode (use mach-o)
2) don't put the .o file with _foo in a static library (they are loaded late)
2) add '-u _foo' to the link line, which will force _foo to be loaded early