Xcode14 Linker assert: ld: Assertion failed: (dylib != NULL), function classicOrdinalForProxy, file LinkEditClassic.hpp, line 495
Originator: | lewurm | ||
Number: | rdar://FB11544896 | Date Originated: | 09/19/2022 |
Status: | Closed | Resolved: | yes |
Product: | Xcode | Product Version: | Xcode 14.0 Build version 14A309 |
Classification: | Reproducible: | yes |
Please see https://gist.github.com/lewurm/48deb2ce67d6c93cff66965d6d770302 Copy of the README.md here: Reproducer for triggering the following assert with Xcode14. ```sh $ xcodebuild -version Xcode 14.0 Build version 14A309 $ make hello_with_objc_selector_stubs ld -o hello_with_objc_selector_stubs -syslibroot /Applications/Xcode14.1-beta1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -lSystem -arch arm64 -platform_version macos 12.0.0 13.0 -U ___darwin_check_fd_set_overflow -ldl -lpthread -framework Foundation -lz /Applications/Xcode14-beta5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/14.0.0/lib/darwin/libclang_rt.osx.a libdarwin_withstubs.a helloworld.o liblibchelper.a libnet.a libnio.a libjava.a libfdlibm.a libzip.a libjvm.a 0 0x104e641a0 __assert_rtn + 140 1 0x104e6d2ec ld::tool::SymbolTableAtom<arm64>::classicOrdinalForProxy(ld::Atom const*) (.cold.2) + 0 2 0x104d75598 ld::tool::LocalRelocationsAtom<arm64_32>::~LocalRelocationsAtom() + 0 3 0x104d74ab8 ld::tool::SymbolTableAtom<arm64>::addImport(ld::Atom const*, ld::tool::StringPoolAtom*) + 204 4 0x104d74150 ld::tool::SymbolTableAtom<arm64>::encode() + 420 5 0x104d60c18 ___ZN2ld4tool10OutputFile20buildLINKEDITContentERNS_8InternalE_block_invoke_3 + 36 6 0x1825325f0 _dispatch_call_block_and_release + 32 7 0x1825341b4 _dispatch_client_callout + 20 8 0x182545b14 _dispatch_root_queue_drain + 952 9 0x182546104 _dispatch_worker_thread2 + 164 10 0x1826f4324 _pthread_wqthread + 228 A linker snapshot was created at: /tmp/hello_with_objc_selector_stubs-2022-09-19-164512.ld-snapshot ld: Assertion failed: (dylib != NULL), function classicOrdinalForProxy, file LinkEditClassic.hpp, line 495. make: *** [hello_with_objc_selector_stubs] Error 1 ``` I noticed that adding `-undefined dynamic_lookup` helps to avoid the assert: ```sh $ LDFLAGS='-undefined dynamic_lookup' make hello_with_objc_selector_stubs ld -o hello_with_objc_selector_stubs -undefined dynamic_lookup -syslibroot /Applications/Xcode14.1-beta1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -lSystem -arch arm64 -platform_version macos 12.0.0 13.0 -U ___darwin_check_fd_set_overflow -ldl -lpthread -framework Foundation -lz /Applications/Xcode14-beta5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/14.0.0/lib/darwin/libclang_rt.osx.a libdarwin_withstubs.a helloworld.o liblibchelper.a libnet.a libnio.a libjava.a libfdlibm.a libzip.a libjvm.a ld: warning: -undefined dynamic_lookup may not work with chained fixups ``` However, trying to execute the final binary it fails with: ```sh $ ./hello_with_objc_selector_stubs dyld[72323]: symbol not found in flat namespace (_objc_msgSend$UTF8String) zsh: abort ./hello_with_objc_selector_stubs ``` Which triggered a memory from a [WWDC22 talk](https://developer.apple.com/videos/play/wwdc2022/110363/) (section `Message send`). The origin is this static library: ```sh $ nm libdarwin_withstubs.a libdarwin_withstubs.a(foundation.o): 00000000000000c8 s _OBJC_CLASSLIST_REFERENCES_$_ 00000000000000d0 s _OBJC_CLASSLIST_REFERENCES_$_.3 U _OBJC_CLASS_$_NSDictionary U _OBJC_CLASS_$_NSProcessInfo U ___CFConstantStringClassReference U _objc_msgSend$UTF8String U _objc_msgSend$dictionaryWithContentsOfFile: U _objc_msgSend$objectForKey: U _objc_msgSend$operatingSystemVersion U _objc_msgSend$processInfo 0000000000000000 T _operatingSystemVersion U _strdup [...] ``` So I compiled `foundation.o` with `-fno-objc-msgsend-selector-stubs`, the result is in `libdarwin_nostubs.a`. ```sh $ make hello_without_objc_selector_stubs ld -o hello_without_objc_selector_stubs -syslibroot /Applications/Xcode14.1-beta1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -lSystem -arch arm64 -platform_version macos 12.0.0 13.0 -U ___darwin_check_fd_set_overflow -ldl -lpthread -framework Foundation -lz /Applications/Xcode14-beta5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/14.0.0/lib/darwin/libclang_rt.osx.a libdarwin_nostubs.a helloworld.o liblibchelper.a libnet.a libnio.a libjava.a libfdlibm.a libzip.a libjvm.a $ ./hello_without_objc_selector_stubs null ``` which works as expected. By the way, sorry I didn't manage to come up with a source-only reproducer. Also, please push a newer revision on GitHub: https://github.com/apple-opensource/ld64/issues/2
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!
Thank you! Adding PURE_INSTRUCTIONS indeed fixed the issue for us.
PS: Please update https://github.com/apple-opensource/ld64 :-)
Engineering has provided the following information regarding this issue:
The problem is with the GraalVM object file helloworld.o,
__TEXT,__text
section should be marked with PURE_INSTRUCTIONS attribute, but it’s not:$ otool -lv helloworld.o
attributes SOME_INSTRUCTIONS EXT_RELOC
You can workaround the problem by compiling an empty source file with clang, e.g., like this:
$ echo "" > dummy.c
$ clang dummy.c -o dummy.o -c -target arm64-apple-macosx12.0
And listing it as the first object file in linker invocation, so this works:
hello_with_objc_selector_stubs: helloworld.o Makefile
$(LD) -o $@ $(LDFLAGS) dummy.o libdarwin_withstubs.a helloworld.o $(LIBS)
The linker assertion is only a side effect of the missing attribute, so on our side we can improve the diagnostics, but you can already proceed with the workaround.