From e00764e365ff697bfb82b069bac2709c4c348023 Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Thu, 15 Feb 2024 15:36:24 -0800 Subject: [PATCH] Keep start and stop symbols linked through clang Changes in https://reviews.llvm.org/D96914 taught LLD to remove `__start_##name` and `__stop_##name` symbol names. The Swift runtime uses these specially named symbols to unpack the runtime type metadata on Linux and WebAssembly systems, resulting in broken binaries when linked with `lld`. This change tells the Swift-paired Clang to force the `-z nostart-stop-gc` flag when compiling for Linux-y systems, including Musl, WASM, and Android. Swift and the clang-linker have to work with other existing toolchains, so we can't simply flip the cmake option in the LLVM build system to keep these symbols and get a working binary. --- clang/lib/Driver/ToolChain.cpp | 2 +- clang/lib/Driver/ToolChains/Gnu.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index bf40ff0903cac..e40b8471cb0aa 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -836,7 +836,7 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const { if (llvm::sys::fs::can_execute(UseLinker)) return std::string(UseLinker); } else { - llvm::SmallString<8> LinkerName; + llvm::SmallString<8> LinkerName = {}; if (Triple.isOSDarwin()) LinkerName.append("ld64."); else diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 40038dce47d84..08a78282af0b0 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -677,8 +677,17 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, } Args.AddAllArgs(CmdArgs, options::OPT_T); + bool useLLD = false; + const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath(&useLLD)); + if (useLLD) { + /// Workaround for https://reviews.llvm.org/D96914 breaking Swift. + /// Newer LLD versions change symbols, resulting in incorrect locations + /// for the type metadata tables. Forcing `-z nostart-stop-gc` on LLD so + /// that it does not munge the symbols. + CmdArgs.push_back("-z"); + CmdArgs.push_back("nostart-stop-gc"); + } - const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs, Output));