Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at devShellTools-shell 120 lines 5.1 kB view raw
1export NIX_SET_BUILD_ID=1 2export NIX_LDFLAGS+=" --compress-debug-sections=zlib" 3export NIX_CFLAGS_COMPILE+=" -ggdb -Wa,--compress-debug-sections" 4export NIX_RUSTFLAGS+=" -g -C strip=none" 5 6cksumAlgo=sha256 7 8fixupOutputHooks+=(_separateDebugInfo) 9postUnpackHooks+=(_recordPristineSourceHashes) 10 11_recordPristineSourceHashes() { 12 # shellcheck disable=2154 13 [ -e "$sourceRoot" ] || return 0 14 15 local checksumFileName=__nix_source_checksums 16 echo "separate-debug-info: recording checksum of source files for debug support..." 17 find "$sourceRoot" -type f -exec cksum -a "$cksumAlgo" '{}' \+ > "$checksumFileName" 18 recordedSourceChecksumsFileName="$(readlink -f "$checksumFileName")" 19} 20 21_separateDebugInfo() { 22 # shellcheck disable=2154 23 [ -e "$prefix" ] || return 0 24 25 local debugOutput="${debug:-$out}" 26 if [ "$prefix" = "$debugOutput" ]; then return 0; fi 27 28 # in case there is nothing to strip, don't fail the build 29 mkdir -p "$debugOutput" 30 31 local dst="$debugOutput/lib/debug/.build-id" 32 33 local source 34 local sourceOverlay 35 # shellcheck disable=2154 36 if [ -e "$src" ]; then 37 source="$src" 38 if [ -n "${recordedSourceChecksumsFileName:-}" ]; then 39 sourceOverlay="$debugOutput/src/overlay" 40 else 41 sourceOverlay="" 42 fi 43 else 44 source="" 45 sourceOverlay="" 46 fi 47 48 # Find executables and dynamic libraries. 49 local i 50 while IFS= read -r -d $'\0' i; do 51 if ! isELF "$i"; then continue; fi 52 53 [ -z "${READELF:-}" ] && echo "_separateDebugInfo: '\$READELF' variable is empty, skipping." 1>&2 && break 54 [ -z "${OBJCOPY:-}" ] && echo "_separateDebugInfo: '\$OBJCOPY' variable is empty, skipping." 1>&2 && break 55 56 # Extract the Build ID. FIXME: there's probably a cleaner way. 57 local id 58 id="$($READELF -n "$i" | sed 's/.*Build ID: \([0-9a-f]*\).*/\1/; t; d')" 59 if [ "${#id}" != 40 ]; then 60 echo "could not find build ID of $i, skipping" >&2 61 continue 62 fi 63 64 65 # Extract the debug info. 66 echo "separating debug info from $i (build ID $id)" 67 68 local debuginfoDir="$dst/${id:0:2}" 69 local buildIdPrefix="$debuginfoDir/${id:2}" 70 local debuginfoFile="$buildIdPrefix.debug" 71 local executableSymlink="$buildIdPrefix.executable" 72 local sourceSymlink="$buildIdPrefix.source" 73 local sourceOverlaySymlink="$buildIdPrefix.sourceoverlay" 74 75 mkdir -p "$debuginfoDir" 76 77 if [ -f "$debuginfoFile" ]; then 78 echo "separate-debug-info: warning: multiple files with build id $id found, overwriting" 79 fi 80 81 # This may fail, e.g. if the binary is for a different 82 # architecture than we're building for. (This happens with 83 # firmware blobs in QEMU.) 84 if $OBJCOPY --only-keep-debug "$i" "$debuginfoFile"; then 85 # If we succeeded, also a create a symlink <original-name>.debug. 86 ln -sfn "$debuginfoFile" "$dst/../$(basename "$i")" 87 # also create a symlink mapping the build-id to the original elf file and the source 88 # debuginfod protocol relies on it 89 ln -sfn "$i" "$executableSymlink" 90 if [ -n "$source" ]; then 91 ln -sfn "$source" "$sourceSymlink" 92 fi 93 if [ -n "$sourceOverlay" ]; then 94 # create it lazily 95 if [ ! -d "$sourceOverlay" ]; then 96 echo "separate-debug-info: copying patched source files to $sourceOverlay..." 97 mkdir -p "$sourceOverlay" 98 pushd "$(dirname "$recordedSourceChecksumsFileName")" || { echo "separate-debug-info: failed to cd parent directory of $recordedSourceChecksumsFileName"; return 1; } 99 while IFS= read -r -d $'\0' modifiedSourceFile; do 100 if [ -z "$modifiedSourceFile" ]; then 101 continue 102 fi 103 # this can happen with files with '\n' in their name 104 if [ ! -f "$modifiedSourceFile" ]; then 105 echo "separate-debug-info: cannot save modified source file $modifiedSourceFile: does not exist. ignoring" 106 continue 107 fi 108 mkdir -p "$sourceOverlay/$(dirname "$modifiedSourceFile")" 109 cp -v "$modifiedSourceFile" "$sourceOverlay/$modifiedSourceFile" 110 done < <(LANG=C cksum -a "$cksumAlgo" --check --ignore-missing --quiet "$recordedSourceChecksumsFileName" 2>&1 | sed -n -e 's/: FAILED$/\x00/p' | sed -z -e 's/^\n//') 111 popd || { echo "separate-debug-info: failed to popd" ; return 1; } 112 fi 113 ln -sfn "$sourceOverlay" "$sourceOverlaySymlink" 114 fi 115 else 116 # If we failed, try to clean up unnecessary directories 117 rmdir -p "$dst/${id:0:2}" --ignore-fail-on-non-empty 118 fi 119 done < <(find "$prefix" -type f -print0 | sort -z) 120}