1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#!/bin/sh
set -eu
: "${CPU_AS:?}" "${CPU_LD:?}" "${CPU_RUN:?}"
TMP=${TMPDIR:-/tmp}/libmcpu-env-preload-$$
mkdir -p "$TMP/lib"
trap 'rm -rf "$TMP"' EXIT HUP INT TERM
cat > "$TMP/main.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
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.o" "$TMP/main.s"
"$CPU_AS" -o "$TMP/a.o" "$TMP/a.s"
"$CPU_AS" -o "$TMP/b.o" "$TMP/b.s"
"$CPU_LD" --dynamic --stack-size=4096 --no-heap -o "$TMP/main" "$TMP/main.o"
"$CPU_LD" --shared --soname=liba.so.1 -o "$TMP/lib/liba.so.1" "$TMP/a.o"
"$CPU_LD" --shared --soname=libb.so.1 -o "$TMP/lib/libb.so.1" "$TMP/b.o"
ln -s liba.so.1 "$TMP/lib/liba.so"
ln -s libb.so.1 "$TMP/lib/libb.so"
# Empty environment is the normal no-preload baseline.
[ "`MCPU_LD_PRELOAD= "$CPU_RUN" --library-path="$TMP/lib" \
--int-reg=r64@0x00018 "$TMP/main"`" = 41 ]
# Environment-only preload uses the same resolver and rightmost-wins ordering.
[ "`MCPU_LD_PRELOAD=liba.so "$CPU_RUN" --library-path="$TMP/lib" \
--int-reg=r64@0x00018 "$TMP/main"`" = 42 ]
[ "`MCPU_LD_PRELOAD=liba.so:libb.so "$CPU_RUN" --library-path="$TMP/lib" \
--int-reg=r64@0x00018 "$TMP/main"`" = 43 ]
[ "`MCPU_LD_PRELOAD=libb.so:liba.so "$CPU_RUN" --library-path="$TMP/lib" \
--int-reg=r64@0x00018 "$TMP/main"`" = 42 ]
# Command-line preload entries are appended after environment entries, so the
# established rightmost-higher-priority rule makes command line stronger.
[ "`MCPU_LD_PRELOAD=liba.so "$CPU_RUN" --library-path="$TMP/lib" \
--ldpreload=libb.so --int-reg=r64@0x00018 "$TMP/main"`" = 43 ]
[ "`MCPU_LD_PRELOAD=libb.so "$CPU_RUN" --library-path="$TMP/lib" \
--ldpreload=liba.so --int-reg=r64@0x00018 "$TMP/main"`" = 42 ]
[ "`MCPU_LD_PRELOAD=liba.so:libb.so "$CPU_RUN" --library-path="$TMP/lib" \
--ldpreload=libb.so:liba.so --int-reg=r64@0x00018 "$TMP/main"`" = 42 ]
# Environment preload is equivalent to --ldpreload for ABI compatibility: an
# ABI-v1 static executable must reject it just as it rejects the CLI option.
"$CPU_LD" --stack-size=4096 --no-heap -o "$TMP/static" "$TMP/main.o"
if MCPU_LD_PRELOAD="$TMP/lib/liba.so.1" "$CPU_RUN" "$TMP/static" \
>/dev/null 2>"$TMP/static.err"; then
echo "ABI-v1 executable unexpectedly accepted MCPU_LD_PRELOAD" >&2
exit 1
fi
grep -q 'dynamic modules require' "$TMP/static.err"
# The environment preload is independent of configuration suppression. An
# explicit pathname therefore still works under --no-config.
[ "`MCPU_LD_PRELOAD="$TMP/lib/liba.so.1" "$CPU_RUN" --no-config \
--int-reg=r64@0x00018 "$TMP/main"`" = 42 ]
# Environment preload remains an explicit override above a normal dependency.
cat > "$TMP/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
"$CPU_AS" -o "$TMP/import.o" "$TMP/import.s"
"$CPU_LD" --dynamic --stack-size=4096 --no-heap -L"$TMP/lib" -la \
-o "$TMP/import" "$TMP/import.o"
[ "`MCPU_LD_PRELOAD=libb.so "$CPU_RUN" --library-path="$TMP/lib" \
--int-reg=r64@0x00018 "$TMP/import"`" = 43 ]
# Invalid environment lists and missing names are hard errors.
if MCPU_LD_PRELOAD=liba.so::libb.so "$CPU_RUN" --library-path="$TMP/lib" \
"$TMP/main" >/dev/null 2>"$TMP/bad-list.err"; then
echo "malformed MCPU_LD_PRELOAD unexpectedly accepted" >&2
exit 1
fi
grep -q 'MCPU_LD_PRELOAD' "$TMP/bad-list.err"
if MCPU_LD_PRELOAD=does-not-exist.so "$CPU_RUN" --library-path="$TMP/lib" \
"$TMP/main" >/dev/null 2>"$TMP/missing.err"; then
echo "missing MCPU_LD_PRELOAD library unexpectedly accepted" >&2
exit 1
fi
grep -q 'MCPU_LD_PRELOAD' "$TMP/missing.err"
MCPU_LD_PRELOAD= "$CPU_RUN" --help 2>&1 | grep -q 'MCPU_LD_PRELOAD'
exit 0
|