Decoding U-Boot crash

来源:互联网 发布:2345电脑软件软件大全 编辑:程序博客网 时间:2024/04/27 20:07

首先说明本文是博文《Linux内核调试技术 - 基础篇》的一部分,为了清晰先将篇幅比较大的单独成文。


在U-Boot中碰到U-Boot崩溃的情况怎么办?可使用本文介绍的script来定位到是什么引起的crash。


下面是当时的邮件,介绍了怎么使用该script:


When U-Boot crashes and prints a register dump and a stack trace, you can

use this script to decode the stack backtrace and find out what happened.


This tool is modified according the following link:

 

http://www.denx.de/wiki/view/DULG/DecodingUBootCrashDumps

 

 Example:

 

NIP:1FF7859C XER: 00000000 LR: 1FF78578 REGS: 1fe3dbd8 TRAP: 0d00 DAR: DEADBF8B
MSR: 00021200 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00

 

GPR00:DEADBEEF 1FE3DCC8 1FE3DF64 00000000 00000000 0000006C 00000003 1FFB490C
GPR08: 00001221 DEADBEEF 1FFB490C 1FFC146C FFFFDEAC 05F5C800 1FFB1800 26FBF000
GPR16: 0002E024 80000001 00000000 000000BC 00000026 00000200 6ECCB7C9 00000000
GPR24: 00002020 000003F8 100F0000 1FE3DF4C 00000000 08000000 1FFB3464 1FE3DEF8
Call backtrace:
1FF9BE00 1FF6B6A4 1FF61240 1FF61194 1FF43920 1FF415FC
Exception in kernel pc 1ff7859c signal 0
### ERROR ### Please RESET the board ###

 

copy the line under "Call backtrace" to file calltrace, then run thescript:

 

u-boot$./backtrace System.map calltrace 0xf8f81000 0x1ff40000
Reading symbols from System.map
Reading calltrace from calltrace
Using Address Offset 0xd9041000
0xf8fdce00 -- 0xf8fdc2a4 + 0x0b5c   _etext
0xf8fac6a4 -- 0xf8fac688 + 0x001c   mmc_get_env_addr
0xf8fa2240 -- 0xf8fa2214 + 0x002c   env_relocate_spec
0xf8fa2194 -- 0xf8fa213c + 0x0058   env_relocate
0xf8f84920 -- 0xf8f847b4 + 0x016c   board_init_r
0xf8f825fc -- 0xf8f825fc + 0x0000   trap_init


Script:

#!/usr/bin/perl -wif ($#ARGV < 3) {        print "Usage:\n";        print "./backstrace System.map calltrace TEXT_BASE reloc_off\n";        print "\tSystem.map: the map file\n";        print "\tcalltrace : the call trace info\n";        print "\tTEXT_BASE : the U-Boot image's TEXT_BASE\n";        print "\treloc_off : the relocation address in RAM\n";        die;}# get system.map filemy $mapfile = shift || ( (-r 'System.map')                         ? 'System.map'                         : '/LinuxPPC/usr/src/linux/System.map' );print STDERR "Reading symbols from $mapfile\n";# get calltrace info filemy $strace = shift;print STDERR "Reading calltrace from $strace\n";# get TEXT_BASEmy $text_base = eval (shift || 0);print "Error: $@" if $@;# get relocation addressmy $reloc_off = eval (shift || 0);print "Error: $@" if $@;my $reloc = $text_base - $reloc_off;printf STDERR "Using Address Offset 0x%08lx\n", $reloc;## Read symbol table#open (MAP, $mapfile) or die "Can't open $mapfile: $!\n";my $cnt = 0;while (<MAP>) {        chomp;        my ($a,$t,$n) = split;        $a = eval ('0x' . $a);        if (($t =~ /^t$/i)      ||            ($n eq '_etext')    ||            ($n eq '_erotext')  ||            ($n eq '_end')      ) {                $addr[$cnt] = $a;                $name[$cnt] = $n;                ++$cnt;        }}close MAP;my ($i, $n, $last);## Now get backtrace info from call strace file#open (STRACE, $strace) or die "Can't open $strace: $!\n";while (<STRACE>) {        chomp;        # = split /\s+/, $_;        my @a = split;        my $aa;        for ($i=0; $i<=$#a; ++$i) {                $aa = eval ('0x' . $a[$i]) + $reloc;                $last = -1;                for ($n=0; $n<$cnt; ++$n) {                        if ($addr[$n] > $aa) {                                last;                        }                        $last = $n;                }                if ($last >= 0) {                        my $offset = $aa - $addr[$last];                        printf "0x%08x -- 0x%08x + 0x%04x   %s\n",                                $aa, $addr[$last], $offset, $name[$last];                } else {                        printf "0x%08x -- unknown address\n", $aa;                }        }}close STRACE;