Description
Describe the bug
SPM turned on --gc-sections
in trunk six months ago, swiftlang/swift-package-manager#4135- just before that, a linux user reported this bug with lld 13 but didn't respond when I asked for more info- and others soon reported similar problems with SPM and lld. The issue appears to be a change to how --gc-sections
works in lld that was added last year, which was then flipped on by default and produces linker errors like these when the repro command below is run:
Swift version 5.6.2 (swift-5.6.2-RELEASE)
Target: x86_64-unknown-linux-gnu
/home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/bin/swift-frontend -frontend -c -primary-file swift/test/Interpreter/hello_toplevel.swift -target x86_64-unknown-linux-gnu -disable-objc-interop -new-driver-path /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/bin/swift-driver -resource-dir /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift -module-name hello_toplevel -o /tmp/TemporaryDirectory.s5r53T/hello_toplevel-1.o
/home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/bin/swift-autolink-extract /tmp/TemporaryDirectory.s5r53T/hello_toplevel-1.o -o /tmp/TemporaryDirectory.s5r53T/hello_toplevel-2.autolink
/home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/bin/clang -fuse-ld=lld -pie -Xlinker -rpath -Xlinker /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o /tmp/TemporaryDirectory.s5r53T/hello_toplevel-1.o @/tmp/TemporaryDirectory.s5r53T/hello_toplevel-2.autolink -L /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux -lswiftCore --target=x86_64-unknown-linux-gnu -v -Xlinker --gc-sections -o hello_toplevel
error: link command failed with exit code 1 (use -v to see invocation)
clang version 13.0.0 (https://github.com/apple/llvm-project.git f765bf5b71fd3637a6f6d1d3e6ab95ca91892a0c)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Candidate multilib: .;@m64
Selected multilib: .;@m64
"/home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/bin/ld.lld" -pie -z relro --hash-style=gnu --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o hello_toplevel /lib/x86_64-linux-gnu/Scrt1.o /lib/x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/bin/../lib -L/lib -L/usr/lib -rpath /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o /tmp/TemporaryDirectory.s5r53T/hello_toplevel-1.o -lswift_Concurrency -lswiftCore -lswiftSwiftOnoneSupport -lswiftCore --gc-sections -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /lib/x86_64-linux-gnu/crtn.o
ld.lld: error: undefined hidden symbol: __start_swift5_protocols
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __stop_swift5_protocols
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __start_swift5_protocol_conformances
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __stop_swift5_protocol_conformances
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __start_swift5_type_metadata
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __stop_swift5_type_metadata
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __start_swift5_typeref
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __stop_swift5_typeref
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __start_swift5_reflstr
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __stop_swift5_reflstr
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __start_swift5_fieldmd
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __stop_swift5_fieldmd
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __start_swift5_assocty
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __stop_swift5_assocty
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __start_swift5_replace
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __stop_swift5_replace
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __start_swift5_replac2
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __stop_swift5_replac2
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __start_swift5_builtin
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: undefined hidden symbol: __stop_swift5_builtin
>>> referenced by SwiftRT-ELF.cpp
>>> /home/foo/swift-5.6.2-RELEASE-ubuntu20.04/usr/lib/swift/linux/x86_64/swiftrt.o:(swift_image_constructor())
ld.lld: error: too many errors emitted, stopping now (use -error-limit=0 to see all errors)
clang-13: error: linker command failed with exit code 1 (use -v to see invocation)
Steps To Reproduce
Steps to reproduce the behavior:
./swift-5.6.2-RELEASE-ubuntu20.04/usr/bin/swiftc swift/test/Interpreter/hello_toplevel.swift -use-ld=lld -Xlinker --gc-sections -v
Removing the lld flag makes it default to the system gold linker on linux, which works fine. Make sure you're running lld 13+ as in the output above, as I think it may pick up an earlier lld installed in the system if one is there.
Expected behavior
Linking with lld 13+ and --gc-sections
to work
Environment (please fill out the following information)
- OS: Ubuntu 20.04 x86_64 and Android 12 AArch64
Additional context
Since linux uses gold by default and the Android LTS NDK used lld 12 till a couple weeks ago, it looks like this wasn't affecting too many people, but will if SPM 5.7 turns on dead-stripping by default, so that change is being backed out of SPM temporarily, swiftlang/swift-package-manager#5698, till we can fix it here.
@keith has proposed #60357 to fix this, but it may not be enough. @drodriguez ran that fix and the new lld flag -z nostart-stop-gc
through the compiler validation suite on linux x86_64 and got a couple dozen more test failures.
I tried replicating what he did natively on Android with the July 25 source snapshot, which uses lld 14 from the Termux environment, and got the following compiler validation suite test results:
No changes, ie just the stock test run with lld - 36 test failures
lld with SWIFT_DRIVER_TEST_OPTIONS=" -Xlinker --gc-sections"
- 1113 test failures
lld with SWIFT_DRIVER_TEST_OPTIONS=" -Xlinker --gc-sections"
and the stdlib fix from #60357 - 159 test failures
lld with SWIFT_DRIVER_TEST_OPTIONS=" -Xlinker --gc-sections -Xlinker -z -Xlinker nostart-stop-gc"
- 54 test failures
I also tried applying both the stdlib fix and -z nostart-stop-gc
, but that made no difference in the test results compared to -z nostart-stop-gc
alone.
Comparing that last run to the first stock run, I see 19 additional test failures- 18 TypeDecoder tests and DebugInfo.ASTSection- that all invoke lldb-moduleimport-test
and fail with FileCheck error: '<stdin>' is empty.
, similar to @drodriguez's results (LinkerSections.function_sections-lld that failed in the stock run now passes with -z nostart-stop-gc
applied, as that test was already using --gc-sections
). I will look into those further.
I'm looking for feedback from the Swift compiler devs on what we should do about this: apply one of these fixes or try something different?
@3405691582, let me know if you can reproduce on OpenBSD.