Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
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}