#!/usr/bin/perl
## $Id: bt2line,v 1.6 2012/08/23 07:37:07 pdc Exp $

$kern='/boot/kernel/kernel';

sub read_nm($) {
	my $symfile=shift;
	print "Reading symbol file: $symfile\n";
	@NM=`nm $symfile`;
	for(@NM) {
		chomp;
		($addr,$type,$sym)=split / +/,$_,3;
		next if $type ne 'T' && $sym=~/_AcpiModuleName|^__Tunable_in|^__func__|^__set/i;
		$COUNT{$sym}++;
		if(!defined $ADDR{$sym} ) {
			$ADDR{$sym}=$addr;
			$TYPE{$sym}=$type;
			$FILE{$sym}=$symfile;
			
		} else {
			print STDERR "$sym $type $addr was already at $ADDR{$sym} $TYPE{$sym} $FILE{$sym}\n"	if $verbose;
		}
	}	
}

if($#ARGV >= 0) {	
	while(($symfile=shift) ne '') {
		read_nm($symfile);
	}
} else {
	read_nm($kern);
}

$verbose=0;


if($list_all) {
for $sym (sort keys %ADDR) {
	$addr=$ADDR{$sym};
	print "$addr\t$sym\n";
}}

$varname=qr'([a-z_0-9]+)'i;
$hexnum=qr'(0x[0-9a-f]+)'i;

print STDERR "Reading backtrace from stdin...\n";

while(<STDIN>) {
	chomp;
	if(/^(?:.+ kernel: )?${varname}\(([^)]*)\) at (?:$hexnum = )?${varname}\+$hexnum/) {
		($func,$parm,$addr,$sym,$off1)=($1,$2,$3,$4,$5);
		print "\n>> [$func($parm) $addr,$sym+$off1] $_\n";

		my $addr1=undef;
		if(defined $addr) { $addr1=$addr } 
		else { $addr1=$ADDR{$sym}; };

		if(defined $addr1) {
			$addr2=sprintf '%x',hex($addr1)+hex($off1);
			$file2=$FILE{$sym};
			print "\n>> $func ($parm) @ $sym=$addr1 + $off1 == $addr2\n";
			system "addr2line -e $file2 -f $addr2";
			print "Warning: $COUNT{$sym} symbols found\n" if $COUNT{$sym}>1;
		} else {
			print "\n>> $_\n";
			print "Unknown symbol: $sym\n";
		}
	} else {
		print "\n" if /Tracing command /;
		print "\n>> $_";
	}
}

__END__

db:0:kdb.enter.panic>  bt
Tracing pid 2819 tid 100125 td 0x88c878a0
kdb_enter(80a0e225,80a0e225,80a186dd,d6780840,d6780840,...) at kdb_enter+0x3a
panic(80a186dd,346,0,d67808b8,0,...) at panic+0xd1
soabort(88961670,80a2dc03,346,0,0,...) at soabort+0x1b
syncache_expand(d6780a60,d6780a40,8c78cb5c,d6780a5c,8c78cb00,...) at syncache_expand+0xdb3
tcp_input(8c78cb00,14,86c17800,1,0,...) at tcp_input+0xc49
ip_input(8c78cb00,4,80a0c98c,109,24,...) at ip_input+0x65b
netisr_dispatch_src(1,0,8c78cb00,d6780b34,80766ae1,...) at netisr_dispatch_src+0xd1
netisr_dispatch(1,8c78cb00,0,86c17800,8c78cb3a,...) at netisr_dispatch+0x20
ether_demux(86c17800,8c78cb00,3,0,3,...) at ether_demux+0x1a1
ether_input(86c16400,8c78cb00,6,2,2,...) at ether_input+0x393
tapwrite(88b85d00,d6780c28,0,0,0,...) at tapwrite+0xef
devfs_write_f(89f7c8c0,d6780c28,8686cb80,0,88c878a0,...) at devfs_write_f+0xac
dofilewrite(d6780c28,ffffffff,ffffffff,0,89f7c8c0,...) at dofilewrite+0x95
kern_writev(88c878a0,5,d6780c28,d6780c48,1,...) at kern_writev+0x58
write(88c878a0,d6780cec,d6780d28,80a12db8,0,...) at write+0x4f
syscallenter(88c878a0,d6780ce4,d6780ce4,0,806d4a26,...) at syscallenter+0x246
syscall(d6780d28) at syscall+0x34
Xint0x80_syscall() at Xint0x80_syscall+0x21
--- syscall (4, FreeBSD ELF32, write), eip = 0x28324d2b, esp = 0x7fbfeb2c, ebp = 0x7fbfec08 ---


Aug 11 22:13:29 <kern.crit> cel kernel: lock order reversal:
Aug 11 22:13:29 <kern.crit> cel kernel: 1st 0xfffffe0137ecc810 lle (lle) @ /usr/src/sys/netinet/in.c:1519
Aug 11 22:13:29 <kern.crit> cel kernel: 2nd 0xffffffff80df32f0 IPFW static rules (IPFW static rules) @ /usr/src/sys/netinet/ipfw/ip_fw2.c:1190
Aug 11 22:13:29 <kern.crit> cel kernel: KDB: stack backtrace:
Aug 11 22:13:29 <kern.crit> cel kernel: db_trace_self_wrapper() at db_trace_self_wrapper+0x2a
Aug 11 22:13:29 <kern.crit> cel kernel: kdb_backtrace() at kdb_backtrace+0x37
Aug 11 22:13:29 <kern.crit> cel kernel: _witness_debugger() at _witness_debugger+0x65
Aug 11 22:13:29 <kern.crit> cel kernel: witness_checkorder() at witness_checkorder+0x833
Aug 11 22:13:29 <kern.crit> cel kernel: _rw_rlock() at _rw_rlock+0x6d
Aug 11 22:13:29 <kern.crit> cel kernel: ipfw_chk() at ipfw_chk+0x18e
Aug 11 22:13:29 <kern.crit> cel kernel: ether_ipfw_chk() at ether_ipfw_chk+0x13a
Aug 11 22:13:29 <kern.crit> cel kernel: ether_output_frame() at ether_output_frame+0x4e
Aug 11 22:13:29 <kern.crit> cel kernel: ether_output() at ether_output+0x5a1
Aug 11 22:13:29 <kern.crit> cel kernel: arprequest() at arprequest+0x148
Aug 11 22:13:29 <kern.crit> cel kernel: arpresolve() at arpresolve+0x55f
Aug 11 22:13:29 <kern.crit> cel kernel: ether_output() at ether_output+0x2c0
Aug 11 22:13:29 <kern.crit> cel kernel: ip_output() at ip_output+0xe89
Aug 11 22:13:29 <kern.crit> cel kernel: dummynet_send() at dummynet_send+0x13c
Aug 11 22:13:29 <kern.crit> cel kernel: dummynet_task() at dummynet_task+0x1ae
Aug 11 22:13:29 <kern.crit> cel kernel: taskqueue_run_locked() at taskqueue_run_locked+0x93
Aug 11 22:13:29 <kern.crit> cel kernel: taskqueue_thread_loop() at taskqueue_thread_loop+0x3e
Aug 11 22:13:29 <kern.crit> cel kernel: fork_exit() at fork_exit+0x135
Aug 11 22:13:29 <kern.crit> cel kernel: fork_trampoline() at fork_trampoline+0xe
Aug 11 22:13:29 <kern.crit> cel kernel: --- trap 0, rip = 0, rsp = 0xffffff81527fad00, rbp = 0 ---


bt2line /boot/kernel/kernel /boot/kernel/geom_cache.ko < ddb.txt | less