mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-11-05 12:47:43 +00:00
111 lines
5.6 KiB
Nix
111 lines
5.6 KiB
Nix
{ pkgs, compiler }:
|
|
assert pkgs.stdenv.hostPlatform.isLinux && pkgs.stdenv.hostPlatform.isx86_64;
|
|
let
|
|
source = pkgs.applyPatches {
|
|
name = "ghc914-rts-single-function-comdat";
|
|
src = compiler.configured-src + "/rts";
|
|
patches = [ ./ghc914-rts-elf-comdat-functions.patch ];
|
|
};
|
|
in pkgs.runCommandCC "ghc914-elf-comdat-functions-check" {} ''
|
|
set -euo pipefail
|
|
mkdir -p "$out"
|
|
includes=()
|
|
for package in rts rts-headers rts-fs libffi-clib; do
|
|
${compiler}/bin/ghc-pkg field "$package" include-dirs --simple-output \
|
|
> "$out/$package-include-dirs.txt"
|
|
for dir in $(cat "$out/$package-include-dirs.txt"); do
|
|
includes+=("-I$dir")
|
|
done
|
|
done
|
|
# Use one consistent set of private headers; installed copies also carry
|
|
# pragma-once headers which must not be included as distinct source files.
|
|
# The upstream RTS uses GNU C extensions. The fixture itself is assembly.
|
|
for variant in baseline patched; do
|
|
if [ "$variant" = baseline ]; then tree=${compiler.configured-src}/rts; else tree=${source}; fi
|
|
mkdir -p "$out/$variant-objects"
|
|
for file in linker/Elf.c Linker.c; do
|
|
object=$(basename "$file" .c)
|
|
$CC -std=gnu11 -Werror=vla -pedantic -Wall -Wextra -O2 -fPIC \
|
|
-mno-avx -mno-avx2 -DCOMPILING_RTS -DINTERNAL_LIBFFI -DFS_NAMESPACE=rts \
|
|
-iquote "$tree" -iquote "$tree/linker" \
|
|
"''${includes[@]}" -I"$tree" \
|
|
-c "$tree/$file" -o "$out/$variant-objects/$object.o" \
|
|
2>&1 | tee "$out/$variant-$object-compile.log"
|
|
done
|
|
done
|
|
cp ${./elf-comdat/Probe.hs} Probe.hs
|
|
for variant in baseline patched; do
|
|
${compiler}/bin/ghc -ignore-dot-ghci -package ghci -j1 -O0 Probe.hs \
|
|
"$out/$variant-objects/Elf.o" "$out/$variant-objects/Linker.o" \
|
|
-o "$out/$variant" -optl-Wl,-Map="$out/$variant.map"
|
|
if grep -E '\.a\((Elf|Linker)\.o\)' "$out/$variant.map"; then
|
|
echo 'Original RTS linker object was unexpectedly extracted' >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
for variant in a b; do
|
|
if [ "$variant" = a ]; then value=17; addend=100; else value=29; addend=200; fi
|
|
common=(-DPROBE_VALUE=$value -DPROBE_READER=reader_$variant -DPROBE_ADDEND=$addend -DPROBE_EXTRA=extra_$variant)
|
|
for kind in comdat zero-size zero-local-label zero-extra-function zero-extra-object zero-extra-global zero-extra-weak partial strong plain-group different-signature weak; do
|
|
flags=(-DGROUP_SIGNATURE=comdat_function)
|
|
case "$kind" in
|
|
zero-size) flags+=(-DZERO_SIZE_FUNCTION) ;;
|
|
zero-local-label) flags+=(-DZERO_SIZE_FUNCTION -DEXTRA_LOCAL_LABEL) ;;
|
|
zero-extra-function) flags+=(-DZERO_SIZE_FUNCTION -DEXTRA_FUNCTION) ;;
|
|
zero-extra-object) flags+=(-DZERO_SIZE_FUNCTION -DEXTRA_OBJECT) ;;
|
|
zero-extra-global) flags+=(-DZERO_SIZE_FUNCTION -DEXTRA_GLOBAL) ;;
|
|
zero-extra-weak) flags+=(-DZERO_SIZE_FUNCTION -DEXTRA_WEAK) ;;
|
|
partial) flags+=(-DPARTIAL_FUNCTION) ;;
|
|
strong) flags+=(-DNO_GROUP) ;;
|
|
plain-group) flags+=(-DPLAIN_GROUP) ;;
|
|
different-signature) flags=(-DGROUP_SIGNATURE=other_signature -DOTHER_SIGNATURE) ;;
|
|
weak) flags+=(-DNO_GROUP -DWEAK_FUNCTION) ;;
|
|
esac
|
|
$CC -c "''${common[@]}" "''${flags[@]}" ${./elf-comdat/fixture.S} \
|
|
-o "$out/$kind-$variant.o"
|
|
done
|
|
$AR rc "$out/comdat-$variant.a" "$out/comdat-$variant.o"
|
|
done
|
|
$CC -c -DNO_GROUP -DGROUP_SIGNATURE=comdat_function \
|
|
-DPROBE_VALUE=41 -DPROBE_READER=reader_strong -DPROBE_ADDEND=300 \
|
|
${./elf-comdat/fixture.S} -o "$out/strong-third.o"
|
|
expect_failure() {
|
|
name=$1; shift
|
|
status=0
|
|
timeout 15s "$@" > "$out/$name.log" 2>&1 || status=$?
|
|
if [ "$status" -ne 1 ]; then
|
|
echo "Expected ordinary failure for $name, got status $status" >&2
|
|
exit 1
|
|
fi
|
|
grep -F 'duplicate definition for symbol' "$out/$name.log"
|
|
grep -F 'comdat_function' "$out/$name.log"
|
|
}
|
|
expect_failure baseline-comdat "$out/baseline" "$out/comdat-a.o" "$out/comdat-b.o"
|
|
expect_failure baseline-zero-size "$out/baseline" "$out/zero-size-a.o" "$out/zero-size-b.o"
|
|
timeout 15s "$out/patched" "$out/comdat-a.o" "$out/comdat-b.o" | tee "$out/comdat.txt"
|
|
grep -Fx '[17,117,217]' "$out/comdat.txt"
|
|
timeout 15s "$out/patched" "$out/comdat-b.o" "$out/comdat-a.o" | tee "$out/comdat-reversed.txt"
|
|
grep -Fx '[29,129,229]' "$out/comdat-reversed.txt"
|
|
for kind in zero-size zero-local-label zero-mixed; do
|
|
if [ "$kind" = zero-mixed ]; then first=zero-size; second=comdat; else first=$kind; second=$kind; fi
|
|
timeout 15s "$out/patched" "$out/$first-a.o" "$out/$second-b.o" | tee "$out/$kind.txt"
|
|
grep -Fx '[17,117,217]' "$out/$kind.txt"
|
|
timeout 15s "$out/patched" "$out/$second-b.o" "$out/$first-a.o" | tee "$out/$kind-reversed.txt"
|
|
grep -Fx '[29,129,229]' "$out/$kind-reversed.txt"
|
|
done
|
|
for executable in baseline patched; do
|
|
timeout 15s "$out/$executable" "$out/weak-a.o" "$out/weak-b.o" | tee "$out/$executable-weak.txt"
|
|
grep -Fx '[17,117,217]' "$out/$executable-weak.txt"
|
|
done
|
|
for kind in strong plain-group partial zero-extra-function zero-extra-object zero-extra-global zero-extra-weak; do
|
|
expect_failure "$kind" "$out/patched" "$out/$kind-a.o" "$out/$kind-b.o"
|
|
done
|
|
expect_failure different-signature "$out/patched" "$out/different-signature-a.o" "$out/comdat-b.o"
|
|
expect_failure mixed-comdat-first "$out/patched" "$out/comdat-a.o" "$out/strong-b.o"
|
|
expect_failure mixed-strong-first "$out/patched" "$out/strong-a.o" "$out/comdat-b.o"
|
|
expect_failure archive-owner-change "$out/patched" --archive-conflict \
|
|
"$out/comdat-a.a" "$out/comdat-b.a" "$out/strong-third.o"
|
|
printf '%s\n' 'PASS: scoped COMDAT coalescing preserves relocations and strong conflicts' \
|
|
| tee "$out/result.txt"
|
|
''
|