1 #!/usr/bin/ksh
2 #
3 #
4 # This file and its contents are supplied under the terms of the
5 # Common Development and Distribution License ("CDDL"), version 1.0.
6 # You may only use this file in accordance with the terms of version
7 # 1.0 of the CDDL.
8 #
9 # A full copy of the text of the CDDL should have accompanied this
10 # source. A copy of the CDDL is also available via the Internet at
11 # http://www.illumos.org/license/CDDL.
12 #
13
14 #
15 # Copyright 2023 Oxide Computer Company
16 #
17
18 #
19 # This test attempts to verify that we can mdb (via libproc / thread_db)
20 # and xregs sees the expected extended register set. It also ensures
21 # that the same values are visible via a core file from that process at
22 # the same point.
23 #
24
25 unalias -a
26 set -o pipefail
27 export LANG=C.UTF-8
28
29 mx_exit=0
30 mx_arg0="$(basename $0)"
31 mx_dir="$(dirname $0)"
32 mx_data="$mx_dir/data"
33 mx_tmpdir="/tmp/mdb_xregs.$$"
34
35 typeset -A mx_seed
36 mx_seed["32"]=0x12900922
37 mx_seed["64"]=0x11900456
38 typeset -A mx_hwtype
39 mx_hwtype["32"]="$mx_dir/xsu_hwtype.32"
40 mx_hwtype["64"]="$mx_dir/xsu_hwtype.64"
41 typeset -A mx_setprog
42 mx_setprog["32"]="$mx_dir/xregs_set.32"
43 mx_setprog["64"]="$mx_dir/xregs_set.64"
44
45 warn()
46 {
47 typeset msg="$*"
48 echo "TEST FAILED: $msg" >&2
49 mx_exit=1
50 }
51
52 fatal()
53 {
54 typeset msg="$*"
55 [[ -z "$msg" ]] && msg="failed"
56 echo "$mx_arg0: $msg" >&2
57 exit 1
58 }
59
60 cleanup()
61 {
62 [[ -n "$mx_tmpdir" ]] && rm -rf "$mx_tmpdir"
63 }
64
65 setup()
66 {
67 if ! mkdir $mx_tmpdir; then
68 fatal "failed to create temporary directory: $mx_tmpdir"
69 fi
70 }
71
72 check_file()
73 {
74 typeset src="$1"
75 typeset act="$2"
76 typeset desc="$3"
77
78 if [[ ! -f "$act" ]]; then
79 warn "failed to generate $act"
80 return
81 fi
82
83 if ! diff -q $src $act; then
84 diff -u $src $act
85 warn "$desc: $act did not match expected output"
86 else
87 printf "TEST PASSED: %s\n" "$desc"
88 fi
89 }
90
91 #
92 # Run one instance of mdb to grab and get our first pass data files
93 # against a real process. We're not really counting on our exit status
94 # from mdb here, mostly on whether or not the generated files all exist
95 # in the end. We gather data from the generated cores in a separate run.
96 #
97 run_live_mdb()
98 {
99 typeset prog="$1"
100 typeset seed="$2"
101 typeset fpregs="$3"
102 typeset core="$4"
103 typeset coreloc="$5"
104
105 mdb $prog <<EOF
106 yield::bp
107 ::run $seed
108 ::tmodel lwp
109 ::fpregs ! cat > $fpregs.lwp
110 ::tmodel thread
111 ::fpregs ! cat > $fpregs.thread
112 _uberdata::printf "$core.%u" uberdata_t pid ! cat > $coreloc
113 ::gcore -o $core
114 ::kill
115 \$q
116 EOF
117 }
118
119 #
120 # We've been given a core file that matches something we just ran above. We
121 # should be able to read the ::fpregs from it and get the exact same data.
122 #
123 check_core()
124 {
125 typeset core="$1"
126 typeset output="$2"
127 typeset check="$3"
128
129 if ! mdb -e "::fpregs ! cat > $output" $core; then
130 warn "mdb failed to get ::fpregs from $core"
131 return
132 fi
133
134 check_file $check $output "extracted core matches"
135 }
136
137 run_one_isa()
138 {
139 typeset isa="$1"
140 typeset target=${mx_setprog[$isa]}
141 typeset hwprog=${mx_hwtype[$isa]}
142 typeset seed=${mx_seed[$isa]}
143 typeset coreloc="$mx_tmpdir/coreloc"
144 typeset fpu_type=
145 typeset corename=
146 typeset fpregs=
147 typeset check=
148
149 if ! fpu_type=$($hwprog 2>/dev/null); then
150 warn "failed to determine $isa-bit FPU type"
151 return
152 fi
153
154 printf "Discovered FPU: %s %s-bit\n" $fpu_type $isa
155 corename="$mx_tmpdir/core.$fpu_type.$isa"
156 fpregs="$mx_tmpdir/fpregs.$fpu_type.$isa"
157 check="$mx_data/mdb_xregs.$fpu_type.$isa"
158
159 run_live_mdb $target $seed $fpregs $corename $coreloc
160 check_file "$check" "$fpregs.lwp" "$isa-bit $fpu_type ::fpregs (lwp)"
161 check_file "$check" "$fpregs.lwp" "$isa-bit $fpu_type ::fpregs (thread)"
162
163 if [[ ! -f "$coreloc" ]]; then
164 warn "missing core file location file, cannot run core tests"
165 return
166 fi
167
168 typeset -i ncores=0
169 for f in $(cat $coreloc); do
170 ((ncores++))
171 if [[ ! -f "$f" ]]; then
172 warn "core file location $f is not a file"
173 continue
174 fi
175
176 check_core "$f" "$mx_tmpdir/fpregs.core" $check
177 done
178
179 if ((ncores == 0)); then
180 warn "No core files found!"
181 fi
182 }
183
184 setup
185 trap 'cleanup' EXIT
186
187 run_one_isa "32"
188 run_one_isa "64"
189
190 exit $mx_exit