|
| 1 | +#! @shell@ |
| 2 | +# This file is copied from nixpkgs with additional handling of `-flavor` prefix. |
| 3 | +# See: https://github.com/NixOS/nixpkgs/blob/fa016524af1414fd5e0d9f3de43b6377486601bf/pkgs/build-support/bintools-wrapper/ld-wrapper.sh |
| 4 | +set -eu -o pipefail +o posix |
| 5 | +shopt -s nullglob |
| 6 | + |
| 7 | +if (( "${NIX_DEBUG:-0}" >= 7 )); then |
| 8 | + set -x |
| 9 | +fi |
| 10 | + |
| 11 | +flavorParams=() |
| 12 | +if [[ $# -ge 2 && "$1" == -flavor ]]; then |
| 13 | + flavorParams=( "$1" "$2" ) |
| 14 | + shift 2 |
| 15 | +fi |
| 16 | + |
| 17 | +path_backup="$PATH" |
| 18 | + |
| 19 | +# phase separation makes this look useless |
| 20 | +# shellcheck disable=SC2157 |
| 21 | +if [ -n "@coreutils_bin@" ]; then |
| 22 | + PATH="@coreutils_bin@/bin" |
| 23 | +fi |
| 24 | + |
| 25 | +source @out@/nix-support/utils.bash |
| 26 | + |
| 27 | +if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then |
| 28 | + source @out@/nix-support/add-flags.sh |
| 29 | +fi |
| 30 | + |
| 31 | + |
| 32 | +# Optionally filter out paths not refering to the store. |
| 33 | +expandResponseParams "$@" |
| 34 | + |
| 35 | +# NIX_LINK_TYPE is set if ld has been called through our cc wrapper. We take |
| 36 | +# advantage of this to avoid both recalculating it, and also repeating other |
| 37 | +# processing cc wrapper has already done. |
| 38 | +if [[ -n "${NIX_LINK_TYPE_@suffixSalt@:-}" ]]; then |
| 39 | + linkType=$NIX_LINK_TYPE_@suffixSalt@ |
| 40 | +else |
| 41 | + linkType=$(checkLinkType "${params[@]}") |
| 42 | +fi |
| 43 | + |
| 44 | +if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}" |
| 45 | + && ( -z "$NIX_IGNORE_LD_THROUGH_GCC_@suffixSalt@" || -z "${NIX_LINK_TYPE_@suffixSalt@:-}" ) ]]; then |
| 46 | + rest=() |
| 47 | + nParams=${#params[@]} |
| 48 | + declare -i n=0 |
| 49 | + |
| 50 | + while (( "$n" < "$nParams" )); do |
| 51 | + p=${params[n]} |
| 52 | + p2=${params[n+1]:-} # handle `p` being last one |
| 53 | + if [ "${p:0:3}" = -L/ ] && badPath "${p:2}"; then |
| 54 | + skip "${p:2}" |
| 55 | + elif [ "$p" = -L ] && badPath "$p2"; then |
| 56 | + n+=1; skip "$p2" |
| 57 | + elif [ "$p" = -rpath ] && badPath "$p2"; then |
| 58 | + n+=1; skip "$p2" |
| 59 | + elif [ "$p" = -dynamic-linker ] && badPath "$p2"; then |
| 60 | + n+=1; skip "$p2" |
| 61 | + elif [ "$p" = -syslibroot ] && [ $p2 == // ]; then |
| 62 | + # When gcc is built on darwin --with-build-sysroot=/ |
| 63 | + # produces '-syslibroot //' linker flag. It's a no-op, |
| 64 | + # which does not introduce impurities. |
| 65 | + n+=1; skip "$p2" |
| 66 | + elif [ "${p:0:10}" = /LIBPATH:/ ] && badPath "${p:9}"; then |
| 67 | + reject "${p:9}" |
| 68 | + # We need to not match LINK.EXE-style flags like |
| 69 | + # /NOLOGO or /LIBPATH:/nix/store/foo |
| 70 | + elif [[ $p =~ ^/[^:]*/ ]] && badPath "$p"; then |
| 71 | + reject "$p" |
| 72 | + elif [ "${p:0:9}" = --sysroot ]; then |
| 73 | + # Our ld is not built with sysroot support (Can we fix that?) |
| 74 | + : |
| 75 | + else |
| 76 | + rest+=("$p") |
| 77 | + fi |
| 78 | + n+=1 |
| 79 | + done |
| 80 | + # Old bash empty array hack |
| 81 | + params=(${rest+"${rest[@]}"}) |
| 82 | +fi |
| 83 | + |
| 84 | + |
| 85 | +source @out@/nix-support/add-hardening.sh |
| 86 | + |
| 87 | +extraAfter=() |
| 88 | +extraBefore=("${flavorParams[@]}" ${hardeningLDFlags[@]+"${hardeningLDFlags[@]}"}) |
| 89 | + |
| 90 | +if [ -z "${NIX_LINK_TYPE_@suffixSalt@:-}" ]; then |
| 91 | + extraAfter+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_@suffixSalt@)) |
| 92 | + extraBefore+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_BEFORE_@suffixSalt@)) |
| 93 | + |
| 94 | + # By adding dynamic linker to extraBefore we allow the users set their |
| 95 | + # own dynamic linker as NIX_LD_FLAGS will override earlier set flags |
| 96 | + if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then |
| 97 | + extraBefore+=("-dynamic-linker" "$NIX_DYNAMIC_LINKER_@suffixSalt@") |
| 98 | + fi |
| 99 | +fi |
| 100 | + |
| 101 | +extraAfter+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_AFTER_@suffixSalt@)) |
| 102 | + |
| 103 | +# These flags *must not* be pulled up to -Wl, flags, so they can't go in |
| 104 | +# add-flags.sh. They must always be set, so must not be disabled by |
| 105 | +# NIX_LDFLAGS_SET. |
| 106 | +if [ -e @out@/nix-support/add-local-ldflags-before.sh ]; then |
| 107 | + source @out@/nix-support/add-local-ldflags-before.sh |
| 108 | +fi |
| 109 | + |
| 110 | + |
| 111 | +# Three tasks: |
| 112 | +# |
| 113 | +# 1. Find all -L... switches for rpath |
| 114 | +# |
| 115 | +# 2. Find relocatable flag for build id. |
| 116 | +# |
| 117 | +# 3. Choose 32-bit dynamic linker if needed |
| 118 | +declare -a libDirs |
| 119 | +declare -A libs |
| 120 | +declare -i relocatable=0 link32=0 |
| 121 | + |
| 122 | +linkerOutput="a.out" |
| 123 | + |
| 124 | +if |
| 125 | + [ "$NIX_DONT_SET_RPATH_@suffixSalt@" != 1 ] \ |
| 126 | + || [ "$NIX_SET_BUILD_ID_@suffixSalt@" = 1 ] \ |
| 127 | + || [ -e @out@/nix-support/dynamic-linker-m32 ] |
| 128 | +then |
| 129 | + prev= |
| 130 | + # Old bash thinks empty arrays are undefined, ugh. |
| 131 | + for p in \ |
| 132 | + ${extraBefore+"${extraBefore[@]}"} \ |
| 133 | + ${params+"${params[@]}"} \ |
| 134 | + ${extraAfter+"${extraAfter[@]}"} |
| 135 | + do |
| 136 | + case "$prev" in |
| 137 | + -L) |
| 138 | + libDirs+=("$p") |
| 139 | + ;; |
| 140 | + -l) |
| 141 | + libs["lib${p}.so"]=1 |
| 142 | + ;; |
| 143 | + -m) |
| 144 | + # Presumably only the last `-m` flag has any effect. |
| 145 | + case "$p" in |
| 146 | + elf_i386) link32=1;; |
| 147 | + *) link32=0;; |
| 148 | + esac |
| 149 | + ;; |
| 150 | + -dynamic-linker | -plugin) |
| 151 | + # Ignore this argument, or it will match *.so and be added to rpath. |
| 152 | + ;; |
| 153 | + *) |
| 154 | + case "$p" in |
| 155 | + -L/*) |
| 156 | + libDirs+=("${p:2}") |
| 157 | + ;; |
| 158 | + -l?*) |
| 159 | + libs["lib${p:2}.so"]=1 |
| 160 | + ;; |
| 161 | + "${NIX_STORE:-}"/*.so | "${NIX_STORE:-}"/*.so.*) |
| 162 | + # This is a direct reference to a shared library. |
| 163 | + libDirs+=("${p%/*}") |
| 164 | + libs["${p##*/}"]=1 |
| 165 | + ;; |
| 166 | + -r | --relocatable | -i) |
| 167 | + relocatable=1 |
| 168 | + esac |
| 169 | + ;; |
| 170 | + esac |
| 171 | + prev="$p" |
| 172 | + done |
| 173 | +fi |
| 174 | + |
| 175 | +# Determine linkerOutput |
| 176 | +prev= |
| 177 | +for p in \ |
| 178 | + ${extraBefore+"${extraBefore[@]}"} \ |
| 179 | + ${params+"${params[@]}"} \ |
| 180 | + ${extraAfter+"${extraAfter[@]}"} |
| 181 | +do |
| 182 | + case "$prev" in |
| 183 | + -o) |
| 184 | + # Informational for post-link-hook |
| 185 | + linkerOutput="$p" |
| 186 | + ;; |
| 187 | + *) |
| 188 | + ;; |
| 189 | + esac |
| 190 | + prev="$p" |
| 191 | +done |
| 192 | + |
| 193 | +if [[ "$link32" == "1" && "$linkType" == dynamic && -e "@out@/nix-support/dynamic-linker-m32" ]]; then |
| 194 | + # We have an alternate 32-bit linker and we're producing a 32-bit ELF, let's |
| 195 | + # use it. |
| 196 | + extraAfter+=( |
| 197 | + '-dynamic-linker' |
| 198 | + "$(< @out@/nix-support/dynamic-linker-m32)" |
| 199 | + ) |
| 200 | +fi |
| 201 | + |
| 202 | +# Add all used dynamic libraries to the rpath. |
| 203 | +if [[ "$NIX_DONT_SET_RPATH_@suffixSalt@" != 1 && "$linkType" != static-pie ]]; then |
| 204 | + # For each directory in the library search path (-L...), |
| 205 | + # see if it contains a dynamic library used by a -l... flag. If |
| 206 | + # so, add the directory to the rpath. |
| 207 | + # It's important to add the rpath in the order of -L..., so |
| 208 | + # the link time chosen objects will be those of runtime linking. |
| 209 | + declare -A rpaths |
| 210 | + for dir in ${libDirs+"${libDirs[@]}"}; do |
| 211 | + if [[ "$dir" =~ [/.][/.] ]] && dir2=$(readlink -f "$dir"); then |
| 212 | + dir="$dir2" |
| 213 | + fi |
| 214 | + if [ -n "${rpaths[$dir]:-}" ] || [[ "$dir" != "${NIX_STORE:-}"/* ]]; then |
| 215 | + # If the path is not in the store, don't add it to the rpath. |
| 216 | + # This typically happens for libraries in /tmp that are later |
| 217 | + # copied to $out/lib. If not, we're screwed. |
| 218 | + continue |
| 219 | + fi |
| 220 | + for path in "$dir"/*; do |
| 221 | + file="${path##*/}" |
| 222 | + if [ "${libs[$file]:-}" ]; then |
| 223 | + # This library may have been provided by a previous directory, |
| 224 | + # but if that library file is inside an output of the current |
| 225 | + # derivation, it can be deleted after this compilation and |
| 226 | + # should be found in a later directory, so we add all |
| 227 | + # directories that contain any of the libraries to rpath. |
| 228 | + rpaths["$dir"]=1 |
| 229 | + extraAfter+=(-rpath "$dir") |
| 230 | + break |
| 231 | + fi |
| 232 | + done |
| 233 | + done |
| 234 | + |
| 235 | +fi |
| 236 | + |
| 237 | +# This is outside the DONT_SET_RPATH branch because it's more targeted and we |
| 238 | +# usually want it (on Darwin) even if DONT_SET_RPATH is set. |
| 239 | +if [ -n "${NIX_COREFOUNDATION_RPATH:-}" ]; then |
| 240 | + extraAfter+=(-rpath $NIX_COREFOUNDATION_RPATH) |
| 241 | +fi |
| 242 | + |
| 243 | +# Only add --build-id if this is a final link. FIXME: should build gcc |
| 244 | +# with --enable-linker-build-id instead? |
| 245 | +# |
| 246 | +# Note: `lld` interprets `--build-id` to mean `--build-id=fast`; GNU ld defaults |
| 247 | +# to SHA1. |
| 248 | +if [ "$NIX_SET_BUILD_ID_@suffixSalt@" = 1 ] && ! (( "$relocatable" )); then |
| 249 | + extraAfter+=(--build-id="${NIX_BUILD_ID_STYLE:-sha1}") |
| 250 | +fi |
| 251 | + |
| 252 | + |
| 253 | +# Optionally print debug info. |
| 254 | +if (( "${NIX_DEBUG:-0}" >= 1 )); then |
| 255 | + # Old bash workaround, see above. |
| 256 | + echo "extra flags before to @prog@:" >&2 |
| 257 | + printf " %q\n" ${extraBefore+"${extraBefore[@]}"} >&2 |
| 258 | + echo "original flags to @prog@:" >&2 |
| 259 | + printf " %q\n" ${params+"${params[@]}"} >&2 |
| 260 | + echo "extra flags after to @prog@:" >&2 |
| 261 | + printf " %q\n" ${extraAfter+"${extraAfter[@]}"} >&2 |
| 262 | +fi |
| 263 | + |
| 264 | +PATH="$path_backup" |
| 265 | +# Old bash workaround, see above. |
| 266 | + |
| 267 | +if (( "${NIX_LD_USE_RESPONSE_FILE:-@use_response_file_by_default@}" >= 1 )); then |
| 268 | + @prog@ @<(printf "%q\n" \ |
| 269 | + ${extraBefore+"${extraBefore[@]}"} \ |
| 270 | + ${params+"${params[@]}"} \ |
| 271 | + ${extraAfter+"${extraAfter[@]}"}) |
| 272 | +else |
| 273 | + @prog@ \ |
| 274 | + ${extraBefore+"${extraBefore[@]}"} \ |
| 275 | + ${params+"${params[@]}"} \ |
| 276 | + ${extraAfter+"${extraAfter[@]}"} |
| 277 | +fi |
| 278 | + |
| 279 | +if [ -e "@out@/nix-support/post-link-hook" ]; then |
| 280 | + source @out@/nix-support/post-link-hook |
| 281 | +fi |
0 commit comments