android crash / debug 堆栈信息

堆栈错误信息:

I/DEBUG   (   30): r0 afd4d4a4  r1 ffffffff  r2 7fffffff r3 afd4d4a4

I/DEBUG   (   30): r4 00000000  r5 ffffffff  r6 00000001 r7 be9f6ccc

I/DEBUG   (   30): r8 00000000  r9 00000000  10 00000000 fp 00000000

I/DEBUG   (   30): ip afd11fcd  sp be9f6c38  lr afd107f4 pc afd107fc  cpsr 80000010

I/DEBUG   (   30):         #00  pc 000107fc  /system/lib/libc.so

I/DEBUG   (   30):         #01  pc 0001ccfe  /system/lib/libdtvservice.so

I/DEBUG   (   30):         #02  pc 0001c646  /system/lib/libdtvservice.so

I/DEBUG   (   30):         #03  pc 0001937e  /system/lib/libdtvservice.so

I/DEBUG   (   30):         #04  pc 000110f8  /system/lib/libdtvservice.so

I/DEBUG   (   30):         #05  pc 000115a8 /system/lib/libdtvservice.so

I/DEBUG   (   30):         #06  pc 00008852  /system/bin/dtvserver

I/DEBUG   (   30):         #07  pc 00014dc8  /system/lib/libc.so

 

……

方法一:

1.将上面这段信息复制到一个新建的文件中,并保存。例如:test-dtvserver.txt.

 

2.用panic.py工具解析这段错误信息,panic.py工具的位置为~/android/

// 工具在附件中

运行:

[maw@localhost android]$ panic.py  test-stack.txt

read file ok

stop search

pr-support.c:258              __gnu_unwind_execute

posix_thread.c:97             destroy_posix_thread

thread.c:293                  thread_destroy

workpool.c:215                work_pool_uninitialize

dtvserver.c:203               dtvs_finalize

dtvserver.c:179               dtvs_initialize

DtvServer.cpp:19              main

dlmalloc.c:3890               tmalloc_small

 

这个就是结果。

 

使用panic.py的环境问题

 

1.要有arm-eabi-addr2line工具   ~/android/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/

2.在system/lib/中要有相应的库文件

3.panic.py的存放位置要正确~/android/,也可以自己修改panic.py工具的代码,放在其他地方.

 

 

方法二:

如果没有arm-eabi-addr2line工具,但是有arm-eabi-objdump工具

就用第二种方法。

I/DEBUG   (   30):         #00  pc 000107fc  /system/lib/libc.so

I/DEBUG   (   30):         #01  pc 0001ccfe  /system/lib/libdtvservice.so

I/DEBUG   (   30):         #02  pc 0001c646  /system/lib/libdtvservice.so

I/DEBUG   (   30):         #03  pc 0001937e  /system/lib/libdtvservice.so

I/DEBUG   (   30):         #04  pc 000110f8  /system/lib/libdtvservice.so

I/DEBUG   (   30):         #05  pc 000115a8  /system/lib/libdtvservice.so

I/DEBUG   (   30):         #06  pc 00008852  /system/bin/dtvserver

I/DEBUG   (   30):         #07  pc 00014dc8  /system/lib/libc.so

 

1.用objdump工具将上面这些对应的库文件反汇编:

运行:arm-eabi-objdump –dS libc.so > libc.dump

//这些库文件路径在out/target/product/generic/obj/SHARED_LIBRARIES/ 

 

2.打开反汇编后的库文件。例如:libc.dump。

找到上面错误码提示的地址。例如000107fc。

在这里我们可以找到这行指令所在的函数和文件

以此类推,依次找出这些错误码对应的函数和文件,就可以知道是哪一个函数调用路线出问题了。

 

panic.py代码

#!/usr/bin/python

# stack symbol parser

 

import os

import string

import sys

 

#define android product name 这个视情况而定在out/target/product文件夹下

ANDROID_PRODUCT_NAME = 'generic'

#ANDROID_PRODUCT_NAME = 'smdk6410'

 

#这里可以修改panic.py工具的存放位置

ANDROID_WORKSPACE = os.getcwd()+"/"

 

# addr2line tool path and symbol path

addr2line_tool = ANDROID_WORKSPACE +'prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-addr2line'

symbol_dir = ANDROID_WORKSPACE + 'out/target/product/'+ ANDROID_PRODUCT_NAME +'/symbols'

symbol_bin = symbol_dir + '/system/bin/'

symbol_lib = symbol_dir + '/system/lib/'

 

class ReadLog:

    def__init__(self,filename):

       self.logname = filename

    defparse(self):

        f =file(self.logname,'r')

        lines =f.readlines()

        if lines!= []:

           print 'read file ok'

        else:

           print 'read file failed'

        result=[]

        for linein lines:

            ifline.find('stack') != -1:

               print 'stop search'

                break

            elifline.find('system') != -1:

               #print 'find one item' + line

               result.append(line)

        returnresult

 

class ParseContent:

    def__init__(self,addr,lib):

           self.address = addr # pc address

           self.exename = lib  # executableor shared library

    defaddr2line(self):

        cmd =addr2line_tool + " -C -f -s -e " + symbol_dir + self.exename + "" + self.address

        #printcmd

        stream =os.popen(cmd)

        lines =stream.readlines();

        list =map(string.strip,lines)

        returnlist

 

inputarg = sys.argv

if len(inputarg) < 2:

    print'Please input panic log'

    exit()

 

filename = inputarg[1]

readlog = ReadLog(filename)

inputlist = readlog.parse()

 

for item in inputlist:

    itemsplit =item.split()

    test =ParseContent(itemsplit[-2],itemsplit[-1])

    list =test.addr2line()

    print"%-30s%s" % (list[1],list[0])


#usage panic.py crash Log > result.txt


如果提示 /usr/bin/python ^M:损坏的解释器:没有该文件或者目录的话,执行一下:dos2unix panic.py 转换一下格式即可。


反汇编pc指针附近代码

有时我们在log中看不到这样明显的调用栈信息,比如出现了dalvik-jit-code-cache,如下:

10-15 01:32:56.759 I/DEBUG   (   93):          #00  pc 47aac03c  /dev/ashmem/dalvik-jit-code-cache (deleted) 10-15 01:32:56.769 I/DEBUG   (   93):          #01  lr 47ab7817  /dev/ashmem/dalvik-jit-code-cache (deleted) 

这样,就没有办法用前面的方法来分析调用栈了。还好google提供了另一个方法来分析问题。虽然有点麻烦。

它的原理,就是将pc附件的指令放到某个程序的内存中,然后进行gdb调试来进行反汇编。

要使用gdbjithelper(位于dalvik/tools/gdbjithelper)将pr和lr附近的cache code反汇编。下面来介绍一下。

首先,打开gdbjithelper.c,可以看到如下代码

int codePC[] = {     
// Sample content     
0x4300e119, 0x4284aa7a, 0xf927f7b7, 0x40112268,     0x419da7f8, 0x00002000, 0x01000100, 0x00080000,     0x4191debc, 0x01010000, 0x4284aa74, 0x68b00054,     0x045cf205, 0xcc016468, 0x0718f2a5, 0xd0102800,     0x4c13c701, 0xa20aa108, 0xefb0f775, 0xe008e010, }; 

将log信息中对应部分

10-15 01:32:56.769 I/DEBUG   (   93): code around pc: 
10-15 01:32:56.769 I/DEBUG   (   93): 47aac01c  e12fff1e e3a00001 e12fff1e e2450014 
10-15 01:32:56.769 I/DEBUG   (   93): 47aac02c e590a000 e5968024 e5904004 e5909010 
10-15 01:32:56.769 I/DEBUG   (   93): 47aac03c e51a200c e5963018 e3520000 0a00000e 
10-15 01:32:56.769 I/DEBUG   (   93): 47aac04c e59f1738 e1a0500a 1592a000 e5988000 
10-15 01:32:56.769 I/DEBUG   (   93): 47aac05c e5862010 e59a0028 e5835028 e2844006  

编辑为类似代码,替换掉,然后修改

#define START_PC_PAGE_OFFSET 0x1e4 

改为

#define START_PC_PAGE_OFFSET 0x01c 

修改的原理是code around pc的开始地址(0x47aac01c & 0xfff)

同理,修改codeLR和START_LR_PAGE_OFFSET

修改完成后,使用模块编译 mmm dalvik/tools/gdbjithelper,将编译好的gdbjithelper push到一台手机上/system/bin 进行调试。

连接设备后,执行步骤如下:

shell> adb shell gdbserver :5039 /path/to/gdbjithelper #设备路径 
shell> adb forward tcp:5039 tcp:5039 
shell> cd ${环境根目录}/ 
shell> prebuilt/Linux/toolchain-eabi-4.2.1/bin/arm-eabi-gdb /path/to/gdbjithelper #PC路径 
(gdb) set solib-absolute-prefix out/target/product/${product-name}/symbols     #告诉gdb查找共享库符号等路径 
(gdb) set solib-search-path out/target/product/${product-name}/symbols/system/lib #告诉gdb查找共享库符号等路径 (gdb) target remote :5039 
(gdb) run 会出现类似下面的输出信息: 0xb01c codePC[0]: 0xe12fff1e 0xb020 codePC[1]: 0xe3a00001 0xb024 codePC[2]: 0xe12fff1e 0xb028 codePC[3]: 0xe2450014 0xb02c codePC[4]: 0xe590a000 0xb030 codePC[5]: 0xe5968024 0xb034 codePC[6]: 0xe5904004 0xb038 codePC[7]: 0xe5909010 0xb03c codePC[8]: 0xe51a200c 0xb040 codePC[9]: 0xe5963018 0xb044 codePC[10]: 0xe3520000 0xb048 codePC[11]: 0x0a00000e 0xb04c codePC[12]: 0xe59f1738 0xb050 codePC[13]: 0xe1a0500a 0xb054 codePC[14]: 0x1592a000 0xb058 codePC[15]: 0xe5988000  0xb05c codePC[16]: 0xe5862010 0xb060 codePC[17]: 0xe59a0028 0xb064 codePC[18]: 0xe5835028 0xb068 codePC[19]: 0xe2844006 
(gdb) x /20i 0xb01c+1 //输出反汇编结果 x/20i (char *)&CodePC+1 ,查看LR 结果 x/20i (char*)&codeLR+1
0xb01d:        vrhadd.u16        d14, d14, d31 
0xb021:        lsls        r1, r0, #0 
0xb023:        b.n        0xb766 
0xb025:        vrhadd.u16        d14, d14, d31 
0xb029:        lsls        r4, r2, #0 
0xb02b:        b.n        0xb4b8 
0xb02d:        add        r0, pc, #0        (adr r0,0xb030) 
0xb02f:        b.n        0xab52 
0xb031:        strh        r4, [r4, #0] 
0xb033:        b.n        0xab62 
0xb035:        ands        r4, r0 
0xb037:        b.n        0xab5a 
0xb039:        str        r0, [sp, #64] 
0xb03b:        b.n        0xab5e            //pc指向,实际跳转地址为0x47aabb5e (0x47aac03c-0xb03c+0xab5e) 0xb03d:        movs        r0, #12 
0xb03f:        b.n        0xaa76 
0xb041:        adds        r0, #24 
0xb043:        b.n        0xab72 
0xb045:        lsls        r0, r0, #0 
0xb047:        b.n        0xb6ee 

类似,codeLR也是这样反汇编的 之后就可以对结果进行分析了。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值