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