Skip to content

Commit ccfd26e

Browse files
committed
bintools-wrapper: skip dynamic linker for static binaries
Currently we set dynamic-linker unconditionally. This breaks however some static binaries i.e. rust binaries linked against musl. There is no reason we should set an elf interpreter for static binaries hence this is skipped if `-static` or `-static-pie` is either passed to our cc or ld wrapper.
1 parent c2842e5 commit ccfd26e

5 files changed

Lines changed: 40 additions & 12 deletions

File tree

pkgs/build-support/bintools-wrapper/add-flags.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var_templates_list=(
33
NIX_IGNORE_LD_THROUGH_GCC
44
NIX_LDFLAGS
55
NIX_LDFLAGS_BEFORE
6+
NIX_DYNAMIC_LINKER
67
NIX_LDFLAGS_AFTER
78
NIX_LDFLAGS_HARDEN
89
NIX_HARDENING_ENABLE
@@ -25,6 +26,10 @@ if [ -e @out@/nix-support/libc-ldflags ]; then
2526
NIX_LDFLAGS_@suffixSalt@+=" $(< @out@/nix-support/libc-ldflags)"
2627
fi
2728

29+
if [ -z "$NIX_DYNAMIC_LINKER_@suffixSalt@" ] && [ -e @out@/nix-support/dynamic-linker ]; then
30+
NIX_DYNAMIC_LINKER_@suffixSalt@="$(< @out@/nix-support/dynamic-linker)"
31+
fi
32+
2833
if [ -e @out@/nix-support/libc-ldflags-before ]; then
2934
NIX_LDFLAGS_BEFORE_@suffixSalt@="$(< @out@/nix-support/libc-ldflags-before) $NIX_LDFLAGS_BEFORE_@suffixSalt@"
3035
fi

pkgs/build-support/bintools-wrapper/default.nix

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,13 +243,7 @@ stdenv.mkDerivation {
243243
if [ -e ${libc_lib}/lib/32/ld-linux.so.2 ]; then
244244
echo ${libc_lib}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32
245245
fi
246-
''
247-
# The dynamic linker is passed in `ldflagsBefore' to allow
248-
# explicit overrides of the dynamic linker by callers to ld
249-
# (the *last* value counts, so ours should come first).
250-
+ ''
251-
echo -dynamic-linker "$dynamicLinker" >> $out/nix-support/libc-ldflags-before
252-
'') + ''
246+
'') + ''
253247
fi
254248
'')
255249

pkgs/build-support/bintools-wrapper/ld-wrapper.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
2020
source @out@/nix-support/add-flags.sh
2121
fi
2222

23+
setDynamicLinker=1
2324

2425
# Optionally filter out paths not refering to the store.
2526
expandResponseParams "$@"
@@ -47,6 +48,11 @@ if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}"
4748
# Our ld is not built with sysroot support (Can we fix that?)
4849
:
4950
else
51+
if [[ "$p" = -static || "$p" = -static-pie ]]; then
52+
# Using a dynamic linker for static binaries can lead to crashes.
53+
# This was observed for rust binaries.
54+
setDynamicLinker=0
55+
fi
5056
rest+=("$p")
5157
fi
5258
n+=1
@@ -63,6 +69,11 @@ extraBefore=(${hardeningLDFlags[@]+"${hardeningLDFlags[@]}"})
6369
if [ -z "${NIX_LDFLAGS_SET_@suffixSalt@:-}" ]; then
6470
extraAfter+=($NIX_LDFLAGS_@suffixSalt@)
6571
extraBefore+=($NIX_LDFLAGS_BEFORE_@suffixSalt@)
72+
# By adding dynamic linker to extraBefore we allow the users set their
73+
# own dynamic linker as NIX_LD_FLAGS will override earlier set flags
74+
if [ "$setDynamicLinker" = 1 ]; then
75+
extraBefore+=("-dynamic-linker" "$NIX_DYNAMIC_LINKER_@suffixSalt@")
76+
fi
6677
fi
6778

6879
extraAfter+=($NIX_LDFLAGS_AFTER_@suffixSalt@)
@@ -134,7 +145,7 @@ then
134145
done
135146
fi
136147

137-
if [ -e "@out@/nix-support/dynamic-linker-m32" ] && (( "$link32" )); then
148+
if [[ "$link32" = "0" && "$setDynamicLinker" = 1 && -e "@out@/nix-support/dynamic-linker-m32" ]]; then
138149
# We have an alternate 32-bit linker and we're producing a 32-bit ELF, let's
139150
# use it.
140151
extraAfter+=(

pkgs/build-support/cc-wrapper/cc-wrapper.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ cc1=0
2828
[[ "@prog@" = *++ ]] && isCpp=1 || isCpp=0
2929
cppInclude=1
3030
cInclude=1
31+
setDynamicLinker=1
3132

3233
expandResponseParams "$@"
3334
declare -i n=0
@@ -58,6 +59,8 @@ while (( "$n" < "$nParams" )); do
5859
cppInclude=0
5960
elif [ "$p" = -nostdinc++ ]; then
6061
cppInclude=0
62+
elif [[ "$p" = -static || "$p" = -static-pie ]]; then
63+
setDynamicLinker=0
6164
elif [[ "$p" != -?* ]]; then
6265
# A dash alone signifies standard input; it is not a flag
6366
nonFlagArgs=1
@@ -152,6 +155,9 @@ if [ "$dontLink" != 1 ]; then
152155
for i in $NIX_LDFLAGS_BEFORE_@suffixSalt@; do
153156
extraBefore+=("-Wl,$i")
154157
done
158+
if [ "$setDynamicLinker" = 1 ]; then
159+
extraBefore+=("-Wl,-dynamic-linker=$NIX_DYNAMIC_LINKER_@suffixSalt@")
160+
fi
155161
for i in $NIX_LDFLAGS_@suffixSalt@; do
156162
if [ "${i:0:3}" = -L/ ]; then
157163
extraAfter+=("$i")

pkgs/test/cc-wrapper/default.nix

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
{ stdenv }:
1+
{ stdenv, glibc }:
22
with stdenv.lib;
33
let
44
# Sanitizers are not supported on Darwin.
55
# Sanitizer headers aren't available in older libc++ stdenvs due to a bug
6-
sanitizersWorking =
7-
(stdenv.cc.isClang && versionAtLeast (getVersion stdenv.cc.name) "5.0.0")
8-
|| (stdenv.cc.isGNU && stdenv.isLinux);
6+
sanitizersWorking = !stdenv.hostPlatform.isMusl && (
7+
(stdenv.cc.isClang && versionAtLeast (getVersion stdenv.cc.name) "5.0.0")
8+
|| (stdenv.cc.isGNU && stdenv.isLinux)
9+
);
10+
staticLibc = optionalString (stdenv.hostPlatform.libc == "glibc") "-L ${glibc.static}/lib";
911
in stdenv.mkDerivation {
1012
name = "cc-wrapper-test";
1113

@@ -28,6 +30,16 @@ in stdenv.mkDerivation {
2830
./core-foundation-check
2931
''}
3032
33+
printf "checking whether compiler builds valid static C binaries... " >&2
34+
$CC ${staticLibc} -static -o cc-static ${./cc-main.c}
35+
./cc-static
36+
# our glibc does not have pie enabled yet.
37+
${optionalString (stdenv.hostPlatform.isMusl && stdenv.cc.isGNU) ''
38+
printf "checking whether compiler builds valid static pie C binaries... " >&2
39+
$CC ${staticLibc} -static-pie -o cc-static-pie ${./cc-main.c}
40+
./cc-static-pie
41+
''}
42+
3143
printf "checking whether compiler uses NIX_CFLAGS_COMPILE... " >&2
3244
mkdir -p foo/include
3345
cp ${./foo.c} foo/include/foo.h

0 commit comments

Comments
 (0)