ro updated this revision to Diff 554711. ro retitled this revision from "[WIP][clang][Driver] Support GNU ld on Solaris" to "[Driver] Support GNU ld on Solaris". ro added a comment. Herald added subscribers: llvm-commits, Sanitizers, Enna1, ormris. Herald added a reviewer: sscalpone. Herald added a reviewer: awarzynski. Herald added projects: Sanitizers, LLVM, Flang, All.
This is a major revison of the original WIP patch that should be (close to) ready. Major differences are: - Linker selection is dynamic now: one can switch between Solaris ld and GNU ld at runtime, with the default selectable with `-DCLANG_DEFAULT_LINKER`. - Testcases have been adjusted to test both variants in case there are differences. - The `compiler-rt/cmake/config-ix.cmake` and `llvm/cmake/modules/AddLLVM.cmake` changes to restrict the tests to Solaris ld are necessary because GNU accepts unknown `-z` options, but warns every time they are used, creating a lot of noise. Since there seems to be no way to check for those warnings in `llvm_check_compiler_linker_flag` or `llvm_check_compiler_linker_flag`, I restrict the cmake tests to Solaris ld in the first place. - The changes to `clang/test/Driver/hip-link-bundle-archive.hip` and `flang/test/Driver/linker-flags.f90` are required to handle the `-DCLANG_DEFAULT_LINKER=gld` case: when this is passed to `cmake`, the `WebAssembly.cpp` `getLinkerPath` returns `/usr/bin/gld` instead of the expected `link`. - `compiler-rt/test/asan/TestCases/global-location-nodebug.cpp` needs to enforce the Solaris ld, otherwise the test would `XPASS` with GNU ld which has the `-S` semantics expected by the test. Tested on `amd64-pc-solaris2.11` and `sparcv9-sun-solaris2.11` with both `-DCLANG_DEFAULT_LINKER=gld` and the default, and `x86_64-pc-linux-gnu`. No regressions in either case. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D85309/new/ https://reviews.llvm.org/D85309 Files: clang/lib/Driver/ToolChains/CommonArgs.cpp clang/lib/Driver/ToolChains/CommonArgs.h clang/lib/Driver/ToolChains/Solaris.cpp clang/lib/Driver/ToolChains/Solaris.h clang/test/Driver/hip-link-bundle-archive.hip clang/test/Driver/solaris-ld-sanitizer.c clang/test/Driver/solaris-ld.c compiler-rt/cmake/config-ix.cmake compiler-rt/test/asan/TestCases/global-location-nodebug.cpp flang/test/Driver/linker-flags.f90 llvm/cmake/modules/AddLLVM.cmake
Index: llvm/cmake/modules/AddLLVM.cmake =================================================================== --- llvm/cmake/modules/AddLLVM.cmake +++ llvm/cmake/modules/AddLLVM.cmake @@ -282,9 +282,9 @@ # ld64's implementation of -dead_strip breaks tools that use plugins. set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-dead_strip") - elseif(${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + elseif(${CMAKE_SYSTEM_NAME} MATCHES "SunOS" AND LLVM_LINKER_IS_SOLARISLD) # Support for ld -z discard-unused=sections was only added in - # Solaris 11.4. + # Solaris 11.4. GNU ld ignores it, but warns every time. include(LLVMCheckLinkerFlag) llvm_check_linker_flag(CXX "-Wl,-z,discard-unused=sections" LINKER_SUPPORTS_Z_DISCARD_UNUSED) if (LINKER_SUPPORTS_Z_DISCARD_UNUSED) @@ -1288,7 +1288,10 @@ # the size of the exported symbol table, but on other platforms we can do # it without any trouble. set_target_properties(${target} PROPERTIES ENABLE_EXPORTS 1) - if (APPLE) + # CMake doesn't set CMAKE_EXE_EXPORTS_${lang}_FLAG on Solaris, so + # ENABLE_EXPORTS has no effect. While Solaris ld defaults to -rdynamic + # behaviour, GNU ld needs it. + if (APPLE OR ${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " -rdynamic") endif() Index: flang/test/Driver/linker-flags.f90 =================================================================== --- flang/test/Driver/linker-flags.f90 +++ flang/test/Driver/linker-flags.f90 @@ -10,7 +10,7 @@ ! 'oldnames' on Windows, but they are not needed when compiling ! Fortran code and they might bring in additional dependencies. ! Make sure they're not added. -! RUN: %flang -### -target aarch64-windows-msvc %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC --implicit-check-not libcmt --implicit-check-not oldnames +! RUN: %flang -### -target aarch64-windows-msvc -fuse-ld= %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC --implicit-check-not libcmt --implicit-check-not oldnames ! Compiler invocation to generate the object file ! CHECK-LABEL: {{.*}} "-emit-obj" Index: compiler-rt/test/asan/TestCases/global-location-nodebug.cpp =================================================================== --- compiler-rt/test/asan/TestCases/global-location-nodebug.cpp +++ compiler-rt/test/asan/TestCases/global-location-nodebug.cpp @@ -2,13 +2,14 @@ /// allow this test to also run on Windows (which can't be done for the /// debuginfo variant). -// RUN: %clangxx_asan -O2 %S/global-location.cpp -o %t %if target={{.*-windows-msvc.*}} %{ -Wl,/DEBUG:NONE %} %else %{ -Wl,-S %} +// RUN: %clangxx_asan -O2 %S/global-location.cpp -o %t %if target={{.*-windows-msvc.*}} %{ -Wl,/DEBUG:NONE %} %else %{ -Wl,-S %} %if target={{.*-solaris.*}} %{ -fuse-ld= %} // RUN: not %run %t g 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=GLOB-NO-G // RUN: not %run %t c 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CLASS_STATIC-NO-G // RUN: not %run %t f 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=FUNC_STATIC-NO-G // RUN: not %run %t l 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=LITERAL-NO-G -/// Solaris ld -S has different semantics. +/// Solaris ld -S has different semantics, so enforce -fuse-ld= for +/// configurations that default to GNU ld. // XFAIL: target={{.*solaris.*}} // CHECK: AddressSanitizer: global-buffer-overflow Index: compiler-rt/cmake/config-ix.cmake =================================================================== --- compiler-rt/cmake/config-ix.cmake +++ compiler-rt/cmake/config-ix.cmake @@ -1,4 +1,5 @@ include(CMakePushCheckState) +include(AddLLVM) include(LLVMCheckCompilerLinkerFlag) include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) @@ -196,7 +197,7 @@ llvm_check_compiler_linker_flag(C "-Wl,-z,text" COMPILER_RT_HAS_Z_TEXT) llvm_check_compiler_linker_flag(C "-fuse-ld=lld" COMPILER_RT_HAS_FUSE_LD_LLD_FLAG) -if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS") +if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS" AND LLVM_LINKER_IS_SOLARISLD) set(VERS_COMPAT_OPTION "-Wl,-z,gnu-version-script-compat") llvm_check_compiler_linker_flag(C "${VERS_COMPAT_OPTION}" COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT) endif() Index: clang/test/Driver/solaris-ld.c =================================================================== --- clang/test/Driver/solaris-ld.c +++ clang/test/Driver/solaris-ld.c @@ -2,10 +2,14 @@ // sysroot to make these tests independent of the host system. // Check sparc-sun-solaris2.11, 32bit -// RUN: %clang -### %s 2>&1 --target=sparc-sun-solaris2.11 \ +// RUN: %clang -### %s --target=sparc-sun-solaris2.11 -fuse-ld= \ // RUN: --gcc-toolchain="" \ -// RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ -// RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32 %s +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefixes=CHECK-LD-SPARC32,CHECK-LD %s +// RUN: %clang -### %s --target=sparc-sun-solaris2.11 -fuse-ld=gld \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefixes=CHECK-LD-SPARC32,CHECK-GLD %s // CHECK-LD-SPARC32-NOT: warning: // CHECK-LD-SPARC32: "-cc1" "-triple" "sparc-sun-solaris2.11" // CHECK-LD-SPARC32-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -16,7 +20,8 @@ // CHECK-LD-SPARC32-SAME: "-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2" // CHECK-LD-SPARC32-SAME: "-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../.." // CHECK-LD-SPARC32-SAME: "-L[[SYSROOT]]/usr/lib" -// CHECK-LD-SPARC32-SAME: "-z" "ignore" "-latomic" "-z" "record" +// CHECK-LD: "-z" "ignore" "-latomic" "-z" "record" +// CHECK-GLD: "--as-needed" "-latomic" "--no-as-needed" // CHECK-LD-SPARC32-SAME: "-lgcc_s" // CHECK-LD-SPARC32-SAME: "-lc" // CHECK-LD-SPARC32-SAME: "-lgcc" @@ -107,31 +112,53 @@ // CHECK-SPARC32-SHARED-NOT: "-lm" // Check the right ld flags are present with -pie. -// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie \ +// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie -fuse-ld= \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-PIE-LD %s +// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie -fuse-ld=gld \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-PIE %s -// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -nopie \ +// RUN: | FileCheck --check-prefix=CHECK-PIE-GLD %s +// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -nopie -fuse-ld= \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-NOPIE %s +// RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s +// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -nopie -fuse-ld=gld \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s // Check that -shared/-r/-static disable PIE. -// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared -pie \ +// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared -pie -fuse-ld= \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-NOPIE %s -// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -r -pie \ +// RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s +// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared -pie -fuse-ld=gld \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s +// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -r -pie -fuse-ld= \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s +// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -r -pie -fuse-ld=gld \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-NOPIE %s -// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -static -pie \ +// RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s +// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -static -pie -fuse-ld= \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-NOPIE %s +// RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s +// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -static -pie -fuse-ld=gld \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s -// CHECK-PIE: "-z" "type=pie" -// CHECK-NOPIE-NOT: "-z" "type=pie" +// CHECK-PIE-LD: "-z" "type=pie" +// CHECK-PIE-GLD: "-pie" +// CHECK-NOPIE-LD-NOT: "-z" "type=pie" +// CHECK-NOPIE-GLD-NOT: "-pie" // -r suppresses default -l and crt*.o, values-*.o like -nostdlib. // RUN: %clang -### %s --target=sparc-sun-solaris2.11 -r 2>&1 \ Index: clang/test/Driver/solaris-ld-sanitizer.c =================================================================== --- clang/test/Driver/solaris-ld-sanitizer.c +++ clang/test/Driver/solaris-ld-sanitizer.c @@ -3,55 +3,55 @@ /// independent of the host system. /// Check sparc-sun-solaris2.11, 32bit -// RUN: %clang --target=sparc-sun-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree \ -// RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32 %s -// CHECK-LD-SPARC32-NOT: "-z" "relax=transtls" +// RUN: %clang --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ +// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check sparc-sun-solaris2.11, 32bit -// RUN: %clang -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree \ -// RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32 %s -// CHECK-LD-SPARC32-NOT: "-z" "relax=transtls" +// RUN: %clang -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ +// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check sparc-sun-solaris2.11, 64bit -// RUN: %clang -m64 --target=sparc-sun-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree \ -// RUN: | FileCheck --check-prefix=CHECK-LD-SPARC64 %s -// CHECK-LD-SPARC64-NOT: "-z" "relax=transtls" +// RUN: %clang -m64 --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ +// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check sparc-sun-solaris2.11, 64bit -// RUN: %clang -m64 -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree \ -// RUN: | FileCheck --check-prefix=CHECK-LD-SPARC64 %s -// CHECK-LD-SPARC64-NOT: "-z" "relax=transtls" +// RUN: %clang -m64 -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ +// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-LD %s + +/// Check i386-pc-solaris2.11, 32bit +// RUN: %clang --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ +// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check i386-pc-solaris2.11, 32bit -// RUN: %clang --target=i386-pc-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \ -// RUN: | FileCheck --check-prefix=CHECK-LD-X32 %s -// CHECK-LD-X32-NOT: "-z" "relax=transtls" +// RUN: %clang -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ +// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-LD %s -/// Check i386-pc-solaris2.11, 32bit -// RUN: %clang -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \ -// RUN: | FileCheck --check-prefix=CHECK-LD-X32 %s -// CHECK-LD-X32-NOT: "-z" "relax=transtls" +/// Check i386-pc-solaris2.11, 64bit +// RUN: %clang -m64 --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ +// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-LD %s + +// CHECK-LD-NOT: "-z" "relax=transtls" /// Check i386-pc-solaris2.11, 64bit -// RUN: %clang -m64 --target=i386-pc-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \ -// RUN: | FileCheck --check-prefix=CHECK-LD-X64 %s -// CHECK-LD-X64-NOT: "-z" "relax=transtls" +// RUN: %clang -m64 -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ +// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-LD-X64-UBSAN %s +// RUN: %clang -m64 -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld=gld \ +// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-GLD-X64-UBSAN %s -/// Check i386-pc-solaris2.11, 64bit -// RUN: %clang -m64 -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \ -// RUN: | FileCheck --check-prefix=CHECK-LD-X64-UBSAN %s // CHECK-LD-X64-UBSAN: "-z" "relax=transtls" +// CHECK-GLD-X64-UBSAN-NOT: "-z" "relax=transtls" /// General tests that the ld -z now workaround is only applied on -/// Solaris/i386 with shared libclang_rt.asan.. Note that we use sysroot to +/// Solaris/i386 with shared libclang_rt.asan. Note that we use sysroot to /// make these tests independent of the host system. /// Check i386-pc-solaris2.11, 32bit, shared libclang_rt.asan Index: clang/test/Driver/hip-link-bundle-archive.hip =================================================================== --- clang/test/Driver/hip-link-bundle-archive.hip +++ clang/test/Driver/hip-link-bundle-archive.hip @@ -56,17 +56,17 @@ // RUN: llvm-ar cr %t/hipBundled2.lib %t/dummy.bc // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \ -// RUN: --target=x86_64-pc-windows-msvc \ +// RUN: --target=x86_64-pc-windows-msvc -fuse-ld= \ // RUN: -nogpuinc -nogpulib %s -fgpu-rdc -L%t -lhipBundled2 \ // RUN: 2>&1 | FileCheck -check-prefix=MSVC %s // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \ -// RUN: --target=x86_64-pc-windows-msvc \ +// RUN: --target=x86_64-pc-windows-msvc -fuse-ld= \ // RUN: -nogpuinc -nogpulib %s -fgpu-rdc -L%t -l:hipBundled2.lib \ // RUN: 2>&1 | FileCheck -check-prefix=MSVC %s // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \ -// RUN: --target=x86_64-pc-windows-msvc \ +// RUN: --target=x86_64-pc-windows-msvc -fuse-ld= \ // RUN: -nogpuinc -nogpulib %s -fgpu-rdc %t/hipBundled2.lib \ // RUN: 2>&1 | FileCheck -check-prefix=MSVC %s Index: clang/lib/Driver/ToolChains/Solaris.h =================================================================== --- clang/lib/Driver/ToolChains/Solaris.h +++ clang/lib/Driver/ToolChains/Solaris.h @@ -38,6 +38,7 @@ bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } + std::string getLinkerPath(const llvm::opt::ArgList &Args) const; void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -65,10 +66,7 @@ SanitizerMask getSupportedSanitizers() const override; unsigned GetDefaultDwarfVersion() const override { return 2; } - const char *getDefaultLinker() const override { - // clang currently uses Solaris ld-only options. - return "/usr/bin/ld"; - } + const char *getDefaultLinker() const override; protected: Tool *buildAssembler() const override; Index: clang/lib/Driver/ToolChains/Solaris.cpp =================================================================== --- clang/lib/Driver/ToolChains/Solaris.cpp +++ clang/lib/Driver/ToolChains/Solaris.cpp @@ -16,6 +16,7 @@ #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/ToolChain.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -59,6 +60,32 @@ return A->getOption().matches(options::OPT_pie); } +// FIXME: Need to handle CLANG_DEFAULT_LINKER here? +std::string solaris::Linker::getLinkerPath(const ArgList &Args) const { + const ToolChain &ToolChain = getToolChain(); + if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) { + StringRef UseLinker = A->getValue(); + if (!UseLinker.empty()) { + if (llvm::sys::path::is_absolute(UseLinker) && + llvm::sys::fs::can_execute(UseLinker)) + return std::string(UseLinker); + + // Accept 'bfd' and 'gld' as aliases for the GNU linker. + if (UseLinker == "bfd" || UseLinker == "gld") + // FIXME: Could also use /usr/bin/gld here. + return std::string("/usr/gnu/bin/ld"); + + // Accept 'ld' as alias for the default linker + if (UseLinker != "ld") + ToolChain.getDriver().Diag(diag::err_drv_invalid_linker_name) + << A->getAsString(Args); + } + } + + // getDefaultLinker() always returns an absolute path. + return ToolChain.getDefaultLinker(); +} + void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -66,9 +93,11 @@ const char *LinkingOutput) const { const bool IsPIE = getPIE(Args, getToolChain()); ArgStringList CmdArgs; + bool LinkerIsGnuLd = isLinkerGnuLd(getToolChain(), Args); - // Demangle C++ names in errors - CmdArgs.push_back("-C"); + // Demangle C++ names in errors. GNU ld already defaults to --demangle. + if (!LinkerIsGnuLd) + CmdArgs.push_back("-C"); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) { CmdArgs.push_back("-e"); @@ -76,8 +105,12 @@ } if (IsPIE) { - CmdArgs.push_back("-z"); - CmdArgs.push_back("type=pie"); + if (LinkerIsGnuLd) { + CmdArgs.push_back("-pie"); + } else { + CmdArgs.push_back("-z"); + CmdArgs.push_back("type=pie"); + } } if (Args.hasArg(options::OPT_static)) { @@ -95,6 +128,42 @@ Args.ClaimAllArgs(options::OPT_pthreads); } + if (LinkerIsGnuLd) { + // Set the correct linker emulation for 32- and 64-bit Solaris. + const toolchains::Solaris &ToolChain = + static_cast<const toolchains::Solaris &>(getToolChain()); + const llvm::Triple::ArchType Arch = ToolChain.getArch(); + + switch (Arch) { + case llvm::Triple::x86: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf_i386_sol2"); + break; + case llvm::Triple::x86_64: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf_x86_64_sol2"); + break; + case llvm::Triple::sparc: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf32_sparc_sol2"); + break; + case llvm::Triple::sparcv9: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf64_sparc_sol2"); + break; + default: + break; + } + + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("-export-dynamic"); + + CmdArgs.push_back("--eh-frame-hdr"); + } else { + // -rdynamic is a no-op with Solaris ld. Claim argument to avoid warning. + Args.ClaimAllArgs(options::OPT_rdynamic); + } + if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); @@ -183,7 +252,8 @@ // in Illumos. if (getToolChain().getTriple().getArch() == llvm::Triple::x86_64 && (SA.needsAsanRt() || SA.needsStatsRt() || - (SA.needsUbsanRt() && !SA.requiresMinimalRuntime()))) { + (SA.needsUbsanRt() && !SA.requiresMinimalRuntime())) && + !LinkerIsGnuLd) { CmdArgs.push_back("-z"); CmdArgs.push_back("relax=transtls"); } @@ -210,7 +280,7 @@ getToolChain().addProfileRTLibs(Args, CmdArgs); - const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + const char *Exec = Args.MakeArgString(getLinkerPath(Args)); C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), Exec, CmdArgs, Inputs, Output)); } @@ -271,6 +341,13 @@ return Res; } +const char *Solaris::getDefaultLinker() const { + // FIXME: Only handle Solaris ld and GNU ld here. + return llvm::StringSwitch<const char *>(CLANG_DEFAULT_LINKER) + .Cases("bfd", "gld", "/usr/gnu/bin/ld") + .Default("/usr/bin/ld"); +} + Tool *Solaris::buildAssembler() const { return new tools::solaris::Assembler(*this); } Index: clang/lib/Driver/ToolChains/CommonArgs.h =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.h +++ clang/lib/Driver/ToolChains/CommonArgs.h @@ -30,6 +30,8 @@ const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const JobAction &JA); +bool isLinkerGnuLd(const ToolChain &TC, const llvm::opt::ArgList &Args); + void addLinkerCompressDebugSectionsOption(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs); Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -302,6 +302,14 @@ } } +bool tools::isLinkerGnuLd(const ToolChain &TC, const ArgList &Args) { + // Only used if targetting Solaris. + const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ); + StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER; + // FIXME: What about -fuse-ld=<path>? + return UseLinker == "bfd" || UseLinker == "gld"; +} + void tools::addLinkerCompressDebugSectionsOption( const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) { @@ -987,9 +995,11 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, StringRef Sanitizer) { + bool LinkerIsGnuLd = isLinkerGnuLd(TC, Args); + // Solaris ld defaults to --export-dynamic behaviour but doesn't support // the option, so don't try to pass it. - if (TC.getTriple().getOS() == llvm::Triple::Solaris) + if (TC.getTriple().getOS() == llvm::Triple::Solaris && !LinkerIsGnuLd) return true; SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer)); if (llvm::sys::fs::exists(SanRT + ".syms")) { @@ -1005,11 +1015,14 @@ bool as_needed) { assert(!TC.getTriple().isOSAIX() && "AIX linker does not support any form of --as-needed option yet."); + bool LinkerIsGnuLd = isLinkerGnuLd(TC, Args); // While the Solaris 11.2 ld added --as-needed/--no-as-needed as aliases // for the native forms -z ignore/-z record, they are missing in Illumos, // so always use the native form. - if (TC.getTriple().isOSSolaris()) { + // GNU ld doesn't support -z ignore/-z record, so don't use them even on + // Solaris. + if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd) { CmdArgs.push_back("-z"); CmdArgs.push_back(as_needed ? "ignore" : "record"); } else {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits