xref: /freebsd/usr.sbin/crashinfo/crashinfo.sh (revision 5e53a4f90f82c4345f277dd87cc9292f26e04a29)
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# $FreeBSD$
33
34usage()
35{
36	echo "usage: crashinfo [-b] [-d crashdir] [-n dumpnr]" \
37		"[-k kernel] [core]"
38	exit 1
39}
40
41# Find a gdb binary to use and save the value in GDB.
42find_gdb()
43{
44	local binary
45
46	for binary in /usr/local/bin/gdb /usr/libexec/gdb /usr/bin/gdb; do
47		if [ -x ${binary} ]; then
48			GDB=${binary}
49			return
50		fi
51	done
52}
53
54# Run a single gdb command against a kernel file in batch mode.
55# The kernel file is specified as the first argument and the command
56# is given in the remaining arguments.
57gdb_command()
58{
59	local k
60
61	k=$1 ; shift
62
63	if [ ${GDB} = /usr/local/bin/gdb ]; then
64		${GDB} -batch -ex "$@" $k
65	else
66		echo -e "$@" | ${GDB} -x /dev/stdin -batch $k
67	fi
68}
69
70find_kernel()
71{
72	local ivers k kvers
73
74	ivers=$(awk '
75	/Version String/ {
76		print
77		nextline=1
78		next
79	}
80	nextline==1 {
81		if ($0 ~ "^  [A-Za-z ]+: ") {
82			nextline=0
83		} else {
84			print
85		}
86	}' $INFO)
87
88	# Look for a matching kernel version, handling possible truncation
89	# of the version string recovered from the dump.
90	for k in `sysctl -n kern.bootfile` $(ls -t /boot/*/kernel); do
91		kvers=$(gdb_command $k 'printf "  Version String: %s", version' | \
92		    awk "{line=line\$0\"\n\"} END{print substr(line,1,${#ivers})}" \
93		    2>/dev/null)
94		if [ "$ivers" = "$kvers" ]; then
95			KERNEL=$k
96			break
97		fi
98	done
99}
100
101BATCH=false
102CRASHDIR=/var/crash
103DUMPNR=
104KERNEL=
105
106while getopts "bd:n:k:" opt; do
107	case "$opt" in
108	b)
109		BATCH=true
110		;;
111	d)
112		CRASHDIR=$OPTARG
113		;;
114	n)
115		DUMPNR=$OPTARG
116		;;
117	k)
118		KERNEL=$OPTARG
119		;;
120	\?)
121		usage
122		;;
123	esac
124done
125
126shift $((OPTIND - 1))
127
128if [ $# -eq 1 ]; then
129	if [ -n "$DUMPNR" ]; then
130		echo "-n and an explicit vmcore are mutually exclusive"
131		usage
132	fi
133
134	# Figure out the crash directory and number from the vmcore name.
135	CRASHDIR=`dirname $1`
136	DUMPNR=$(expr $(basename $1) : 'vmcore\.\([0-9]*\)$')
137	if [ -z "$DUMPNR" ]; then
138		echo "Unable to determine dump number from vmcore file $1."
139		exit 1
140	fi
141elif [ $# -gt 1 ]; then
142	usage
143else
144	# If we don't have an explicit dump number, operate on the most
145	# recent dump.
146	if [ -z "$DUMPNR" ]; then
147		if ! [ -r $CRASHDIR/bounds ]; then
148			echo "No crash dumps in $CRASHDIR."
149			exit 1
150		fi
151		next=`cat $CRASHDIR/bounds`
152		if [ -z "$next" ] || [ "$next" -eq 0 ]; then
153			echo "No crash dumps in $CRASHDIR."
154			exit 1
155		fi
156		DUMPNR=$(($next - 1))
157	fi
158fi
159
160VMCORE=$CRASHDIR/vmcore.$DUMPNR
161INFO=$CRASHDIR/info.$DUMPNR
162FILE=$CRASHDIR/core.txt.$DUMPNR
163HOSTNAME=`hostname`
164
165if $BATCH; then
166	echo "Writing crash summary to $FILE."
167	exec > $FILE 2>&1
168fi
169
170find_gdb
171if [ -z "$GDB" ]; then
172	echo "Unable to find a kernel debugger."
173	exit 1
174fi
175
176if [ ! -e $VMCORE ]; then
177	echo "$VMCORE not found"
178	exit 1
179fi
180
181if [ ! -e $INFO ]; then
182	echo "$INFO not found"
183	exit 1
184fi
185
186# If the user didn't specify a kernel, then try to find one.
187if [ -z "$KERNEL" ]; then
188	find_kernel
189	if [ -z "$KERNEL" ]; then
190		echo "Unable to find matching kernel for $VMCORE"
191		exit 1
192	fi
193elif [ ! -e $KERNEL ]; then
194	echo "$KERNEL not found"
195	exit 1
196fi
197
198umask 077
199
200# Simulate uname
201ostype=$(gdb_command $KERNEL 'printf "%s", ostype')
202osrelease=$(gdb_command $KERNEL 'printf "%s", osrelease')
203version=$(gdb_command $KERNEL 'printf "%s", version' | tr '\t\n' '  ')
204machine=$(gdb_command $KERNEL 'printf "%s", machine')
205
206if ! $BATCH; then
207	echo "Writing crash summary to $FILE."
208	exec > $FILE 2>&1
209fi
210
211echo "$HOSTNAME dumped core - see $VMCORE"
212echo
213date
214echo
215echo "$ostype $HOSTNAME $osrelease $version $machine"
216echo
217sed -ne '/^  Panic String: /{s//panic: /;p;}' $INFO
218echo
219
220# XXX: /bin/sh on 7.0+ is broken so we can't simply pipe the commands to
221# kgdb via stdin and have to use a temporary file instead.
222file=`mktemp /tmp/crashinfo.XXXXXX`
223if [ $? -eq 0 ]; then
224	echo "bt" >> $file
225	echo "quit" >> $file
226	${GDB%gdb}kgdb $KERNEL $VMCORE < $file
227	rm -f $file
228	echo
229fi
230echo
231
232echo "------------------------------------------------------------------------"
233echo "ps -axlww"
234echo
235ps -M $VMCORE -N $KERNEL -axlww
236echo
237
238echo "------------------------------------------------------------------------"
239echo "vmstat -s"
240echo
241vmstat -M $VMCORE -N $KERNEL -s
242echo
243
244echo "------------------------------------------------------------------------"
245echo "vmstat -m"
246echo
247vmstat -M $VMCORE -N $KERNEL -m
248echo
249
250echo "------------------------------------------------------------------------"
251echo "vmstat -z"
252echo
253vmstat -M $VMCORE -N $KERNEL -z
254echo
255
256echo "------------------------------------------------------------------------"
257echo "vmstat -i"
258echo
259vmstat -M $VMCORE -N $KERNEL -i
260echo
261
262echo "------------------------------------------------------------------------"
263echo "pstat -T"
264echo
265pstat -M $VMCORE -N $KERNEL -T
266echo
267
268echo "------------------------------------------------------------------------"
269echo "pstat -s"
270echo
271pstat -M $VMCORE -N $KERNEL -s
272echo
273
274echo "------------------------------------------------------------------------"
275echo "iostat"
276echo
277iostat -M $VMCORE -N $KERNEL
278echo
279
280echo "------------------------------------------------------------------------"
281echo "ipcs -a"
282echo
283ipcs -C $VMCORE -N $KERNEL -a
284echo
285
286echo "------------------------------------------------------------------------"
287echo "ipcs -T"
288echo
289ipcs -C $VMCORE -N $KERNEL -T
290echo
291
292# XXX: This doesn't actually work in 5.x+
293if false; then
294echo "------------------------------------------------------------------------"
295echo "w -dn"
296echo
297w -M $VMCORE -N $KERNEL -dn
298echo
299fi
300
301echo "------------------------------------------------------------------------"
302echo "nfsstat"
303echo
304nfsstat -M $VMCORE -N $KERNEL
305echo
306
307echo "------------------------------------------------------------------------"
308echo "netstat -s"
309echo
310netstat -M $VMCORE -N $KERNEL -s
311echo
312
313echo "------------------------------------------------------------------------"
314echo "netstat -m"
315echo
316netstat -M $VMCORE -N $KERNEL -m
317echo
318
319echo "------------------------------------------------------------------------"
320echo "netstat -anA"
321echo
322netstat -M $VMCORE -N $KERNEL -anA
323echo
324
325echo "------------------------------------------------------------------------"
326echo "netstat -aL"
327echo
328netstat -M $VMCORE -N $KERNEL -aL
329echo
330
331echo "------------------------------------------------------------------------"
332echo "fstat"
333echo
334fstat -M $VMCORE -N $KERNEL
335echo
336
337echo "------------------------------------------------------------------------"
338echo "dmesg"
339echo
340dmesg -a -M $VMCORE -N $KERNEL
341echo
342
343echo "------------------------------------------------------------------------"
344echo "kernel config"
345echo
346config -x $KERNEL
347
348echo
349echo "------------------------------------------------------------------------"
350echo "ddb capture buffer"
351echo
352
353ddb capture -M $VMCORE -N $KERNEL print
354