llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-driver

Author: windsunil

<details>
<summary>Changes</summary>

While upgrading clang/llvm to 23.1.0 in openembedded-core I hit this
link failure on 32-bit x86 musl:

    ld: undefined reference to `__stack_chk_fail_local'

I dug into it. musl's libc has __stack_chk_fail but not
__stack_chk_fail_local. GCC emits calls to the _local variant in
PIC/PIE code on some targets - I checked with GCC 16: 32-bit x86 does
it, x86_64 does not. So on those targets, any GCC-built object linked
with clang on musl fails once stack protection is used.

Distros already solve this on the GCC side: Alpine and OpenEmbedded
ship a tiny libssp_nonshared.a containing just that symbol, and patch
GCC to add -lssp_nonshared when stack protection is on. Both carry
the same downstream patch for clang too (OpenEmbedded since 2016),
and the GCC side is being fixed in parallel (gcc PR driver/127138,
v2 on gcc-patches: 
https://gcc.gnu.org/pipermail/gcc-patches/2026-August/729351.html)

This patch makes the clang driver do what those patched GCCs do: on
musl, when stack protection is enabled, add -lssp_nonshared - but
only if the library is actually present in the toolchain library
paths. Toolchains that do not ship it see no change.

Tested on i686 musl: a GCC 16 -fPIC -fstack-protector-strong object
fails to link with current clang and links fine with this change.
Added a driver test; the rest of clang/test/Driver is unaffected.


---
Full diff: https://github.com/llvm/llvm-project/pull/219828.diff


4 Files Affected:

- (modified) clang/docs/ReleaseNotes.md (+4) 
- (modified) clang/lib/Driver/ToolChains/Gnu.cpp (+18) 
- (added) clang/test/Driver/Inputs/musl_ssp_tree/usr/lib/libssp_nonshared.a () 
- (added) clang/test/Driver/linux-musl-ssp.c (+28) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index bdbabf2cd98d0..47fb498cd5e3f 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -205,6 +205,10 @@ features cannot lower the translation-unit ABI level;
 - Clang tools now resolve tool names without a path in compilation databases
   through `PATH`.
 
+- On musl targets, the driver now links ``libssp_nonshared.a`` when stack
+  protection is enabled and the library is present in the toolchain library
+  paths, matching what musl distributions configure GCC to do.
+
 - Clang now allows GNU computed `goto` extension in `constexpr` functions, 
matching the relaxed
   `constexpr` function body rules introduced in C++23.
 
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp 
b/clang/lib/Driver/ToolChains/Gnu.cpp
index 04f3b8d2200d6..5285f55897732 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -535,6 +535,24 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, 
const JobAction &JA,
       if (!Args.hasArg(options::OPT_nolibc))
         CmdArgs.push_back("-lc");
 
+      // musl does not provide __stack_chk_fail_local, but GCC emits calls
+      // to it in PIC/PIE code on some targets (32-bit x86, PowerPC). musl
+      // distributions ship the symbol in libssp_nonshared.a and make GCC
+      // link it when stack protection is on; match that if the library
+      // exists.
+      if (ToolChain.getTriple().isMusl()) {
+        bool WantsSSP = ToolChain.GetDefaultStackProtectorLevel(
+                            /*KernelOrKext=*/false) != LangOptions::SSPOff;
+        if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
+                                     options::OPT_fstack_protector,
+                                     options::OPT_fstack_protector_all,
+                                     options::OPT_fstack_protector_strong))
+          WantsSSP = !A->getOption().matches(options::OPT_fno_stack_protector);
+        if (WantsSSP &&
+            ToolChain.GetFilePath("libssp_nonshared.a") != 
"libssp_nonshared.a")
+          CmdArgs.push_back("-lssp_nonshared");
+      }
+
       // Add IAMCU specific libs, if needed.
       if (IsIAMCU)
         CmdArgs.push_back("-lgloss");
diff --git a/clang/test/Driver/Inputs/musl_ssp_tree/usr/lib/libssp_nonshared.a 
b/clang/test/Driver/Inputs/musl_ssp_tree/usr/lib/libssp_nonshared.a
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/linux-musl-ssp.c 
b/clang/test/Driver/linux-musl-ssp.c
new file mode 100644
index 0000000000000..4e6bc9cc427ce
--- /dev/null
+++ b/clang/test/Driver/linux-musl-ssp.c
@@ -0,0 +1,28 @@
+// Check that on musl the driver links libssp_nonshared.a when stack
+// protection is enabled and the sysroot provides the library.
+
+// RUN: %clang -### --target=i686-unknown-linux-musl \
+// RUN:   --sysroot=%S/Inputs/musl_ssp_tree -fstack-protector-strong %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=SSP %s
+// SSP: "-lc" "-lssp_nonshared"
+
+// Not with stack protection disabled (last flag wins).
+// RUN: %clang -### --target=i686-unknown-linux-musl \
+// RUN:   --sysroot=%S/Inputs/musl_ssp_tree -fstack-protector-strong \
+// RUN:   -fno-stack-protector %s 2>&1 | FileCheck --check-prefix=NOSSP %s
+// NOSSP-NOT: "-lssp_nonshared"
+
+// Not without any stack protector flag.
+// RUN: %clang -### --target=i686-unknown-linux-musl \
+// RUN:   --sysroot=%S/Inputs/musl_ssp_tree %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=NOSSP %s
+
+// Not on glibc: libc_nonshared.a is linked via the libc.so linker script.
+// RUN: %clang -### --target=i686-unknown-linux-gnu \
+// RUN:   --sysroot=%S/Inputs/musl_ssp_tree -fstack-protector-strong %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=NOSSP %s
+
+// Not when the sysroot does not provide the library.
+// RUN: %clang -### --target=i686-unknown-linux-musl \
+// RUN:   --sysroot=%S/Inputs/basic_linux_tree -fstack-protector-strong %s \
+// RUN:   2>&1 | FileCheck --check-prefix=NOSSP %s

``````````

</details>


https://github.com/llvm/llvm-project/pull/219828
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to