[clang] [Hexagon] Add scs multilib for -fsanitize=shadow-call-stack (PR #208833)
Brian Cain via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 10 21:19:32 PDT 2026
https://github.com/androm3da updated https://github.com/llvm/llvm-project/pull/208833
>From 94dd6bb4c974a8480eded17ecdee201395288cef Mon Sep 17 00:00:00 2001
From: Brian Cain <brian.cain at oss.qualcomm.com>
Date: Fri, 10 Jul 2026 13:37:07 -0700
Subject: [PATCH 1/2] [Hexagon] Add scs multilib for
-fsanitize=shadow-call-stack
musl hexagon targets already select msan/asan library variants based
on the sanitizer in use; do the same for shadow-call-stack so that
-fsanitize=shadow-call-stack picks up usr/lib/scs.
---
clang/lib/Driver/ToolChains/Hexagon.cpp | 5 +++++
clang/test/Driver/hexagon-toolchain-linux.c | 24 ++++++++++++++++++++-
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index 4dd519a2c239b..6ac6c20ae7224 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -743,12 +743,17 @@ HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
Multilibs.push_back(MultilibBuilder("asan", {}, {})
.flag("-fsanitize=address")
.makeMultilib());
+ Multilibs.push_back(MultilibBuilder("scs", {}, {})
+ .flag("-fsanitize=shadow-call-stack")
+ .makeMultilib());
Multilib::flags_list Flags;
addMultilibFlag(getSanitizerArgs(Args).needsMsanRt(), "-fsanitize=memory",
Flags);
addMultilibFlag(getSanitizerArgs(Args).needsAsanRt(), "-fsanitize=address",
Flags);
+ addMultilibFlag(getSanitizerArgs(Args).hasShadowCallStack(),
+ "-fsanitize=shadow-call-stack", Flags);
if (Multilibs.select(D, Flags, SelectedMultilibs)) {
Multilib LastSelected = SelectedMultilibs.back();
diff --git a/clang/test/Driver/hexagon-toolchain-linux.c b/clang/test/Driver/hexagon-toolchain-linux.c
index 3f19a37d8a38b..669e2b504d282 100644
--- a/clang/test/Driver/hexagon-toolchain-linux.c
+++ b/clang/test/Driver/hexagon-toolchain-linux.c
@@ -223,7 +223,28 @@
// CHECK-ASAN: "-L{{[^"]*}}basic_linux_libcxx_tree{{/|\\\\}}usr{{/|\\\\}}lib{{/|\\\\}}asan"
// CHECK-ASAN-SAME: "-L{{[^"]*}}basic_linux_libcxx_tree{{/|\\\\}}usr{{/|\\\\}}lib"
// -----------------------------------------------------------------------------
-// No sanitizer: no msan/asan library paths
+// Sanitizer library paths: -fsanitize=shadow-call-stack
+// -----------------------------------------------------------------------------
+// RUN: %clang -### --target=hexagon-unknown-linux-musl \
+// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
+// RUN: -mcpu=hexagonv60 \
+// RUN: -fuse-ld=lld \
+// RUN: -fsanitize=shadow-call-stack -ffixed-r19 \
+// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree %s 2>&1 | FileCheck -check-prefix=CHECK-SCS %s
+// CHECK-SCS: "-L{{[^"]*}}basic_linux_libcxx_tree{{/|\\\\}}usr{{/|\\\\}}lib{{/|\\\\}}scs"
+// CHECK-SCS-SAME: "-L{{[^"]*}}basic_linux_libcxx_tree{{/|\\\\}}usr{{/|\\\\}}lib"
+// -----------------------------------------------------------------------------
+// Library paths: -ffixed-r19 alone must NOT select the scs multilib
+// -----------------------------------------------------------------------------
+// RUN: %clang -### --target=hexagon-unknown-linux-musl \
+// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
+// RUN: -mcpu=hexagonv60 \
+// RUN: -fuse-ld=lld \
+// RUN: -ffixed-r19 \
+// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree %s 2>&1 | FileCheck -check-prefix=CHECK-R19-ONLY %s
+// CHECK-R19-ONLY-NOT: "-L{{.*}}{{/|\\\\}}scs"
+// -----------------------------------------------------------------------------
+// No sanitizer: no msan/asan/scs library paths
// -----------------------------------------------------------------------------
// RUN: %clang -### --target=hexagon-unknown-linux-musl \
// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
@@ -232,6 +253,7 @@
// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree %s 2>&1 | FileCheck -check-prefix=CHECK-NOSAN %s
// CHECK-NOSAN-NOT: "-L{{.*}}{{/|\\\\}}msan"
// CHECK-NOSAN-NOT: "-L{{.*}}{{/|\\\\}}asan"
+// CHECK-NOSAN-NOT: "-L{{.*}}{{/|\\\\}}scs"
// -----------------------------------------------------------------------------
// ThinLTO passes LTO options to the linker
// -----------------------------------------------------------------------------
>From a455c8ba2dc6e08acbf64776154078c802c936bb Mon Sep 17 00:00:00 2001
From: Brian Cain <brian.cain at oss.qualcomm.com>
Date: Fri, 10 Jul 2026 22:50:32 -0500
Subject: [PATCH 2/2] [Hexagon] Select startup objects from the selected
multilib dir
Resolve crt1.o/crti.o from the selected multilib's library directory:
usr/lib<suffix>/ for a non-default sanitizer multilib (e.g. "scs"), and the
base usr/lib for the default multilib. This lets the shadow-call-stack multilib
ship a crt1.o whose _start initialises r19 (the shadow-stack pointer) before any
instrumented code runs, which is required for whole-program
-fsanitize=shadow-call-stack on musl.
---
clang/lib/Driver/ToolChains/Hexagon.cpp | 20 +++++++++++------
clang/test/Driver/hexagon-toolchain-linux.c | 24 +++++++++++++++++++++
2 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index 6ac6c20ae7224..aeb08bb06bc7b 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -356,19 +356,25 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_shared, options::OPT_static, options::OPT_r))
CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");
+ StringRef MLSuffix;
+ if (!HTC.getSelectedMultilibs().empty() &&
+ !HTC.getSelectedMultilibs().back().isDefault())
+ MLSuffix = HTC.getSelectedMultilibs().back().gccSuffix();
+ auto StartFile = [&](StringRef Name) -> std::string {
+ return D.SysRoot + "/usr/lib" + MLSuffix.str() + "/" + Name.str();
+ };
+
if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles,
options::OPT_nostdlib, options::OPT_r))
- CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o"));
+ CmdArgs.push_back(Args.MakeArgString(StartFile("crt1.o")));
else if (Args.hasArg(options::OPT_shared) &&
!Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib,
options::OPT_r))
- CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o"));
+ CmdArgs.push_back(Args.MakeArgString(StartFile("crti.o")));
- if (!HTC.getSelectedMultilibs().empty() &&
- !HTC.getSelectedMultilibs().back().isDefault()) {
- CmdArgs.push_back(
- Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib" +
- HTC.getSelectedMultilibs().back().gccSuffix()));
+ if (!MLSuffix.empty()) {
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + D.SysRoot +
+ "/usr/lib" + MLSuffix));
}
CmdArgs.push_back(
Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib"));
diff --git a/clang/test/Driver/hexagon-toolchain-linux.c b/clang/test/Driver/hexagon-toolchain-linux.c
index 669e2b504d282..ed2acd9c61c2e 100644
--- a/clang/test/Driver/hexagon-toolchain-linux.c
+++ b/clang/test/Driver/hexagon-toolchain-linux.c
@@ -244,6 +244,30 @@
// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree %s 2>&1 | FileCheck -check-prefix=CHECK-R19-ONLY %s
// CHECK-R19-ONLY-NOT: "-L{{.*}}{{/|\\\\}}scs"
// -----------------------------------------------------------------------------
+// Startup object: -fsanitize=shadow-call-stack links the scs crt1.o, not the
+// base crt1.o. Selection is on the multilib in effect, not file presence, so
+// this holds even though the test sysroot ships no usr/lib/scs/crt1.o.
+// -----------------------------------------------------------------------------
+// RUN: %clang -### --target=hexagon-unknown-linux-musl \
+// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
+// RUN: -mcpu=hexagonv60 \
+// RUN: -fuse-ld=lld \
+// RUN: -fsanitize=shadow-call-stack -ffixed-r19 \
+// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree %s 2>&1 | FileCheck -check-prefix=CHECK-SCS-CRT %s
+// CHECK-SCS-CRT: "{{[^"]*}}basic_linux_libcxx_tree{{/|\\\\}}usr{{/|\\\\}}lib{{/|\\\\}}scs{{/|\\\\}}crt1.o"
+// CHECK-SCS-CRT-NOT: "{{[^"]*}}basic_linux_libcxx_tree{{/|\\\\}}usr{{/|\\\\}}lib{{/|\\\\}}crt1.o"
+// -----------------------------------------------------------------------------
+// Startup object: without the scs multilib, the base crt1.o is used (never the
+// scs one).
+// -----------------------------------------------------------------------------
+// RUN: %clang -### --target=hexagon-unknown-linux-musl \
+// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
+// RUN: -mcpu=hexagonv60 \
+// RUN: -fuse-ld=lld \
+// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree %s 2>&1 | FileCheck -check-prefix=CHECK-NOSCS-CRT %s
+// CHECK-NOSCS-CRT: "{{[^"]*}}basic_linux_libcxx_tree{{/|\\\\}}usr{{/|\\\\}}lib{{/|\\\\}}crt1.o"
+// CHECK-NOSCS-CRT-NOT: "{{/|\\\\}}scs{{/|\\\\}}crt1.o"
+// -----------------------------------------------------------------------------
// No sanitizer: no msan/asan/scs library paths
// -----------------------------------------------------------------------------
// RUN: %clang -### --target=hexagon-unknown-linux-musl \
More information about the cfe-commits
mailing list