]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/crashinfo/crashinfo.sh
MFV r331400: 8484 Implement aggregate sum and use for arc counters
[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 # $FreeBSD$
33
34 usage()
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.
42 find_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.
57 gdb_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
70 find_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
101 BATCH=false
102 CRASHDIR=/var/crash
103 DUMPNR=
104 KERNEL=
105
106 while 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
124 done
125
126 shift $((OPTIND - 1))
127
128 if [ $# -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
141 elif [ $# -gt 1 ]; then
142         usage
143 else
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
158 fi
159
160 VMCORE=$CRASHDIR/vmcore.$DUMPNR
161 INFO=$CRASHDIR/info.$DUMPNR
162 FILE=$CRASHDIR/core.txt.$DUMPNR
163 HOSTNAME=`hostname`
164
165 if $BATCH; then
166         echo "Writing crash summary to $FILE."
167         exec > $FILE 2>&1
168 fi
169
170 find_gdb
171 if [ -z "$GDB" ]; then
172         echo "Unable to find a kernel debugger."
173         exit 1
174 fi
175
176 if [ ! -e $VMCORE ]; then
177         echo "$VMCORE not found"
178         exit 1
179 fi
180
181 if [ ! -e $INFO ]; then
182         echo "$INFO not found"
183         exit 1
184 fi
185
186 # If the user didn't specify a kernel, then try to find one.
187 if [ -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
193 elif [ ! -e $KERNEL ]; then
194         echo "$KERNEL not found"
195         exit 1
196 fi
197
198 umask 077
199
200 # Simulate uname
201 ostype=$(gdb_command $KERNEL 'printf "%s", ostype')
202 osrelease=$(gdb_command $KERNEL 'printf "%s", osrelease')
203 version=$(gdb_command $KERNEL 'printf "%s", version' | tr '\t\n' '  ')
204 machine=$(gdb_command $KERNEL 'printf "%s", machine')
205
206 if ! $BATCH; then
207         echo "Writing crash summary to $FILE."
208         exec > $FILE 2>&1
209 fi
210
211 echo "$HOSTNAME dumped core - see $VMCORE"
212 echo
213 date
214 echo
215 echo "$ostype $HOSTNAME $osrelease $version $machine"
216 echo
217 sed -ne '/^  Panic String: /{s//panic: /;p;}' $INFO
218 echo
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.
222 file=`mktemp /tmp/crashinfo.XXXXXX`
223 if [ $? -eq 0 ]; then
224         echo "bt" >> $file
225         echo "quit" >> $file
226         ${GDB%gdb}kgdb $KERNEL $VMCORE < $file
227         rm -f $file
228         echo
229 fi
230 echo
231
232 echo "------------------------------------------------------------------------"
233 echo "ps -axlww"
234 echo
235 ps -M $VMCORE -N $KERNEL -axlww
236 echo
237
238 echo "------------------------------------------------------------------------"
239 echo "vmstat -s"
240 echo
241 vmstat -M $VMCORE -N $KERNEL -s
242 echo
243
244 echo "------------------------------------------------------------------------"
245 echo "vmstat -m"
246 echo
247 vmstat -M $VMCORE -N $KERNEL -m
248 echo
249
250 echo "------------------------------------------------------------------------"
251 echo "vmstat -z"
252 echo
253 vmstat -M $VMCORE -N $KERNEL -z
254 echo
255
256 echo "------------------------------------------------------------------------"
257 echo "vmstat -i"
258 echo
259 vmstat -M $VMCORE -N $KERNEL -i
260 echo
261
262 echo "------------------------------------------------------------------------"
263 echo "pstat -T"
264 echo
265 pstat -M $VMCORE -N $KERNEL -T
266 echo
267
268 echo "------------------------------------------------------------------------"
269 echo "pstat -s"
270 echo
271 pstat -M $VMCORE -N $KERNEL -s
272 echo
273
274 echo "------------------------------------------------------------------------"
275 echo "iostat"
276 echo
277 iostat -M $VMCORE -N $KERNEL
278 echo
279
280 echo "------------------------------------------------------------------------"
281 echo "ipcs -a"
282 echo
283 ipcs -C $VMCORE -N $KERNEL -a
284 echo
285
286 echo "------------------------------------------------------------------------"
287 echo "ipcs -T"
288 echo
289 ipcs -C $VMCORE -N $KERNEL -T
290 echo
291
292 # XXX: This doesn't actually work in 5.x+
293 if false; then
294 echo "------------------------------------------------------------------------"
295 echo "w -dn"
296 echo
297 w -M $VMCORE -N $KERNEL -dn
298 echo
299 fi
300
301 echo "------------------------------------------------------------------------"
302 echo "nfsstat"
303 echo
304 nfsstat -M $VMCORE -N $KERNEL
305 echo
306
307 echo "------------------------------------------------------------------------"
308 echo "netstat -s"
309 echo
310 netstat -M $VMCORE -N $KERNEL -s
311 echo
312
313 echo "------------------------------------------------------------------------"
314 echo "netstat -m"
315 echo
316 netstat -M $VMCORE -N $KERNEL -m
317 echo
318
319 echo "------------------------------------------------------------------------"
320 echo "netstat -anA"
321 echo
322 netstat -M $VMCORE -N $KERNEL -anA
323 echo
324
325 echo "------------------------------------------------------------------------"
326 echo "netstat -aL"
327 echo
328 netstat -M $VMCORE -N $KERNEL -aL
329 echo
330
331 echo "------------------------------------------------------------------------"
332 echo "fstat"
333 echo
334 fstat -M $VMCORE -N $KERNEL
335 echo
336
337 echo "------------------------------------------------------------------------"
338 echo "dmesg"
339 echo
340 dmesg -a -M $VMCORE -N $KERNEL
341 echo
342
343 echo "------------------------------------------------------------------------"
344 echo "kernel config"
345 echo
346 config -x $KERNEL
347
348 echo
349 echo "------------------------------------------------------------------------"
350 echo "ddb capture buffer"
351 echo
352
353 ddb capture -M $VMCORE -N $KERNEL print