summary refs log tree commit diff
diff options
context:
space:
mode:
authorJörg Thalheim <Mic92@users.noreply.github.com>2021-05-25 06:32:25 +0100
committerGitHub <noreply@github.com>2021-05-25 06:32:25 +0100
commit5551a785784e839d68c65b3e2daf81916d165c29 (patch)
treed9d702511de64680a184f9275949fd5bddc6811d
parent18d250069d6a23479ffea1682476dfb3888b40d4 (diff)
parent602b5f8747e63ff737d48e6f18c8fd35168a707c (diff)
downloadnixpkgs-5551a785784e839d68c65b3e2daf81916d165c29.tar
nixpkgs-5551a785784e839d68c65b3e2daf81916d165c29.tar.gz
nixpkgs-5551a785784e839d68c65b3e2daf81916d165c29.tar.bz2
nixpkgs-5551a785784e839d68c65b3e2daf81916d165c29.tar.lz
nixpkgs-5551a785784e839d68c65b3e2daf81916d165c29.tar.xz
nixpkgs-5551a785784e839d68c65b3e2daf81916d165c29.tar.zst
nixpkgs-5551a785784e839d68c65b3e2daf81916d165c29.zip
Merge pull request #123989 from Mic92/static-pie
glibc: allow to build position-independent static executable
-rw-r--r--pkgs/build-support/bintools-wrapper/ld-wrapper.sh35
-rw-r--r--pkgs/build-support/cc-wrapper/cc-wrapper.sh15
-rw-r--r--pkgs/build-support/wrapper-common/utils.bash35
-rw-r--r--pkgs/development/libraries/glibc/common.nix2
-rw-r--r--pkgs/test/cc-wrapper/default.nix3
5 files changed, 66 insertions, 24 deletions
diff --git a/pkgs/build-support/bintools-wrapper/ld-wrapper.sh b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh
index e54dd6f4714..2f96480f80c 100644
--- a/pkgs/build-support/bintools-wrapper/ld-wrapper.sh
+++ b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh
@@ -20,15 +20,25 @@ if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
     source @out@/nix-support/add-flags.sh
 fi
 
-setDynamicLinker=1
 
 # Optionally filter out paths not refering to the store.
 expandResponseParams "$@"
+
+# NIX_LINK_TYPE is set if ld has been called through our cc wrapper. We take
+# advantage of this to avoid both recalculating it, and also repeating other
+# processing cc wrapper has already done.
+if [[ -n "${NIX_LINK_TYPE_@suffixSalt@:-}" ]]; then
+    linkType=$NIX_LINK_TYPE_@suffixSalt@
+else
+    linkType=$(checkLinkType "$@")
+fi
+
 if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}"
-        && ( -z "$NIX_IGNORE_LD_THROUGH_GCC_@suffixSalt@" || -z "${NIX_LDFLAGS_SET_@suffixSalt@:-}" ) ]]; then
+        && ( -z "$NIX_IGNORE_LD_THROUGH_GCC_@suffixSalt@" || -z "${NIX_LINK_TYPE_@suffixSalt@:-}" ) ]]; then
     rest=()
     nParams=${#params[@]}
     declare -i n=0
+
     while (( "$n" < "$nParams" )); do
         p=${params[n]}
         p2=${params[n+1]:-} # handle `p` being last one
@@ -48,11 +58,6 @@ if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}"
             # Our ld is not built with sysroot support (Can we fix that?)
             :
         else
-            if [[ "$p" = -static || "$p" = -static-pie ]]; then
-                # Using a dynamic linker for static binaries can lead to crashes.
-                # This was observed for rust binaries.
-                setDynamicLinker=0
-            fi
             rest+=("$p")
         fi
         n+=1
@@ -61,22 +66,24 @@ if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}"
     params=(${rest+"${rest[@]}"})
 fi
 
+
 source @out@/nix-support/add-hardening.sh
 
 extraAfter=()
 extraBefore=(${hardeningLDFlags[@]+"${hardeningLDFlags[@]}"})
 
-if [ -z "${NIX_LDFLAGS_SET_@suffixSalt@:-}" ]; then
-    extraAfter+=($NIX_LDFLAGS_@suffixSalt@)
-    extraBefore+=($NIX_LDFLAGS_BEFORE_@suffixSalt@)
+if [ -z "${NIX_LINK_TYPE_@suffixSalt@:-}" ]; then
+    extraAfter+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_@suffixSalt@))
+    extraBefore+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_BEFORE_@suffixSalt@))
+
     # By adding dynamic linker to extraBefore we allow the users set their
     # own dynamic linker as NIX_LD_FLAGS will override earlier set flags
-    if [[ "$setDynamicLinker" = 1 && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then
+    if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then
         extraBefore+=("-dynamic-linker" "$NIX_DYNAMIC_LINKER_@suffixSalt@")
     fi
 fi
 
-extraAfter+=($NIX_LDFLAGS_AFTER_@suffixSalt@)
+extraAfter+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_AFTER_@suffixSalt@))
 
 # These flags *must not* be pulled up to -Wl, flags, so they can't go in
 # add-flags.sh. They must always be set, so must not be disabled by
@@ -173,7 +180,7 @@ do
     prev="$p"
 done
 
-if [[ "$link32" = "1" && "$setDynamicLinker" = 1 && -e "@out@/nix-support/dynamic-linker-m32" ]]; then
+if [[ "$link32" == "1" && "$linkType" == dynamic && -e "@out@/nix-support/dynamic-linker-m32" ]]; then
     # We have an alternate 32-bit linker and we're producing a 32-bit ELF, let's
     # use it.
     extraAfter+=(
@@ -183,7 +190,7 @@ if [[ "$link32" = "1" && "$setDynamicLinker" = 1 && -e "@out@/nix-support/dynami
 fi
 
 # Add all used dynamic libraries to the rpath.
-if [ "$NIX_DONT_SET_RPATH_@suffixSalt@" != 1 ]; then
+if [[ "$NIX_DONT_SET_RPATH_@suffixSalt@" != 1 && "$linkType" != static-pie ]]; then
     # For each directory in the library search path (-L...),
     # see if it contains a dynamic library used by a -l... flag.  If
     # so, add the directory to the rpath.
diff --git a/pkgs/build-support/cc-wrapper/cc-wrapper.sh b/pkgs/build-support/cc-wrapper/cc-wrapper.sh
index 2e62aef4604..aa25de33641 100644
--- a/pkgs/build-support/cc-wrapper/cc-wrapper.sh
+++ b/pkgs/build-support/cc-wrapper/cc-wrapper.sh
@@ -29,9 +29,10 @@ cc1=0
 cxxInclude=1
 cxxLibrary=1
 cInclude=1
-setDynamicLinker=1
 
 expandResponseParams "$@"
+linkType=$(checkLinkType "$@")
+
 declare -i n=0
 nParams=${#params[@]}
 while (( "$n" < "$nParams" )); do
@@ -60,8 +61,6 @@ while (( "$n" < "$nParams" )); do
         cxxInclude=0
     elif [ "$p" = -nostdinc++ ]; then
         cxxInclude=0
-    elif [[ "$p" = -static || "$p" = -static-pie ]]; then
-        setDynamicLinker=0
     elif [[ "$p" != -?* ]]; then
         # A dash alone signifies standard input; it is not a flag
         nonFlagArgs=1
@@ -151,24 +150,24 @@ if [ "$dontLink" != 1 ]; then
 
     # Add the flags that should only be passed to the compiler when
     # linking.
-    extraAfter+=($NIX_CFLAGS_LINK_@suffixSalt@)
+    extraAfter+=($(filterRpathFlags "$linkType" $NIX_CFLAGS_LINK_@suffixSalt@))
 
     # Add the flags that should be passed to the linker (and prevent
     # `ld-wrapper' from adding NIX_LDFLAGS_@suffixSalt@ again).
-    for i in $NIX_LDFLAGS_BEFORE_@suffixSalt@; do
+    for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_BEFORE_@suffixSalt@); do
         extraBefore+=("-Wl,$i")
     done
-    if [[ "$setDynamicLinker" = 1 && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then
+    if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then
         extraBefore+=("-Wl,-dynamic-linker=$NIX_DYNAMIC_LINKER_@suffixSalt@")
     fi
-    for i in $NIX_LDFLAGS_@suffixSalt@; do
+    for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_@suffixSalt@); do
         if [ "${i:0:3}" = -L/ ]; then
             extraAfter+=("$i")
         else
             extraAfter+=("-Wl,$i")
         fi
     done
-    export NIX_LDFLAGS_SET_@suffixSalt@=1
+    export NIX_LINK_TYPE_@suffixSalt@=$linkType
 fi
 
 # As a very special hack, if the arguments are just `-v', then don't
diff --git a/pkgs/build-support/wrapper-common/utils.bash b/pkgs/build-support/wrapper-common/utils.bash
index f773270f7de..cb3552ebc54 100644
--- a/pkgs/build-support/wrapper-common/utils.bash
+++ b/pkgs/build-support/wrapper-common/utils.bash
@@ -129,3 +129,38 @@ expandResponseParams() {
         fi
     done
 }
+
+checkLinkType() {
+    local arg mode
+    type="dynamic"
+    for arg in "$@"; do
+        if [[ "$arg" = -static ]]; then
+            type="static"
+        elif [[ "$arg" = -static-pie ]]; then
+            type="static-pie"
+        fi
+    done
+    echo "$type"
+}
+
+# When building static-pie executables we cannot have rpath
+# set. At least glibc requires rpath to be empty
+filterRpathFlags() {
+    local linkType=$1 ret="" i
+    shift
+
+    if [[ "$linkType" == "static-pie" ]]; then
+        while [[ "$#" -gt 0 ]]; do
+            i="$1"; shift 1
+            if [[ "$i" == -rpath ]]; then
+                # also skip its argument
+                shift
+            else
+                ret+="$i "
+            fi
+        done
+    else
+        ret=$@
+    fi
+    echo $ret
+}
diff --git a/pkgs/development/libraries/glibc/common.nix b/pkgs/development/libraries/glibc/common.nix
index 3597dd70f2c..f0df6f9e592 100644
--- a/pkgs/development/libraries/glibc/common.nix
+++ b/pkgs/development/libraries/glibc/common.nix
@@ -153,6 +153,8 @@ stdenv.mkDerivation ({
       "--enable-add-ons"
       "--sysconfdir=/etc"
       "--enable-stackguard-randomization"
+      "--enable-static-pie"
+      "--enable-bind-now"
       (lib.withFeatureAs withLinuxHeaders "headers" "${linuxHeaders}/include")
       (lib.enableFeature profilingLibraries "profile")
     ] ++ lib.optionals withLinuxHeaders [
diff --git a/pkgs/test/cc-wrapper/default.nix b/pkgs/test/cc-wrapper/default.nix
index d82ba296e2f..b483372dea0 100644
--- a/pkgs/test/cc-wrapper/default.nix
+++ b/pkgs/test/cc-wrapper/default.nix
@@ -35,8 +35,7 @@ in stdenv.mkDerivation {
       printf "checking whether compiler builds valid static C binaries... " >&2
       $CC ${staticLibc} -static -o cc-static ${./cc-main.c}
       ./cc-static
-      # our glibc does not have pie enabled yet.
-      ${lib.optionalString (stdenv.hostPlatform.isMusl && stdenv.cc.isGNU) ''
+      ${lib.optionalString (stdenv.cc.isGNU && lib.versionAtLeast (lib.getVersion stdenv.cc.name) "8.0.0") ''
         printf "checking whether compiler builds valid static pie C binaries... " >&2
         $CC ${staticLibc} -static-pie -o cc-static-pie ${./cc-main.c}
         ./cc-static-pie