]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/crashinfo/crashinfo.sh
Remove $FreeBSD$: one-line sh pattern
[FreeBSD/FreeBSD.git] / usr.sbin / crashinfo / crashinfo.sh
1 #!/bin/sh
2 #
3 # SPDX-License-Identifier: BSD-3-Clause
4 #
5 # Copyright (c) 2008 Yahoo!, Inc.
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions
10 # are met:
11 # 1. Redistributions of source code must retain the above copyright
12 #    notice, this list of conditions and the following disclaimer.
13 # 2. Redistributions in binary form must reproduce the above copyright
14 #    notice, this list of conditions and the following disclaimer in the
15 #    documentation and/or other materials provided with the distribution.
16 # 3. Neither the name of the author nor the names of any co-contributors
17 #    may be used to endorse or promote products derived from this software
18 #    without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 # SUCH DAMAGE.
31 #
32
33 usage()
34 {
35         echo "usage: crashinfo [-b] [-d crashdir] [-n dumpnr]" \
36                 "[-k kernel] [core]"
37         exit 1
38 }
39
40 # Remove an uncompressed copy of a dump
41 cleanup()
42 {
43
44         [ -e $VMCORE ] && rm -f $VMCORE
45 }
46
47 # Find a gdb binary to use and save the value in GDB.
48 find_gdb()
49 {
50         local binary
51
52         for binary in /usr/local/bin/gdb /usr/libexec/gdb; do
53                 if [ -x ${binary} ]; then
54                         GDB=${binary}
55                         return
56                 fi
57         done
58 }
59
60 # Run a single gdb command against a kernel file in batch mode.
61 # The kernel file is specified as the first argument and the command
62 # is given in the remaining arguments.
63 gdb_command()
64 {
65         local k
66
67         k=$1 ; shift
68
69         if [ ${GDB} = /usr/local/bin/gdb ]; then
70                 ${GDB} -batch -ex "$@" $k
71         else
72                 echo -e "$@" | ${GDB} -x /dev/stdin -batch $k
73         fi
74 }
75
76 find_kernel()
77 {
78         local ivers k kvers
79
80         ivers=$(awk '
81         /Version String/ {
82                 print
83                 nextline=1
84                 next
85         }
86         nextline==1 {
87                 if ($0 ~ "^  [A-Za-z ]+: ") {
88                         nextline=0
89                 } else {
90                         print
91                 }
92         }' $INFO)
93
94         # Look for a matching kernel version, handling possible truncation
95         # of the version string recovered from the dump.
96         for k in `sysctl -n kern.bootfile` $(ls -t /boot/*/kernel); do
97                 kvers=$(gdb_command $k 'printf "  Version String: %s", version' | \
98                     awk "{line=line\$0\"\n\"} END{print substr(line,1,${#ivers})}" \
99                     2>/dev/null)
100                 if [ "$ivers" = "$kvers" ]; then
101                         KERNEL=$k
102                         break
103                 fi
104         done
105 }
106
107 BATCH=false
108 CRASHDIR=/var/crash
109 DUMPNR=
110 KERNEL=
111
112 while getopts "bd:n:k:" opt; do
113         case "$opt" in
114         b)
115                 BATCH=true
116                 ;;
117         d)
118                 CRASHDIR=$OPTARG
119                 ;;
120         n)
121                 DUMPNR=$OPTARG
122                 ;;
123         k)
124                 KERNEL=$OPTARG
125                 ;;
126         \?)
127                 usage
128                 ;;
129         esac
130 done
131
132 shift $((OPTIND - 1))
133
134 if [ $# -eq 1 ]; then
135         if [ -n "$DUMPNR" ]; then
136                 echo "-n and an explicit vmcore are mutually exclusive"
137                 usage
138         fi
139
140         # Figure out the crash directory and number from the vmcore name.
141         CRASHDIR=`dirname $1`
142         DUMPNR=$(expr $(basename $1) : 'vmcore\.\([0-9]*\)')
143         if [ -z "$DUMPNR" ]; then
144                 echo "Unable to determine dump number from vmcore file $1."
145                 exit 1
146         fi
147 elif [ $# -gt 1 ]; then
148         usage
149 else
150         # If we don't have an explicit dump number, operate on the most
151         # recent dump.
152         if [ -z "$DUMPNR" ]; then
153                 if ! [ -r $CRASHDIR/bounds ]; then
154                         echo "No crash dumps in $CRASHDIR."
155                         exit 1
156                 fi                      
157                 next=`cat $CRASHDIR/bounds`
158                 if [ -z "$next" ] || [ "$next" -eq 0 ]; then
159                         echo "No crash dumps in $CRASHDIR."
160                         exit 1
161                 fi
162                 DUMPNR=$(($next - 1))
163         fi
164 fi
165
166 VMCORE=$CRASHDIR/vmcore.$DUMPNR
167 INFO=$CRASHDIR/info.$DUMPNR
168 FILE=$CRASHDIR/core.txt.$DUMPNR
169 HOSTNAME=`hostname`
170
171 if $BATCH; then
172         echo "Writing crash summary to $FILE."
173         exec > $FILE 2>&1
174 fi
175
176 find_gdb
177 if [ -z "$GDB" ]; then
178         echo "Unable to find a kernel debugger."
179         echo "Please install the devel/gdb port or gdb package."
180         exit 1
181 fi
182
183 if [ ! -e $VMCORE ]; then
184         if [ -e $VMCORE.gz ]; then
185                 trap cleanup EXIT HUP INT QUIT TERM
186                 gzcat $VMCORE.gz > $VMCORE
187         elif [ -e $VMCORE.zst ]; then
188                 trap cleanup EXIT HUP INT QUIT TERM
189                 zstdcat $VMCORE.zst > $VMCORE
190         else
191                 echo "$VMCORE not found"
192                 exit 1
193         fi
194 fi
195
196 if [ ! -e $INFO ]; then
197         echo "$INFO not found"
198         exit 1
199 fi
200
201 # If the user didn't specify a kernel, then try to find one.
202 if [ -z "$KERNEL" ]; then
203         find_kernel
204         if [ -z "$KERNEL" ]; then
205                 echo "Unable to find matching kernel for $VMCORE"
206                 exit 1
207         fi
208 elif [ ! -e $KERNEL ]; then
209         echo "$KERNEL not found"
210         exit 1
211 fi
212
213 umask 077
214
215 # Simulate uname
216 ostype=$(gdb_command $KERNEL 'printf "%s", ostype')
217 osrelease=$(gdb_command $KERNEL 'printf "%s", osrelease')
218 version=$(gdb_command $KERNEL 'printf "%s", version' | tr '\t\n' '  ')
219 machine=$(gdb_command $KERNEL 'printf "%s", machine')
220
221 if ! $BATCH; then
222         echo "Writing crash summary to $FILE."
223         exec > $FILE 2>&1
224 fi
225
226 echo "$HOSTNAME dumped core - see $VMCORE"
227 echo
228 date
229 echo
230 echo "$ostype $HOSTNAME $osrelease $version $machine"
231 echo
232 sed -ne '/^  Panic String: /{s//panic: /;p;}' $INFO
233 echo
234
235 # XXX: /bin/sh on 7.0+ is broken so we can't simply pipe the commands to
236 # kgdb via stdin and have to use a temporary file instead.
237 file=`mktemp /tmp/crashinfo.XXXXXX`
238 if [ $? -eq 0 ]; then
239         echo "bt" >> $file
240         echo "quit" >> $file
241         ${GDB%gdb}kgdb $KERNEL $VMCORE < $file
242         rm -f $file
243         echo
244 fi
245 echo
246
247 echo "------------------------------------------------------------------------"
248 echo "ps -axlww"
249 echo
250 ps -M $VMCORE -N $KERNEL -axlww
251 echo
252
253 echo "------------------------------------------------------------------------"
254 echo "vmstat -s"
255 echo
256 vmstat -M $VMCORE -N $KERNEL -s
257 echo
258
259 echo "------------------------------------------------------------------------"
260 echo "vmstat -m"
261 echo
262 vmstat -M $VMCORE -N $KERNEL -m
263 echo
264
265 echo "------------------------------------------------------------------------"
266 echo "vmstat -z"
267 echo
268 vmstat -M $VMCORE -N $KERNEL -z
269 echo
270
271 echo "------------------------------------------------------------------------"
272 echo "vmstat -i"
273 echo
274 vmstat -M $VMCORE -N $KERNEL -i
275 echo
276
277 echo "------------------------------------------------------------------------"
278 echo "pstat -T"
279 echo
280 pstat -M $VMCORE -N $KERNEL -T
281 echo
282
283 echo "------------------------------------------------------------------------"
284 echo "pstat -s"
285 echo
286 pstat -M $VMCORE -N $KERNEL -s
287 echo
288
289 echo "------------------------------------------------------------------------"
290 echo "iostat"
291 echo
292 iostat -M $VMCORE -N $KERNEL
293 echo
294
295 echo "------------------------------------------------------------------------"
296 echo "ipcs -a"
297 echo
298 ipcs -C $VMCORE -N $KERNEL -a
299 echo
300
301 echo "------------------------------------------------------------------------"
302 echo "ipcs -T"
303 echo
304 ipcs -C $VMCORE -N $KERNEL -T
305 echo
306
307 # XXX: This doesn't actually work in 5.x+
308 if false; then
309 echo "------------------------------------------------------------------------"
310 echo "w -dn"
311 echo
312 w -M $VMCORE -N $KERNEL -dn
313 echo
314 fi
315
316 echo "------------------------------------------------------------------------"
317 echo "netstat -s"
318 echo
319 netstat -M $VMCORE -N $KERNEL -s
320 echo
321
322 echo "------------------------------------------------------------------------"
323 echo "netstat -m"
324 echo
325 netstat -M $VMCORE -N $KERNEL -m
326 echo
327
328 echo "------------------------------------------------------------------------"
329 echo "netstat -anA"
330 echo
331 netstat -M $VMCORE -N $KERNEL -anA
332 echo
333
334 echo "------------------------------------------------------------------------"
335 echo "netstat -aL"
336 echo
337 netstat -M $VMCORE -N $KERNEL -aL
338 echo
339
340 echo "------------------------------------------------------------------------"
341 echo "fstat"
342 echo
343 fstat -M $VMCORE -N $KERNEL
344 echo
345
346 echo "------------------------------------------------------------------------"
347 echo "dmesg"
348 echo
349 dmesg -a -M $VMCORE -N $KERNEL
350 echo
351
352 echo "------------------------------------------------------------------------"
353 echo "kernel config"
354 echo
355 config -x $KERNEL
356
357 echo
358 echo "------------------------------------------------------------------------"
359 echo "ddb capture buffer"
360 echo
361
362 ddb capture -M $VMCORE -N $KERNEL print