Skip to content

Commit

Permalink
[Driver] Improve legibility of ld -z options on Solaris
Browse files Browse the repository at this point in the history
Following the lead of the Linux code, this patch passes the `ld -z` options
as two separate args on Solaris, improving legibility.  For lack of a
variadic `std::push_back`, `getAsNeededOption` had to be changed to
`addAsNeededOption`, matching other `add*Options` functions, changing
callers accordingly.  The additional args are also used in a WIP revision
of the Solaris GNU ld patch D85309 <https://reviews.llvm.org/D85309>, which
will allow runtime selection of the linker to use.

Tested on `amd64-pc-solaris2.11` and `x86_64-pc-linux-gnu`.

Differential Revision: https://reviews.llvm.org/D158955
  • Loading branch information
rorth committed Aug 28, 2023
1 parent cec855a commit 779353e
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 40 deletions.
28 changes: 18 additions & 10 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Expand Up @@ -999,24 +999,30 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
return false;
}

const char *tools::getAsNeededOption(const ToolChain &TC, bool as_needed) {
void tools::addAsNeededOption(const ToolChain &TC,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
bool as_needed) {
assert(!TC.getTriple().isOSAIX() &&
"AIX linker does not support any form of --as-needed option yet.");

// 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())
return as_needed ? "-zignore" : "-zrecord";
else
return as_needed ? "--as-needed" : "--no-as-needed";
if (TC.getTriple().isOSSolaris()) {
CmdArgs.push_back("-z");
CmdArgs.push_back(as_needed ? "ignore" : "record");
} else {
CmdArgs.push_back(as_needed ? "--as-needed" : "--no-as-needed");
}
}

void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
const llvm::opt::ArgList &Args,
ArgStringList &CmdArgs) {
// Force linking against the system libraries sanitizers depends on
// (see PR15823 why this is necessary).
CmdArgs.push_back(getAsNeededOption(TC, false));
addAsNeededOption(TC, Args, CmdArgs, false);
// There's no libpthread or librt on RTEMS & Android.
if (TC.getTriple().getOS() != llvm::Triple::RTEMS &&
!TC.getTriple().isAndroid() && !TC.getTriple().isOHOSFamily()) {
Expand Down Expand Up @@ -1260,8 +1266,10 @@ bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringLis
return false;
}

void tools::linkXRayRuntimeDeps(const ToolChain &TC, ArgStringList &CmdArgs) {
CmdArgs.push_back(getAsNeededOption(TC, false));
void tools::linkXRayRuntimeDeps(const ToolChain &TC,
const llvm::opt::ArgList &Args,
ArgStringList &CmdArgs) {
addAsNeededOption(TC, Args, CmdArgs, false);
CmdArgs.push_back("-lpthread");
if (!TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-lrt");
Expand Down Expand Up @@ -1805,7 +1813,7 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
!TC.getTriple().isAndroid() &&
!TC.getTriple().isOSCygMing() && !TC.getTriple().isOSAIX();
if (AsNeeded)
CmdArgs.push_back(getAsNeededOption(TC, true));
addAsNeededOption(TC, Args, CmdArgs, true);

switch (UNW) {
case ToolChain::UNW_None:
Expand Down Expand Up @@ -1839,7 +1847,7 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
}

if (AsNeeded)
CmdArgs.push_back(getAsNeededOption(TC, false));
addAsNeededOption(TC, Args, CmdArgs, false);
}

static void AddLibgcc(const ToolChain &TC, const Driver &D,
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Driver/ToolChains/CommonArgs.h
Expand Up @@ -40,12 +40,13 @@ bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);

void linkSanitizerRuntimeDeps(const ToolChain &TC,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);

bool addXRayRuntime(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);

void linkXRayRuntimeDeps(const ToolChain &TC,
void linkXRayRuntimeDeps(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);

void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
Expand Down Expand Up @@ -142,7 +143,8 @@ void addHIPRuntimeLibArgs(const ToolChain &TC, Compilation &C,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);

const char *getAsNeededOption(const ToolChain &TC, bool as_needed);
void addAsNeededOption(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs, bool as_needed);

llvm::opt::Arg *getLastCSProfileGenerateArg(const llvm::opt::ArgList &Args);
llvm::opt::Arg *getLastProfileUseArg(const llvm::opt::ArgList &Args);
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/FreeBSD.cpp
Expand Up @@ -303,9 +303,9 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lm");
}
if (NeedsSanitizerDeps)
linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
if (NeedsXRayDeps)
linkXRayRuntimeDeps(ToolChain, CmdArgs);
linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
// FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
// the default system libraries. Just mimic this for now.
if (Profiling)
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/Gnu.cpp
Expand Up @@ -588,10 +588,10 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--start-group");

if (NeedsSanitizerDeps)
linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);

if (NeedsXRayDeps)
linkXRayRuntimeDeps(ToolChain, CmdArgs);
linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);

bool WantPthread = Args.hasArg(options::OPT_pthread) ||
Args.hasArg(options::OPT_pthreads);
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/Hexagon.cpp
Expand Up @@ -369,12 +369,12 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (NeedsSanitizerDeps) {
linkSanitizerRuntimeDeps(HTC, CmdArgs);
linkSanitizerRuntimeDeps(HTC, Args, CmdArgs);

CmdArgs.push_back("-lunwind");
}
if (NeedsXRayDeps)
linkXRayRuntimeDeps(HTC, CmdArgs);
linkXRayRuntimeDeps(HTC, Args, CmdArgs);

CmdArgs.push_back("-lclang_rt.builtins-hexagon");
CmdArgs.push_back("-lc");
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/NetBSD.cpp
Expand Up @@ -305,9 +305,9 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lm");
}
if (NeedsSanitizerDeps)
linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
if (NeedsXRayDeps)
linkXRayRuntimeDeps(ToolChain, CmdArgs);
linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lc");
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/OpenBSD.cpp
Expand Up @@ -220,11 +220,11 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
if (NeedsSanitizerDeps) {
CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins"));
linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
}
if (NeedsXRayDeps) {
CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins"));
linkXRayRuntimeDeps(ToolChain, CmdArgs);
linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
}
// FIXME: For some reason GCC passes -lgcc before adding
// the default system libraries. Just mimic this for now.
Expand Down
18 changes: 11 additions & 7 deletions clang/lib/Driver/ToolChains/Solaris.cpp
Expand Up @@ -164,9 +164,9 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so
// forcibly link with libatomic as a workaround.
if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) {
CmdArgs.push_back(getAsNeededOption(getToolChain(), true));
addAsNeededOption(getToolChain(), Args, CmdArgs, true);
CmdArgs.push_back("-latomic");
CmdArgs.push_back(getAsNeededOption(getToolChain(), false));
addAsNeededOption(getToolChain(), Args, CmdArgs, false);
}
CmdArgs.push_back("-lgcc_s");
CmdArgs.push_back("-lc");
Expand All @@ -176,20 +176,24 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
const SanitizerArgs &SA = getToolChain().getSanitizerArgs(Args);
if (NeedsSanitizerDeps) {
linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
linkSanitizerRuntimeDeps(getToolChain(), Args, CmdArgs);

// Work around Solaris/amd64 ld bug when calling __tls_get_addr directly.
// However, ld -z relax=transtls is available since Solaris 11.2, but not
// in Illumos.
if (getToolChain().getTriple().getArch() == llvm::Triple::x86_64 &&
(SA.needsAsanRt() || SA.needsStatsRt() ||
(SA.needsUbsanRt() && !SA.requiresMinimalRuntime())))
CmdArgs.push_back("-zrelax=transtls");
(SA.needsUbsanRt() && !SA.requiresMinimalRuntime()))) {
CmdArgs.push_back("-z");
CmdArgs.push_back("relax=transtls");
}
}
// Avoid AsanInitInternal cycle, Issue #64126.
if (getToolChain().getTriple().isX86() && SA.needsSharedRt() &&
SA.needsAsanRt())
CmdArgs.push_back("-znow");
SA.needsAsanRt()) {
CmdArgs.push_back("-z");
CmdArgs.push_back("now");
}
}

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
Expand Down
20 changes: 10 additions & 10 deletions clang/test/Driver/solaris-ld-sanitizer.c
Expand Up @@ -6,49 +6,49 @@
// 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: -zrelax=transtls
// CHECK-LD-SPARC32-NOT: "-z" "relax=transtls"

/// 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: -zrelax=transtls
// CHECK-LD-SPARC32-NOT: "-z" "relax=transtls"

/// 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: -zrelax=transtls
// CHECK-LD-SPARC64-NOT: "-z" "relax=transtls"

/// 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: -zrelax=transtls
// CHECK-LD-SPARC64-NOT: "-z" "relax=transtls"

/// 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: -zrelax=transtls
// CHECK-LD-X32-NOT: "-z" "relax=transtls"

/// 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: -zrelax=transtls
// CHECK-LD-X32-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: -zrelax=transtls
// CHECK-LD-X64-NOT: "-z" "relax=transtls"

/// 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: -zrelax=transtls
// CHECK-LD-X64-UBSAN: "-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
Expand All @@ -58,10 +58,10 @@
// RUN: %clang -fsanitize=address -shared-libasan --target=i386-pc-solaris2.11 %s -### 2>&1 \
// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \
// RUN: | FileCheck --check-prefix=CHECK-LD-X32-ASAN-SHARED %s
// CHECK-LD-X32-ASAN-SHARED: -znow
// CHECK-LD-X32-ASAN-SHARED: "-z" "now"

/// Check i386-pc-solaris2.11, 32bit, static libclang_rt.asan
// RUN: %clang -fsanitize=address --target=i386-pc-solaris2.11 %s -### 2>&1 \
// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \
// RUN: | FileCheck --check-prefix=CHECK-LD-X32-ASAN %s
// CHECK-LD-X32-ASAN-NOT: -znow
// CHECK-LD-X32-ASAN-NOT: "-z" "now"
2 changes: 1 addition & 1 deletion clang/test/Driver/solaris-ld.c
Expand Up @@ -16,7 +16,7 @@
// 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: "-zignore" "-latomic" "-zrecord"
// CHECK-LD-SPARC32-SAME: "-z" "ignore" "-latomic" "-z" "record"
// CHECK-LD-SPARC32-SAME: "-lgcc_s"
// CHECK-LD-SPARC32-SAME: "-lc"
// CHECK-LD-SPARC32-SAME: "-lgcc"
Expand Down

0 comments on commit 779353e

Please sign in to comment.