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