diff options
Diffstat (limited to 'tests/tst-symbol-scope-runner.sh')
| -rwxr-xr-x | tests/tst-symbol-scope-runner.sh | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/tests/tst-symbol-scope-runner.sh b/tests/tst-symbol-scope-runner.sh new file mode 100755 index 0000000..8a4154e --- /dev/null +++ b/tests/tst-symbol-scope-runner.sh @@ -0,0 +1,276 @@ +#!/bin/sh +set -eu + +: "${CPU_AS:?}" "${CPU_LD:?}" "${CPU_RUN:?}" + +TMP=${TMPDIR:-/tmp}/libmcpu-symbol-scope-$$ +mkdir -p "$TMP/lib" +trap 'rm -rf "$TMP"' EXIT HUP INT TERM + +cat > "$TMP/main-import.s" <<'EOS' +.global _life +.extern foo +.text +_start_life: + LDI r64@0x00000, 40 + CALL foo + MOV r64@0x00018, r64@0x00000 + LDI r32@0x00030, 0 + EXIT r32@0x00030 +EOS + +cat > "$TMP/a.s" <<'EOS' +.global foo +.text +foo: + LDI r64@0x00008, 2 + IADD r64@0x00000, r64@0x00000, r64@0x00008 + RET +EOS + +cat > "$TMP/b.s" <<'EOS' +.global foo +.text +foo: + LDI r64@0x00008, 3 + IADD r64@0x00000, r64@0x00000, r64@0x00008 + RET +EOS + +"$CPU_AS" -o "$TMP/main-import.o" "$TMP/main-import.s" +"$CPU_AS" -o "$TMP/a.o" "$TMP/a.s" +"$CPU_AS" -o "$TMP/b.o" "$TMP/b.s" +"$CPU_LD" --shared --soname=liba.so.1 -o "$TMP/lib/liba.so.1.0.0" "$TMP/a.o" +"$CPU_LD" --shared --soname=libb.so.1 -o "$TMP/lib/libb.so.1.0.0" "$TMP/b.o" +ln -s liba.so.1.0.0 "$TMP/lib/liba.so.1" +ln -s liba.so.1 "$TMP/lib/liba.so" +ln -s libb.so.1.0.0 "$TMP/lib/libb.so.1" +ln -s libb.so.1 "$TMP/lib/libb.so" + +# Normal DT_NEEDED scope is breadth-first and left-to-right. For equal +# GLOBAL definitions the first direct dependency wins. +"$CPU_LD" --dynamic --stack-size=4096 --no-heap \ + -L"$TMP/lib" -la -lb -o "$TMP/main-ab" "$TMP/main-import.o" +[ "`"$CPU_RUN" --library-path="$TMP/lib" --int-reg=r64@0x00018 "$TMP/main-ab"`" = 42 ] + +"$CPU_LD" --dynamic --stack-size=4096 --no-heap \ + -L"$TMP/lib" -lb -la -o "$TMP/main-ba" "$TMP/main-import.o" +[ "`"$CPU_RUN" --library-path="$TMP/lib" --int-reg=r64@0x00018 "$TMP/main-ba"`" = 43 ] + +# A main-executable GLOBAL outranks normal dependencies. +cat > "$TMP/main-own.s" <<'EOS' +.global _life +.global foo +.text +_start_life: + LDI r64@0x00000, 40 + CALL foo + MOV r64@0x00018, r64@0x00000 + LDI r32@0x00030, 0 + EXIT r32@0x00030 +foo: + LDI r64@0x00008, 1 + IADD r64@0x00000, r64@0x00000, r64@0x00008 + RET +EOS +"$CPU_AS" -o "$TMP/main-own.o" "$TMP/main-own.s" +"$CPU_LD" --dynamic --stack-size=4096 --no-heap \ + -L"$TMP/lib" -la -o "$TMP/main-own" "$TMP/main-own.o" +[ "`"$CPU_RUN" --library-path="$TMP/lib" --int-reg=r64@0x00018 "$TMP/main-own"`" = 41 ] + +# Explicit preload is the intentional override scope. Equal-strength GLOBAL +# preloads keep the historical rightmost-higher-priority rule. +[ "`"$CPU_RUN" --library-path="$TMP/lib" \ + --ldpreload=liba.so:libb.so \ + --int-reg=r64@0x00018 "$TMP/main-own"`" = 43 ] +[ "`"$CPU_RUN" --library-path="$TMP/lib" \ + --ldpreload=libb.so:liba.so \ + --int-reg=r64@0x00018 "$TMP/main-own"`" = 42 ] + +# Binding strength outranks scope class: a WEAK preload must not preempt a +# normal GLOBAL definition. +cat > "$TMP/weak.s" <<'EOS' +.weak foo +.text +foo: + LDI r64@0x00008, 9 + IADD r64@0x00000, r64@0x00000, r64@0x00008 + RET +EOS +"$CPU_AS" -o "$TMP/weak.o" "$TMP/weak.s" +"$CPU_LD" --shared --soname=libweak.so.1 -o "$TMP/libweak.so" "$TMP/weak.o" +[ "`"$CPU_RUN" --library-path="$TMP/lib" --ldpreload="$TMP/libweak.so" \ + --int-reg=r64@0x00018 "$TMP/main-ab"`" = 42 ] + +# If only WEAK definitions exist, the same scope ordering applies: first normal +# dependency wins, while rightmost explicit preload wins. +cat > "$TMP/weak-main.s" <<'EOS' +.global _life +.weak foo +.text +_start_life: + LDI r64@0x00000, 40 + CALL foo + MOV r64@0x00018, r64@0x00000 + LDI r32@0x00030, 0 + EXIT r32@0x00030 +EOS +cat > "$TMP/wa.s" <<'EOS' +.weak foo +.text +foo: + LDI r64@0x00008, 2 + IADD r64@0x00000, r64@0x00000, r64@0x00008 + RET +EOS +cat > "$TMP/wb.s" <<'EOS' +.weak foo +.text +foo: + LDI r64@0x00008, 3 + IADD r64@0x00000, r64@0x00000, r64@0x00008 + RET +EOS +"$CPU_AS" -o "$TMP/weak-main.o" "$TMP/weak-main.s" +"$CPU_AS" -o "$TMP/wa.o" "$TMP/wa.s" +"$CPU_AS" -o "$TMP/wb.o" "$TMP/wb.s" +"$CPU_LD" --shared --soname=libwa.so.1 -o "$TMP/lib/libwa.so.1" "$TMP/wa.o" +"$CPU_LD" --shared --soname=libwb.so.1 -o "$TMP/lib/libwb.so.1" "$TMP/wb.o" +ln -s libwa.so.1 "$TMP/lib/libwa.so" +ln -s libwb.so.1 "$TMP/lib/libwb.so" +"$CPU_LD" --dynamic --stack-size=4096 --no-heap \ + -L"$TMP/lib" -lwa -lwb -o "$TMP/weak-main" "$TMP/weak-main.o" +[ "`"$CPU_RUN" --library-path="$TMP/lib" --int-reg=r64@0x00018 "$TMP/weak-main"`" = 42 ] +[ "`"$CPU_RUN" --ldpreload="$TMP/lib/libwa.so.1:$TMP/lib/libwb.so.1" \ + --int-reg=r64@0x00018 "$TMP/weak-main"`" = 43 ] + +# A direct dependency outranks a conflicting transitive dependency. The +# resolver must therefore build a true breadth-first scope rather than expose +# DFS traversal order to symbol resolution. +cat > "$TMP/deep.s" <<'EOS' +.global deep_anchor +.global foo +.text +deep_anchor: + RET +foo: + LDI r64@0x00008, 9 + IADD r64@0x00000, r64@0x00000, r64@0x00008 + RET +EOS +cat > "$TMP/mid.s" <<'EOS' +.global mid_anchor +.extern deep_anchor +.text +mid_anchor: + CALL deep_anchor + RET +EOS +cat > "$TMP/direct.s" <<'EOS' +.global foo +.text +foo: + LDI r64@0x00008, 3 + IADD r64@0x00000, r64@0x00000, r64@0x00008 + RET +EOS +cat > "$TMP/bfs-main.s" <<'EOS' +.global _life +.extern mid_anchor +.extern foo +.text +_start_life: + LDI r64@0x00000, 40 + CALL mid_anchor + CALL foo + MOV r64@0x00018, r64@0x00000 + LDI r32@0x00030, 0 + EXIT r32@0x00030 +EOS +"$CPU_AS" -o "$TMP/deep.o" "$TMP/deep.s" +"$CPU_AS" -o "$TMP/mid.o" "$TMP/mid.s" +"$CPU_AS" -o "$TMP/direct.o" "$TMP/direct.s" +"$CPU_AS" -o "$TMP/bfs-main.o" "$TMP/bfs-main.s" +"$CPU_LD" --shared --soname=libdeep.so.1 -o "$TMP/lib/libdeep.so.1.0.0" "$TMP/deep.o" +ln -s libdeep.so.1.0.0 "$TMP/lib/libdeep.so.1" +ln -s libdeep.so.1 "$TMP/lib/libdeep.so" +"$CPU_LD" --shared --soname=libmid.so.1 -L"$TMP/lib" -ldeep \ + -o "$TMP/lib/libmid.so.1.0.0" "$TMP/mid.o" +ln -s libmid.so.1.0.0 "$TMP/lib/libmid.so.1" +ln -s libmid.so.1 "$TMP/lib/libmid.so" +"$CPU_LD" --shared --soname=libdirect.so.1 -o "$TMP/lib/libdirect.so.1.0.0" "$TMP/direct.o" +ln -s libdirect.so.1.0.0 "$TMP/lib/libdirect.so.1" +ln -s libdirect.so.1 "$TMP/lib/libdirect.so" +"$CPU_LD" --dynamic --stack-size=4096 --no-heap \ + -L"$TMP/lib" -lmid -ldirect -o "$TMP/bfs-main" "$TMP/bfs-main.o" +[ "`"$CPU_RUN" --library-path="$TMP/lib" --int-reg=r64@0x00018 "$TMP/bfs-main"`" = 43 ] + +# Diamond graph: A and B both depend on C. SONAME deduplication loads C once, +# while the direct A/B scope still follows left-to-right order. +cat > "$TMP/common.s" <<'EOS' +.global common_anchor +.text +common_anchor: + RET +EOS +cat > "$TMP/da.s" <<'EOS' +.global a_anchor +.global foo +.extern common_anchor +.text +a_anchor: + CALL common_anchor + RET +foo: + LDI r64@0x00008, 2 + IADD r64@0x00000, r64@0x00000, r64@0x00008 + RET +EOS +cat > "$TMP/db.s" <<'EOS' +.global b_anchor +.global foo +.extern common_anchor +.text +b_anchor: + CALL common_anchor + RET +foo: + LDI r64@0x00008, 3 + IADD r64@0x00000, r64@0x00000, r64@0x00008 + RET +EOS +cat > "$TMP/diamond-main.s" <<'EOS' +.global _life +.extern a_anchor +.extern b_anchor +.extern foo +.text +_start_life: + LDI r64@0x00000, 40 + CALL a_anchor + CALL b_anchor + CALL foo + MOV r64@0x00018, r64@0x00000 + LDI r32@0x00030, 0 + EXIT r32@0x00030 +EOS +"$CPU_AS" -o "$TMP/common.o" "$TMP/common.s" +"$CPU_AS" -o "$TMP/da.o" "$TMP/da.s" +"$CPU_AS" -o "$TMP/db.o" "$TMP/db.s" +"$CPU_AS" -o "$TMP/diamond-main.o" "$TMP/diamond-main.s" +"$CPU_LD" --shared --soname=libcommon.so.1 -o "$TMP/lib/libcommon.so.1.0.0" "$TMP/common.o" +ln -s libcommon.so.1.0.0 "$TMP/lib/libcommon.so.1" +ln -s libcommon.so.1 "$TMP/lib/libcommon.so" +"$CPU_LD" --shared --soname=libda.so.1 -L"$TMP/lib" -lcommon \ + -o "$TMP/lib/libda.so.1.0.0" "$TMP/da.o" +ln -s libda.so.1.0.0 "$TMP/lib/libda.so.1" +ln -s libda.so.1 "$TMP/lib/libda.so" +"$CPU_LD" --shared --soname=libdb.so.1 -L"$TMP/lib" -lcommon \ + -o "$TMP/lib/libdb.so.1.0.0" "$TMP/db.o" +ln -s libdb.so.1.0.0 "$TMP/lib/libdb.so.1" +ln -s libdb.so.1 "$TMP/lib/libdb.so" +"$CPU_LD" --dynamic --stack-size=4096 --no-heap \ + -L"$TMP/lib" -lda -ldb -o "$TMP/diamond-main" "$TMP/diamond-main.o" +[ "`"$CPU_RUN" --library-path="$TMP/lib" --int-reg=r64@0x00018 "$TMP/diamond-main"`" = 42 ] + +exit 0 |
