From 40e9b2a7e6490eef782e5c34703a99e61fae7017 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 28 Aug 2017 14:56:08 -0400 Subject: [PATCH] binutils-wrapper: Init Factor a binutils wrapper out of cc-wrapper. While only LD is wrapped, the setup hook defines environment variables on behalf of other utilites. --- .../binutils-wrapper/add-flags.sh | 40 +++ .../binutils-wrapper/add-hardening.sh | 53 ++++ .../binutils-wrapper/default.nix | 288 ++++++++++++++++++ .../ld-solaris-wrapper.sh | 0 .../ld-wrapper.sh | 2 +- .../binutils-wrapper/setup-hook.sh | 63 ++++ pkgs/build-support/cc-wrapper/add-flags.sh | 19 +- .../build-support/cc-wrapper/add-hardening.sh | 10 - pkgs/build-support/cc-wrapper/cc-wrapper.sh | 6 + pkgs/build-support/cc-wrapper/default.nix | 139 ++------- .../macos-sierra-reexport-hack.bash | 106 ------- pkgs/build-support/cc-wrapper/setup-hook.sh | 23 -- 12 files changed, 482 insertions(+), 267 deletions(-) create mode 100644 pkgs/build-support/binutils-wrapper/add-flags.sh create mode 100644 pkgs/build-support/binutils-wrapper/add-hardening.sh create mode 100644 pkgs/build-support/binutils-wrapper/default.nix rename pkgs/build-support/{cc-wrapper => binutils-wrapper}/ld-solaris-wrapper.sh (100%) mode change 100755 => 100644 rename pkgs/build-support/{cc-wrapper => binutils-wrapper}/ld-wrapper.sh (98%) create mode 100644 pkgs/build-support/binutils-wrapper/setup-hook.sh delete mode 100644 pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash diff --git a/pkgs/build-support/binutils-wrapper/add-flags.sh b/pkgs/build-support/binutils-wrapper/add-flags.sh new file mode 100644 index 00000000000..a69e2313af3 --- /dev/null +++ b/pkgs/build-support/binutils-wrapper/add-flags.sh @@ -0,0 +1,40 @@ +# See cc-wrapper for comments. +var_templates_list=( + NIX+IGNORE_LD_THROUGH_GCC + NIX+LDFLAGS + NIX+LDFLAGS_BEFORE + NIX+LDFLAGS_AFTER + NIX+LDFLAGS_HARDEN +) +var_templates_bool=( + NIX+SET_BUILD_ID + NIX+DONT_SET_RPATH +) + +declare -a role_infixes=() +if [ "${NIX_BINUTILS_WRAPPER_@infixSalt@_TARGET_BUILD:-}" ]; then + role_infixes+=(_BUILD_) +fi +if [ "${NIX_BINUTILS_WRAPPER_@infixSalt@_TARGET_HOST:-}" ]; then + role_infixes+=(_) +fi +if [ "${NIX_BINUTILS_WRAPPER_@infixSalt@_TARGET_TARGET:-}" ]; then + role_infixes+=(_TARGET_) +fi + +for var in "${var_templates_list[@]}"; do + mangleVarList "$var" "${role_infixes[@]}" +done +for var in "${var_templates_bool[@]}"; do + mangleVarBool "$var" "${role_infixes[@]}" +done + +if [ -e @out@/nix-support/libc-ldflags ]; then + NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/libc-ldflags)" +fi + +if [ -e @out@/nix-support/libc-ldflags-before ]; then + NIX_@infixSalt@_LDFLAGS_BEFORE="$(< @out@/nix-support/libc-ldflags-before) $NIX_@infixSalt@_LDFLAGS_BEFORE" +fi + +export NIX_BINUTILS_WRAPPER_@infixSalt@_FLAGS_SET=1 diff --git a/pkgs/build-support/binutils-wrapper/add-hardening.sh b/pkgs/build-support/binutils-wrapper/add-hardening.sh new file mode 100644 index 00000000000..6dabc2007bc --- /dev/null +++ b/pkgs/build-support/binutils-wrapper/add-hardening.sh @@ -0,0 +1,53 @@ +hardeningFlags=(relro bindnow) +# Intentionally word-split in case 'hardeningEnable' is defined in +# Nix. Also, our bootstrap tools version of bash is old enough that +# undefined arrays trip `set -u`. +if [[ -v hardeningEnable[@] ]]; then + hardeningFlags+=(${hardeningEnable[@]}) +fi +hardeningLDFlags=() + +declare -A hardeningDisableMap + +# Intentionally word-split in case 'hardeningDisable' is defined in Nix. +for flag in ${hardeningDisable[@]:-IGNORED_KEY} @hardening_unsupported_flags@ +do + hardeningDisableMap[$flag]=1 +done + +if [[ -n "${NIX_DEBUG:-}" ]]; then + printf 'HARDENING: disabled flags:' >&2 + (( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2 + echo >&2 +fi + +if [[ -z "${hardeningDisableMap[all]:-}" ]]; then + if [[ -n "${NIX_DEBUG:-}" ]]; then + echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2; + fi + for flag in "${hardeningFlags[@]}" + do + if [[ -z "${hardeningDisableMap[$flag]:-}" ]]; then + case $flag in + pie) + if [[ ! ("$*" =~ " -shared " || "$*" =~ " -static ") ]]; then + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling LDFlags -pie >&2; fi + hardeningLDFlags+=('-pie') + fi + ;; + relro) + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling relro >&2; fi + hardeningLDFlags+=('-z' 'relro') + ;; + bindnow) + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling bindnow >&2; fi + hardeningLDFlags+=('-z' 'now') + ;; + *) + # Ignore unsupported. Checked in Nix that at least *some* + # tool supports each flag. + ;; + esac + fi + done +fi diff --git a/pkgs/build-support/binutils-wrapper/default.nix b/pkgs/build-support/binutils-wrapper/default.nix new file mode 100644 index 00000000000..e885078c3de --- /dev/null +++ b/pkgs/build-support/binutils-wrapper/default.nix @@ -0,0 +1,288 @@ +# The Nixpkgs CC is not directly usable, since it doesn't know where +# the C library and standard header files are. Therefore the compiler +# produced by that package cannot be installed directly in a user +# environment and used from the command line. So we use a wrapper +# script that sets up the right environment variables so that the +# compiler and the linker just "work". + +{ name ? "", stdenv, nativeTools, noLibc ? false, nativeLibc, nativePrefix ? "" +, binutils ? null, libc ? null +, coreutils ? null, shell ? stdenv.shell, gnugrep ? null +, extraPackages ? [], extraBuildCommands ? "" +, buildPackages ? {} +, useMacosReexportHack ? false +}: + +with stdenv.lib; + +assert nativeTools -> nativePrefix != ""; +assert !nativeTools -> + binutils != null && coreutils != null && gnugrep != null; +assert !(nativeLibc && noLibc); +assert (noLibc || nativeLibc) == (libc == null); + +let + inherit (stdenv) hostPlatform targetPlatform; + + # Prefix for binaries. Customarily ends with a dash separator. + # + # TODO(@Ericson2314) Make unconditional, or optional but always true by + # default. + prefix = stdenv.lib.optionalString (targetPlatform != hostPlatform) + (targetPlatform.config + "-"); + + binutilsVersion = (builtins.parseDrvName binutils.name).version; + binutilsName = (builtins.parseDrvName binutils.name).name; + + libc_bin = if libc == null then null else getBin libc; + libc_dev = if libc == null then null else getDev libc; + libc_lib = if libc == null then null else getLib libc; + binutils_bin = if nativeTools then "" else getBin binutils; + # The wrapper scripts use 'cat' and 'grep', so we may need coreutils. + coreutils_bin = if nativeTools then "" else getBin coreutils; + + dashlessTarget = stdenv.lib.replaceStrings ["-"] ["_"] targetPlatform.config; + + # See description in cc-wrapper. + infixSalt = dashlessTarget; + + # The dynamic linker has different names on different platforms. This is a + # shell glob that ought to match it. + dynamicLinker = + /**/ if libc == null then null + else if targetPlatform.system == "i686-linux" then "${libc_lib}/lib/ld-linux.so.2" + else if targetPlatform.system == "x86_64-linux" then "${libc_lib}/lib/ld-linux-x86-64.so.2" + # ARM with a wildcard, which can be "" or "-armhf". + else if targetPlatform.isArm then "${libc_lib}/lib/ld-linux*.so.3" + else if targetPlatform.system == "aarch64-linux" then "${libc_lib}/lib/ld-linux-aarch64.so.1" + else if targetPlatform.system == "powerpc-linux" then "${libc_lib}/lib/ld.so.1" + else if targetPlatform.system == "mips64el-linux" then "${libc_lib}/lib/ld.so.1" + else if targetPlatform.system == "x86_64-darwin" then "/usr/lib/dyld" + else if stdenv.lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1" + else null; + + expand-response-params = + if buildPackages.stdenv.cc or null != null && buildPackages.stdenv.cc != "/dev/null" + then import ../expand-response-params { inherit (buildPackages) stdenv; } + else ""; + +in + +stdenv.mkDerivation { + name = prefix + + (if name != "" then name else "${binutilsName}-wrapper") + + (stdenv.lib.optionalString (binutils != null && binutilsVersion != "") "-${binutilsVersion}"); + + preferLocalBuild = true; + + inherit binutils_bin shell libc_bin libc_dev libc_lib coreutils_bin; + gnugrep_bin = if nativeTools then "" else gnugrep; + + binPrefix = prefix; + inherit infixSalt; + + outputs = [ "out" "man" ]; + + passthru = { + inherit libc nativeTools nativeLibc nativePrefix prefix; + + emacsBufferSetup = pkgs: '' + ; We should handle propagation here too + (mapc + (lambda (arg) + (when (file-directory-p (concat arg "/lib")) + (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib"))) + (when (file-directory-p (concat arg "/lib64")) + (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib64")))) + '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)})) + ''; + }; + + dontBuild = true; + dontConfigure = true; + + unpackPhase = '' + src=$PWD + ''; + + installPhase = + '' + set -u + + mkdir -p $out/bin $out/nix-support $man/nix-support + + wrap() { + local dst="$1" + local wrapper="$2" + export prog="$3" + set +u + substituteAll "$wrapper" "$out/bin/$dst" + set -u + chmod +x "$out/bin/$dst" + } + '' + + + (if nativeTools then '' + echo ${nativePrefix} > $out/nix-support/orig-binutils + + ldPath="${nativePrefix}/bin" + '' else '' + echo $binutils_bin > $out/nix-support/orig-binutils + + ldPath="${binutils_bin}/bin" + '' + + + optionalString (targetPlatform.isSunOS && nativePrefix != "") '' + # Solaris needs an additional ld wrapper. + ldPath="${nativePrefix}/bin" + exec="$ldPath/${prefix}ld" + wrap ld-solaris ${./ld-solaris-wrapper.sh} + '') + + + '' + # Create a symlink to as (the assembler). + if [ -e $ldPath/${prefix}as ]; then + ln -s $ldPath/${prefix}as $out/bin/${prefix}as + fi + + '' + (if !useMacosReexportHack then '' + wrap ${prefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${prefix}ld} + '' else '' + ldInner="${prefix}ld-reexport-delegate" + wrap "$ldInner" ${./macos-sierra-reexport-hack.bash} ''${ld:-$ldPath/${prefix}ld} + wrap "${prefix}ld" ${./ld-wrapper.sh} "$out/bin/$ldInner" + unset ldInner + '') + '' + + if [ -e ${binutils_bin}/bin/${prefix}ld.gold ]; then + wrap ${prefix}ld.gold ${./ld-wrapper.sh} ${binutils_bin}/bin/${prefix}ld.gold + fi + + if [ -e ${binutils_bin}/bin/ld.bfd ]; then + wrap ${prefix}ld.bfd ${./ld-wrapper.sh} ${binutils_bin}/bin/${prefix}ld.bfd + fi + + set +u + ''; + + propagatedBuildInputs = extraPackages; + + setupHook = ./setup-hook.sh; + + postFixup = + '' + set -u + '' + + + optionalString (libc != null) ('' + ## + ## General libc support + ## + + echo "-L${libc_lib}/lib" > $out/nix-support/libc-ldflags + + echo "${libc_lib}" > $out/nix-support/orig-libc + echo "${libc_dev}" > $out/nix-support/orig-libc-dev + + ## + ## Dynamic linker support + ## + + if [[ -z ''${dynamicLinker+x} ]]; then + echo "Don't know the name of the dynamic linker for platform '${targetPlatform.config}', so guessing instead." >&2 + local dynamicLinker="${libc_lib}/lib/ld*.so.?" + fi + + # Expand globs to fill array of options + dynamicLinker=($dynamicLinker) + + case ''${#dynamicLinker[@]} in + 0) echo "No dynamic linker found for platform '${targetPlatform.config}'." >&2;; + 1) echo "Using dynamic linker: '$dynamicLinker'" >&2;; + *) echo "Multiple dynamic linkers found for platform '${targetPlatform.config}'." >&2;; + esac + + if [ -n "$dynamicLinker" ]; then + echo $dynamicLinker > $out/nix-support/dynamic-linker + + '' + (if targetPlatform.isDarwin then '' + printf "export LD_DYLD_PATH=%q\n" "$dynamicLinker" >> $out/nix-support/setup-hook + '' else '' + if [ -e ${libc_lib}/lib/32/ld-linux.so.2 ]; then + echo ${libc_lib}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32 + fi + + local ldflagsBefore=(-dynamic-linker "$dynamicLinker") + '') + '' + fi + + # The dynamic linker is passed in `ldflagsBefore' to allow + # explicit overrides of the dynamic linker by callers to ld + # (the *last* value counts, so ours should come first). + printWords "''${ldflagsBefore[@]}" > $out/nix-support/libc-ldflags-before + '') + + + optionalString (!nativeTools) '' + + ## + ## User env support + ## + + # Propagate the underling unwrapped binutils so that if you + # install the wrapper, you get tools like objdump, the manpages, + # etc. as well (same for any binaries of libc). + printWords ${binutils_bin} ${if libc == null then "" else libc_bin} > $out/nix-support/propagated-user-env-packages + '' + + + '' + + ## + ## Hardening support + ## + + # some linkers on some platforms don't support specific -z flags + export hardening_unsupported_flags="" + if [[ "$($ldPath/${prefix}ld -z now 2>&1 || true)" =~ un(recognized|known)\ option ]]; then + hardening_unsupported_flags+=" bindnow" + fi + if [[ "$($ldPath/${prefix}ld -z relro 2>&1 || true)" =~ un(recognized|known)\ option ]]; then + hardening_unsupported_flags+=" relro" + fi + '' + + + optionalString hostPlatform.isCygwin '' + hardening_unsupported_flags+=" pic" + '' + + + '' + set +u + substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh + substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh + substituteAll ${../cc-wrapper/utils.sh} $out/nix-support/utils.sh + + ## + ## Extra custom steps + ## + + '' + + extraBuildCommands; + + inherit dynamicLinker expand-response-params; + + # for substitution in utils.sh + expandResponseParams = "${expand-response-params}/bin/expand-response-params"; + + crossAttrs = { + shell = shell.crossDrv + shell.crossDrv.shellPath; + }; + + meta = + let binutils_ = if binutils != null then binutils else {}; in + (if binutils_ ? meta then removeAttrs binutils.meta ["priority"] else {}) // + { description = + stdenv.lib.attrByPath ["meta" "description"] "System binary utilities" binutils_ + + " (wrapper script)"; + } // optionalAttrs useMacosReexportHack { + platforms = stdenv.lib.platforms.darwin; + }; +} diff --git a/pkgs/build-support/cc-wrapper/ld-solaris-wrapper.sh b/pkgs/build-support/binutils-wrapper/ld-solaris-wrapper.sh old mode 100755 new mode 100644 similarity index 100% rename from pkgs/build-support/cc-wrapper/ld-solaris-wrapper.sh rename to pkgs/build-support/binutils-wrapper/ld-solaris-wrapper.sh diff --git a/pkgs/build-support/cc-wrapper/ld-wrapper.sh b/pkgs/build-support/binutils-wrapper/ld-wrapper.sh similarity index 98% rename from pkgs/build-support/cc-wrapper/ld-wrapper.sh rename to pkgs/build-support/binutils-wrapper/ld-wrapper.sh index 97e4e45decf..dd30c4d55ef 100644 --- a/pkgs/build-support/cc-wrapper/ld-wrapper.sh +++ b/pkgs/build-support/binutils-wrapper/ld-wrapper.sh @@ -12,7 +12,7 @@ fi source @out@/nix-support/utils.sh -if [ -z "${NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then +if [ -z "${NIX_BINUTILS_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then source @out@/nix-support/add-flags.sh fi diff --git a/pkgs/build-support/binutils-wrapper/setup-hook.sh b/pkgs/build-support/binutils-wrapper/setup-hook.sh new file mode 100644 index 00000000000..3395ddd3391 --- /dev/null +++ b/pkgs/build-support/binutils-wrapper/setup-hook.sh @@ -0,0 +1,63 @@ +# Binutils Wrapper hygiene +# +# See comments in cc-wrapper's setup hook. This works exactly the same way. + +binutilsWrapper_addLDVars () { + case $depOffset in + -1) local role='BUILD_' ;; + 0) local role='' ;; + 1) local role='TARGET_' ;; + *) echo "binutils-wrapper: Error: Cannot be used with $depOffset-offset deps, " >2; + return 1 ;; + esac + + if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then + export NIX_${role}LDFLAGS+=" -L$1/lib64" + fi + + if [[ -d "$1/lib" ]]; then + export NIX_${role}LDFLAGS+=" -L$1/lib" + fi +} + +if [ -n "${crossConfig:-}" ]; then + export NIX_BINUTILS_WRAPPER_@infixSalt@_TARGET_BUILD=1 + role="BUILD_" +else + export NIX_BINUTILS_WRAPPER_@infixSalt@_TARGET_HOST=1 + role="" +fi + +envHooks+=(binutilsWrapper_addLDVars) + +# shellcheck disable=SC2157 +if [ -n "@binutils_bin@" ]; then + addToSearchPath _PATH @binutils_bin@/bin +fi + +# shellcheck disable=SC2157 +if [ -n "@libc_bin@" ]; then + addToSearchPath _PATH @libc_bin@/bin +fi + +# shellcheck disable=SC2157 +if [ -n "@coreutils_bin@" ]; then + addToSearchPath _PATH @coreutils_bin@/bin +fi + +# Export tool environment variables so various build systems use the right ones. + +export NIX_${role}BINUTILS=@out@ + +for CMD in \ + ar as nm objcopy ranlib strip strings size ld windres +do + if + PATH=$_PATH type -p "@binPrefix@$CMD" > /dev/null + then + export "${role}$(echo "$CMD" | tr "[:lower:]" "[:upper:]")=@binPrefix@${CMD}"; + fi +done + +# No local scope in sourced file +unset role diff --git a/pkgs/build-support/cc-wrapper/add-flags.sh b/pkgs/build-support/cc-wrapper/add-flags.sh index 978041fb4d8..fb6e38302a5 100644 --- a/pkgs/build-support/cc-wrapper/add-flags.sh +++ b/pkgs/build-support/cc-wrapper/add-flags.sh @@ -10,15 +10,8 @@ var_templates_list=( NIX+CXXSTDLIB_COMPILE NIX+CXXSTDLIB_LINK NIX+GNATFLAGS_COMPILE - NIX+IGNORE_LD_THROUGH_GCC - NIX+LDFLAGS - NIX+LDFLAGS_BEFORE - NIX+LDFLAGS_AFTER ) - var_templates_bool=( - NIX+SET_BUILD_ID - NIX+DONT_SET_RPATH NIX+ENFORCE_NO_NATIVE ) @@ -62,17 +55,13 @@ if [ -e @out@/nix-support/gnat-cflags ]; then NIX_@infixSalt@_GNATFLAGS_COMPILE="$(< @out@/nix-support/gnat-cflags) $NIX_@infixSalt@_GNATFLAGS_COMPILE" fi -if [ -e @out@/nix-support/libc-ldflags ]; then - NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/libc-ldflags)" -fi - if [ -e @out@/nix-support/cc-ldflags ]; then + # We don't import this above, but just tack this on know. binutils-wrapper's + # add-flags will not clobber it. + # + # TODO(@Ericson2314): Consider `NIX_@infixSalt@_CFLAGS_LINK` instead NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/cc-ldflags)" fi -if [ -e @out@/nix-support/libc-ldflags-before ]; then - NIX_@infixSalt@_LDFLAGS_BEFORE="$(< @out@/nix-support/libc-ldflags-before) $NIX_@infixSalt@_LDFLAGS_BEFORE" -fi - # That way forked processes will not extend these environment variables again. export NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET=1 diff --git a/pkgs/build-support/cc-wrapper/add-hardening.sh b/pkgs/build-support/cc-wrapper/add-hardening.sh index 34358e04194..3983e866ee1 100644 --- a/pkgs/build-support/cc-wrapper/add-hardening.sh +++ b/pkgs/build-support/cc-wrapper/add-hardening.sh @@ -6,7 +6,6 @@ if [[ -v hardeningEnable[@] ]]; then hardeningFlags+=(${hardeningEnable[@]}) fi hardeningCFlags=() -hardeningLDFlags=() declare -A hardeningDisableMap @@ -44,7 +43,6 @@ if [[ -z "${hardeningDisableMap[all]:-}" ]]; then if [[ ! ("$*" =~ " -shared " || "$*" =~ " -static ") ]]; then if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling LDFlags -pie >&2; fi hardeningCFlags+=('-pie') - hardeningLDFlags+=('-pie') fi ;; pic) @@ -59,14 +57,6 @@ if [[ -z "${hardeningDisableMap[all]:-}" ]]; then if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling format >&2; fi hardeningCFlags+=('-Wformat' '-Wformat-security' '-Werror=format-security') ;; - relro) - if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling relro >&2; fi - hardeningLDFlags+=('-z' 'relro') - ;; - bindnow) - if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling bindnow >&2; fi - hardeningLDFlags+=('-z' 'now') - ;; *) # Ignore unsupported. Checked in Nix that at least *some* # tool supports each flag. diff --git a/pkgs/build-support/cc-wrapper/cc-wrapper.sh b/pkgs/build-support/cc-wrapper/cc-wrapper.sh index 3a471c293cc..524e5309847 100644 --- a/pkgs/build-support/cc-wrapper/cc-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/cc-wrapper.sh @@ -13,6 +13,12 @@ fi source @out@/nix-support/utils.sh +# Flirting with a layer violation here. +if [ -z "${NIX_BINUTILS_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then + source @binutils@/nix-support/add-flags.sh +fi + +# Put this one second so libc ldflags take priority. if [ -z "${NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then source @out@/nix-support/add-flags.sh fi diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index 0114170b8eb..c9820c27ea5 100644 --- a/pkgs/build-support/cc-wrapper/default.nix +++ b/pkgs/build-support/cc-wrapper/default.nix @@ -11,7 +11,7 @@ , isGNU ? false, isClang ? cc.isClang or false, gnugrep ? null , buildPackages ? {} , useMacosReexportHack ? false -}: +} @ args: with stdenv.lib; @@ -21,14 +21,23 @@ assert !nativeTools -> assert !(nativeLibc && noLibc); assert (noLibc || nativeLibc) == (libc == null); -assert stdenv.targetPlatform != stdenv.hostPlatform -> runCommand != null; - # For ghdl (the vhdl language provider to gcc) we need zlib in the wrapper. assert cc.langVhdl or false -> zlib != null; let inherit (stdenv) hostPlatform targetPlatform; + binutils = import ../binutils-wrapper { + inherit (args) binutils; + inherit # name + stdenv nativeTools noLibc nativeLibc nativePrefix + libc + coreutils shell gnugrep + extraPackages extraBuildCommands + buildPackages + useMacosReexportHack; + }; + # Prefix for binaries. Customarily ends with a dash separator. # # TODO(@Ericson2314) Make unconditional, or optional but always true by @@ -43,7 +52,6 @@ let libc_dev = if libc == null then null else getDev libc; libc_lib = if libc == null then null else getLib libc; cc_solib = getLib cc; - binutils_bin = if nativeTools then "" else getBin binutils; # The wrapper scripts use 'cat' and 'grep', so we may need coreutils. coreutils_bin = if nativeTools then "" else getBin coreutils; @@ -59,21 +67,6 @@ let # unstable implementation detail, however. infixSalt = dashlessTarget; - # The dynamic linker has different names on different platforms. This is a - # shell glob that ought to match it. - dynamicLinker = - /**/ if libc == null then null - else if targetPlatform.system == "i686-linux" then "${libc_lib}/lib/ld-linux.so.2" - else if targetPlatform.system == "x86_64-linux" then "${libc_lib}/lib/ld-linux-x86-64.so.2" - # ARM with a wildcard, which can be "" or "-armhf". - else if targetPlatform.isArm then "${libc_lib}/lib/ld-linux*.so.3" - else if targetPlatform.system == "aarch64-linux" then "${libc_lib}/lib/ld-linux-aarch64.so.1" - else if targetPlatform.system == "powerpc-linux" then "${libc_lib}/lib/ld.so.1" - else if targetPlatform.system == "mips64el-linux" then "${libc_lib}/lib/ld.so.1" - else if targetPlatform.system == "x86_64-darwin" then "/usr/lib/dyld" - else if stdenv.lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1" - else null; - expand-response-params = if buildPackages.stdenv.cc or null != null && buildPackages.stdenv.cc != "/dev/null" then import ../expand-response-params { inherit (buildPackages) stdenv; } @@ -88,7 +81,7 @@ stdenv.mkDerivation { preferLocalBuild = true; - inherit cc shell libc_bin libc_dev libc_lib binutils_bin coreutils_bin; + inherit cc shell libc_bin libc_dev libc_lib binutils coreutils_bin; gnugrep_bin = if nativeTools then "" else gnugrep; binPrefix = prefix; @@ -102,13 +95,11 @@ stdenv.mkDerivation { emacsBufferSetup = pkgs: '' ; We should handle propagation here too - (mapc (lambda (arg) - (when (file-directory-p (concat arg "/include")) - (setenv "NIX_${infixSalt}_CFLAGS_COMPILE" (concat (getenv "NIX_${infixSalt}_CFLAGS_COMPILE") " -isystem " arg "/include"))) - (when (file-directory-p (concat arg "/lib")) - (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib"))) - (when (file-directory-p (concat arg "/lib64")) - (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib64")))) '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)})) + (mapc + (lambda (arg) + (when (file-directory-p (concat arg "/include")) + (setenv "NIX_${infixSalt}_CFLAGS_COMPILE" (concat (getenv "NIX_${infixSalt}_CFLAGS_COMPILE") " -isystem " arg "/include")))) + '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)})) ''; }; @@ -138,45 +129,18 @@ stdenv.mkDerivation { echo ${if targetPlatform.isDarwin then cc else nativePrefix} > $out/nix-support/orig-cc ccPath="${if targetPlatform.isDarwin then cc else nativePrefix}/bin" - ldPath="${nativePrefix}/bin" '' else '' echo $cc > $out/nix-support/orig-cc ccPath="${cc}/bin" - ldPath="${binutils_bin}/bin" - '' - - + optionalString (targetPlatform.isSunOS && nativePrefix != "") '' - # Solaris needs an additional ld wrapper. - ldPath="${nativePrefix}/bin" - exec="$ldPath/${prefix}ld" - wrap ld-solaris ${./ld-solaris-wrapper.sh} '') + '' - # Create a symlink to as (the assembler). This is useful when a - # cc-wrapper is installed in a user environment, as it ensures that - # the right assembler is called. - if [ -e $ldPath/${prefix}as ]; then - ln -s $ldPath/${prefix}as $out/bin/${prefix}as - fi - - '' + (if !useMacosReexportHack then '' - wrap ${prefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${prefix}ld} - '' else '' - ldInner="${prefix}ld-reexport-delegate" - wrap "$ldInner" ${./macos-sierra-reexport-hack.bash} ''${ld:-$ldPath/${prefix}ld} - wrap "${prefix}ld" ${./ld-wrapper.sh} "$out/bin/$ldInner" - unset ldInner - '') + '' - - if [ -e ${binutils_bin}/bin/${prefix}ld.gold ]; then - wrap ${prefix}ld.gold ${./ld-wrapper.sh} ${binutils_bin}/bin/${prefix}ld.gold - fi - - if [ -e ${binutils_bin}/bin/ld.bfd ]; then - wrap ${prefix}ld.bfd ${./ld-wrapper.sh} ${binutils_bin}/bin/${prefix}ld.bfd - fi + # Create symlinks to everything in the binutils wrapper. + for bbin in $binutils/bin/*; do + mkdir -p "$out/bin" + ln -s "$bbin" "$out/bin/$(basename $bbin)" + done # We export environment variables pointing to the wrapped nonstandard # cmds, lest some lousy configure script use those to guess compiler @@ -236,7 +200,7 @@ stdenv.mkDerivation { ln -s $ccPath/${prefix}ghdl $out/bin/${prefix}ghdl ''; - propagatedBuildInputs = extraPackages; + propagatedBuildInputs = [ binutils ] ++ extraPackages; setupHook = ./setup-hook.sh; @@ -245,7 +209,7 @@ stdenv.mkDerivation { set -u '' - + optionalString (libc != null) ('' + + optionalString (libc != null) '' ## ## General libc support ## @@ -263,48 +227,9 @@ stdenv.mkDerivation { # another -idirafter is necessary to add that directory again. echo "-B${libc_lib}/lib/ -idirafter ${libc_dev}/include -idirafter ${cc}/lib/gcc/*/*/include-fixed" > $out/nix-support/libc-cflags - echo "-L${libc_lib}/lib" > $out/nix-support/libc-ldflags - echo "${libc_lib}" > $out/nix-support/orig-libc echo "${libc_dev}" > $out/nix-support/orig-libc-dev - - ## - ## Dynamic linker support - ## - - if [[ -z ''${dynamicLinker+x} ]]; then - echo "Don't know the name of the dynamic linker for platform '${targetPlatform.config}', so guessing instead." >&2 - local dynamicLinker="${libc_lib}/lib/ld*.so.?" - fi - - # Expand globs to fill array of options - dynamicLinker=($dynamicLinker) - - case ''${#dynamicLinker[@]} in - 0) echo "No dynamic linker found for platform '${targetPlatform.config}'." >&2;; - 1) echo "Using dynamic linker: '$dynamicLinker'" >&2;; - *) echo "Multiple dynamic linkers found for platform '${targetPlatform.config}'." >&2;; - esac - - if [ -n "$dynamicLinker" ]; then - echo $dynamicLinker > $out/nix-support/dynamic-linker - - '' + (if targetPlatform.isDarwin then '' - printf "export LD_DYLD_PATH=%q\n" "$dynamicLinker" >> $out/nix-support/setup-hook - '' else '' - if [ -e ${libc_lib}/lib/32/ld-linux.so.2 ]; then - echo ${libc_lib}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32 - fi - - local ldflagsBefore=(-dynamic-linker "$dynamicLinker") - '') + '' - fi - - # The dynamic linker is passed in `ldflagsBefore' to allow - # explicit overrides of the dynamic linker by callers to gcc/ld - # (the *last* value counts, so ours should come first). - printWords "''${ldflagsBefore[@]}" > $out/nix-support/libc-ldflags-before - '') + '' + optionalString (!nativeTools) '' @@ -345,7 +270,6 @@ stdenv.mkDerivation { # Propagate the wrapped cc so that if you install the wrapper, # you get tools like gcov, the manpages, etc. as well (including # for binutils and Glibc). - printWords ${cc} ${binutils_bin} ${if libc == null then "" else libc_bin} > $out/nix-support/propagated-user-env-packages printWords ${cc.man or ""} > $man/nix-support/propagated-user-env-packages '' @@ -355,14 +279,7 @@ stdenv.mkDerivation { ## Hardening support ## - # some linkers on some platforms don't support specific -z flags export hardening_unsupported_flags="" - if [[ "$($ldPath/${prefix}ld -z now 2>&1 || true)" =~ un(recognized|known)\ option ]]; then - hardening_unsupported_flags+=" bindnow" - fi - if [[ "$($ldPath/${prefix}ld -z relro 2>&1 || true)" =~ un(recognized|known)\ option ]]; then - hardening_unsupported_flags+=" relro" - fi '' + optionalString hostPlatform.isCygwin '' @@ -381,7 +298,7 @@ stdenv.mkDerivation { '' + extraBuildCommands; - inherit dynamicLinker expand-response-params; + inherit expand-response-params; # for substitution in utils.sh expandResponseParams = "${expand-response-params}/bin/expand-response-params"; @@ -396,7 +313,5 @@ stdenv.mkDerivation { { description = stdenv.lib.attrByPath ["meta" "description"] "System C compiler" cc_ + " (wrapper script)"; - } // optionalAttrs useMacosReexportHack { - platforms = stdenv.lib.platforms.darwin; }; } diff --git a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash deleted file mode 100644 index b7aa7ea5c09..00000000000 --- a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash +++ /dev/null @@ -1,106 +0,0 @@ -#! @shell@ - -set -eu -o pipefail - -path_backup="$PATH" -if [ -n "@coreutils_bin@" ]; then - PATH="@coreutils_bin@/bin" -fi - -declare -r recurThreshold=300 - -declare overflowCount=0 -for ((n=0; n < $#; ++n)); do - case "${!n}" in - -l*) let overflowCount+=1 ;; - -reexport-l*) let overflowCount+=1 ;; - *) ;; - esac -done - -declare -a allArgs=() - -if (( "$overflowCount" <= "$recurThreshold" )); then - allArgs=("$@") -else - declare -a childrenLookup=() childrenLink=() - - while (( $# )); do - case "$1" in - -L/*) - childrenLookup+=("$1") - allArgs+=("$1") - ;; - -L) - echo "cctools LD does not support '-L foo' or '-l foo'" >&2 - exit 1 - ;; - -l) - echo "cctools LD does not support '-L foo' or '-l foo'" >&2 - exit 1 - ;; - -lazy_library | -lazy_framework | -lto_library) - # We aren't linking any "azy_library", "to_library", etc. - allArgs+=("$1") - ;; - -lazy-l | -weak-l) allArgs+=("$1") ;; - # We can't so easily prevent header issues from these. - -lSystem) allArgs+=("$1") ;; - # Special case as indirection seems like a bad idea for something - # so fundamental. Can be removed for simplicity. - -l?* | -reexport-l?*) childrenLink+=("$1") ;; - *) allArgs+=("$1") ;; - esac - - shift - done - - declare n=0 - while (( $n < "${#childrenLink[@]}" )); do - if [[ "${childrenLink[n]}" = -l* ]]; then - childrenLink[n]="-reexport${childrenLink[n]}" - fi - let ++n - done - unset n - - declare -r outputNameLibless=$(basename $( \ - if [[ -z "${outputName:+isUndefined}" ]]; then - echo unnamed - elif [[ "${outputName:0:3}" = lib ]]; then - echo "${outputName:3}" - else - echo "${outputName}" - fi)) - declare -ra children=("$outputNameLibless-reexport-delegate-0" \ - "$outputNameLibless-reexport-delegate-1") - - mkdir -p "$out/lib" - - PATH="$PATH:@out@/bin" - - symbolBloatObject=$outputNameLibless-symbol-hack.o - if [[ ! -e $symbolBloatObject ]]; then - printf '.private_extern _______child_hack_foo\nchild_hack_foo:\n' \ - | @binPrefix@as -- -o $symbolBloatObject - fi - - # first half of libs - @binPrefix@ld -macosx_version_min $MACOSX_DEPLOYMENT_TARGET -arch x86_64 -dylib \ - -o "$out/lib/lib${children[0]}.dylib" \ - -install_name "$out/lib/lib${children[0]}.dylib" \ - "${childrenLookup[@]}" "$symbolBloatObject" \ - "${childrenLink[@]:0:$((${#childrenLink[@]} / 2 ))}" - - # second half of libs - @binPrefix@ld -macosx_version_min $MACOSX_DEPLOYMENT_TARGET -arch x86_64 -dylib \ - -o "$out/lib/lib${children[1]}.dylib" \ - -install_name "$out/lib/lib${children[1]}.dylib" \ - "${childrenLookup[@]}" "$symbolBloatObject" \ - "${childrenLink[@]:$((${#childrenLink[@]} / 2 ))}" - - allArgs+=("-L$out/lib" "-l${children[0]}" "-l${children[1]}") -fi - -PATH="$path_backup" -exec @prog@ "${allArgs[@]}" diff --git a/pkgs/build-support/cc-wrapper/setup-hook.sh b/pkgs/build-support/cc-wrapper/setup-hook.sh index e43c1609edb..9273f50c667 100644 --- a/pkgs/build-support/cc-wrapper/setup-hook.sh +++ b/pkgs/build-support/cc-wrapper/setup-hook.sh @@ -74,14 +74,6 @@ ccWrapper_addCVars () { export NIX_${role}CFLAGS_COMPILE+=" ${ccIncludeFlag:--isystem} $1/include" fi - if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then - export NIX_${role}LDFLAGS+=" -L$1/lib64" - fi - - if [[ -d "$1/lib" ]]; then - export NIX_${role}LDFLAGS+=" -L$1/lib" - fi - if [[ -d "$1/Library/Frameworks" ]]; then export NIX_${role}CFLAGS_COMPILE+=" -F$1/Library/Frameworks" fi @@ -116,11 +108,6 @@ if [ -n "@cc@" ]; then addToSearchPath _PATH @cc@/bin fi -# shellcheck disable=SC2157 -if [ -n "@binutils_bin@" ]; then - addToSearchPath _PATH @binutils_bin@/bin -fi - # shellcheck disable=SC2157 if [ -n "@libc_bin@" ]; then addToSearchPath _PATH @libc_bin@/bin @@ -138,15 +125,5 @@ export NIX_${role}CC=@out@ export ${role}CC=@named_cc@ export ${role}CXX=@named_cxx@ -for CMD in \ - ar as nm objcopy ranlib strip strings size ld windres -do - if - PATH=$_PATH type -p "@binPrefix@$CMD" > /dev/null - then - export "${role}$(echo "$CMD" | tr "[:lower:]" "[:upper:]")=@binPrefix@${CMD}"; - fi -done - # No local scope in sourced file unset role