制造一个crash
 
为了演示的目的,我在libsensors的open_sensors_device中故意制造了一个crash:
 
static int open_sensors_device(const struct hw_module_t* module, const char* name,
        struct hw_device_t** device)
{
    int status = -EINVAL;
    //if our sensor system is ready,commented next line
    //return status;
 
    char* ptr = 0;
    *ptr = 0;
 
 
    // ....
}
        
这里ptr指向0地址,但后面却往这个0地址写0,因此会crash。crash时,logcat可以看到android打印的backtrace:
 
I/SystemServer( 1046): Sensor Service
I/DEBUG   (  971): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG   (  971): Build fingerprint: 'Questers/kylin/kylin/aspen168:2.2.1/FRG83/builder.20110307.131914:user/release-keys'
I/DEBUG   (  971): pid: 1046, tid: 1059  >>> system_server <<<
I/DEBUG   (  971): signal 11 (SIGSEGV), fault addr 00000000
I/DEBUG   (  971):  r0 8150218c  r1 81501250  r2 ae205500  r3 00000000
I/DEBUG   (  971):  r4 ae203d5b  r5 8150210c  r6 43891f6c  r7 42084eb0
I/DEBUG   (  971):  r8 4a570b80  r9 42084ea8  10 42084e94  fp 0011f3e0
I/DEBUG   (  971):  ip a7f0110c  sp 4a570b50  lr ae203247  pc 815009ba  cpsr a0000030
I/DEBUG   (  971):          #00  pc 000009ba  /system/lib/hw/sensors.default.so
I/DEBUG   (  971):          #01  pc 00003244  /system/lib/libandroid_servers.so
I/DEBUG   (  971):          #02  pc 00011cf4  /system/lib/libdvm.so
I/DEBUG   (  971):          #03  pc 0003f194  /system/lib/libdvm.so
I/DEBUG   (  971):          #04  pc 00016cb8  /system/lib/libdvm.so
I/DEBUG   (  971):          #05  pc 0001d604  /system/lib/libdvm.so
I/DEBUG   (  971):          #06  pc 0001c49c  /system/lib/libdvm.so
I/DEBUG   (  971):          #07  pc 00055374  /system/lib/libdvm.so
I/DEBUG   (  971):          #08  pc 0005558a  /system/lib/libdvm.so
I/DEBUG   (  971):          #09  pc 00049672  /system/lib/libdvm.so
I/DEBUG   (  971):          #10  pc 000113fc  /system/lib/libc.so
I/DEBUG   (  971):          #11  pc 00010ee0  /system/lib/libc.so
I/DEBUG   (  971): 
I/DEBUG   (  971): code around pc:
I/DEBUG   (  971): 81500998 600b189b 46c04770 00001772 fffffef4 
I/DEBUG   (  971): 815009a8 4d2bb5f0 492b1c0c b083447d 90012300 
I/DEBUG   (  971): 815009b8 701b1869 1c161c20 efa8f7ff d11f1e07 
I/DEBUG   (  971): 815009c8 f7ff205c 2100ef62 1c04225c ef92f7ff 
I/DEBUG   (  971): 815009d8 21014821 6562424a 60676020 4a20491f 
I/DEBUG   (  971): 
I/DEBUG   (  971): code around lr:
I/DEBUG   (  971): ae203224 b082480e 1820447c f7fea901 2800eaf6 
I/DEBUG   (  971): ae203234 9801d10f 4a0b490a 18616943 681b18a2 
I/DEBUG   (  971): ae203244 28004798 9801d105 1d034669 47a06fdc 
I/DEBUG   (  971): ae203254 2000e000 bd10b002 00001ee8 ffffec3f 
I/DEBUG   (  971): ae203264 ffffec47 000003ec 4e3db5f0 4c3d1c05 
I/DEBUG   (  971): 
I/DEBUG   (  971): stack:
I/DEBUG   (  971):     4a570b10  4a570b80  
I/DEBUG   (  971):     4a570b14  42084e74  
I/DEBUG   (  971):     4a570b18  0027be10  [heap]
I/DEBUG   (  971):     4a570b1c  0011f3e0  [heap]
I/DEBUG   (  971):     4a570b20  00000001  
I/DEBUG   (  971):     4a570b24  00000007  
I/DEBUG   (  971):     4a570b28  00000000  
I/DEBUG   (  971):     4a570b2c  00000000  
I/DEBUG   (  971):     4a570b30  420ce5c0  /dev/ashmem/dalvik-LinearAlloc (deleted)
I/DEBUG   (  971):     4a570b34  0011f3e0  [heap]
I/DEBUG   (  971):     4a570b38  0027be10  [heap]
I/DEBUG   (  971):     4a570b3c  422962b0  /dev/ashmem/dalvik-LinearAlloc (deleted)
I/DEBUG   (  971):     4a570b40  4a570bb0  
I/DEBUG   (  971):     4a570b44  000000d0  
I/DEBUG   (  971):     4a570b48  df002777  
I/DEBUG   (  971):     4a570b4c  e3a070ad  
I/DEBUG   (  971): #00 4a570b50  422962b0  /dev/ashmem/dalvik-LinearAlloc (deleted)
I/DEBUG   (  971):     4a570b54  8150218c  /system/lib/hw/sensors.default.so
I/DEBUG   (  971):     4a570b58  45d7fd20  /dev/ashmem/mspace/dalvik-heap/2 (deleted)
I/DEBUG   (  971):     4a570b5c  ae205114  /system/lib/libandroid_servers.so
I/DEBUG   (  971):     4a570b60  00000004  
I/DEBUG   (  971):     4a570b64  43891f6c  /data/dalvik-cache/system@framework@services.jar@classes.dex
I/DEBUG   (  971):     4a570b68  42084eb0  
I/DEBUG   (  971):     4a570b6c  ae203247  /system/lib/libandroid_servers.so
I/DEBUG   (  971): #01 4a570b70  438a922c  /data/dalvik-cache/system@framework@services.jar@classes.dex
I/DEBUG   (  971):     4a570b74  8150218c  /system/lib/hw/sensors.default.so
I/DEBUG   (  971):     4a570b78  4a570ba0  
I/DEBUG   (  971):     4a570b7c  aca11cf8  /system/lib/libdvm.so
D/Zygote  (  973): Process 1046 terminated by signal (11)
 
有用的信息
 
我们可以关注以下五处:
 
1. 哪个进程crash了
这里为/system/bin/system_server出了问题,它的pid为1046。
 
2. crash时cpu抛出的信号
比如这里是11(SEGV),表示段错误,一般为程序指令访问非法地址时产生。其它的信号的意义可以参考《Unix环境高级编程》。另外,这个数字和名字间的对应关系可以用kill -l列出:
 
# kill -l
 1    HUP Hangup                        17   CHLD Child exited            
 2    INT Interrupt                     18   CONT Continue                
 3   QUIT Quit                          19   STOP Stopped (signal)        
 4    ILL Illegal instruction           20   TSTP Stopped                 
 5   TRAP Trap                          21   TTIN Stopped (tty input)     
 6   ABRT Aborted                       22   TTOU Stopper (tty output)    
 7    BUS Bus error                     23    URG Urgent I/O condition    
 8    FPE Floating point exception      24   XCPU CPU time limit exceeded 
 9   KILL Killed                        25   XFSZ File size limit exceeded
10   USR1 User signal 1                 26 VTALRM Virtual timer expired   
11   SEGV Segmentation fault            27   PROF Profiling timer expired 
12   USR2 User signal 2                 28  WINCH Window size changed     
13   PIPE Broken pipe                   29     IO I/O possible            
14   ALRM Alarm clock                   30    PWR Power failure           
15   TERM Terminated                    31    SYS Bad system call         
16 STKFLT Stack fault     
 
3. 发生错误的地址
如上面的log打印出的“fault addr 00000000",表示cpu对这个地址作读写操作除了异常。NULL(0)地址为OS预留的地址,作指针初始化用途,不允许程序进行读写。
 
4. PC指针
如上面打印出的
 
#00  pc 000009ba  /system/lib/hw/sensors.default.so
#01  pc 00003244  /system/lib/libandroid_servers.so
表示出错时cpu的指令指针指向这个地址。可以用后面介绍的方法由地址找出代码位置。
 
5. 栈信息
android会dump出栈的内容。在unix/linux中,一般情况下栈会向低地址位置移动,android也不例外。在上面dump的信息中,越靠上(地址越小)表示这是栈顶位置,越往下表示栈底。
另外,dump的信息中有三列:
 
4a570b54  8150218c  /system/lib/hw/sensors.default.so
 
第一列:表示栈空间的地址。这里为4a570b54
第二列:这个栈单元中的内容。这里为8150218c
第三列:表示该内容对应的代码。若无text信息,则此处显示为空。这里为/system/lib/hw/sensors.default.so
最后需要注意的是,这里显示的地址为完整形式,即基地址+偏移量。基地址可以从/proc/<pid>/maps中看出(<pid>为crash进程对应的pid):
 
cat /proc/1059/maps | grep "sensors.default.so"
81500000-81502000 r-xp 00000000 00:0f 953        /system/lib/hw/sensors.default.so
81502000-81503000 rwxp 00002000 00:0f 953        /system/lib/hw/sensors.default.so
这里上面一行(不可写)为sensors.default.so的文本段,下一行为数据段(可读写)。可以看到sensors.default.so被映射到了system_server进程的81500000~81503000地址空间中。将代码完整地址8150218c减去基地址81500000,可以得到libc.so中的偏移地址0000218c。另外注意到,8150218c映射到数据段,说明出问题时栈保存有sensors.default.so中某一个函数中的局部变量。
 
由地址得到符号信息
 
给定一个地址,可以找出它对应的符号信息,以便分析。
 
找到大致的函数位置
guang@leave001:~/froyo_0308$ vendor/qsts/toolchain/arm-linux-4.1.1/bin/arm-linux-objdump -t out/target/product/kylin/symbols/system/lib/sensors.default.so | sort > list.txt
注意,这里需要找到out下symbols中的so文件,因为它的symbol信息没有被strip掉。list.txt中包含了按照地址排序的符号信息。根据sensors.default.so出错的地址000009ba,可以找到符号信息:
 
00000990 <sensors__get_sensors_list>:
000009a8 <open_sensors_device>:
00000a8c <pick_sensor>:
可以看到跟000009ba比较接近的地址为000009a8,因此可以判断出错的函数为open_sensors_device。
 
找出具体位置
objdump -t仅打印简单的信息。-S参数可以显示详细信息,输出中包含c和汇编代码:
 
guang@leave001:~/froyo_0308$ vendor/qsts/toolchain/arm-linux-4.1.1/bin/arm-linux-objdump -S out/target/product/kylin/symbols/system/lib/sensors.default.so > list.txt
在生成的list.txt中找到函数open_sensors_device,下面可以看到c代码和汇编:
 
static int open_sensors_device(const struct hw_module_t* module, const char* name,
        struct hw_device_t** device)
{
     9a8:   b5f0        push    {r4, r5, r6, r7, lr}
    int status = -EINVAL;
    //if our sensor system is ready,commented next line
    //return status;
 
    char* ptr = 0;
    *ptr = 0;
 
    if (!strcmp(name, SENSORS_HARDWARE_CONTROL)) {
     9aa:   4d2b        ldr r5, [pc, #172]  (a58 <.text+0xc8>)
     9ac:   1c0c        adds    r4, r1, #0
     9ae:   492b        ldr r1, [pc, #172]  (a5c <.text+0xcc>)
     9b0:   447d        add r5, pc
     9b2:   b083        sub sp, #12
     9b4:   2300        movs    r3, #0
     9b6:   9001        str r0, [sp, #4]
     9b8:   1869        adds    r1, r5, r1
     9ba:   701b        strb    r3, [r3, #0]
     9bc:   1c20        adds    r0, r4, #0
     9be:   1c16        adds    r6, r2, #0
     9c0:   f7ff efa8   blx 914 <.text-0x7c>
     9c4:   1e07        subs    r7, r0, #0
     9c6:   d11f        bne.n   a08 <open_sensors_device+0x60>
出错的地址为09ba,这里的汇编代码为
 
9ba:   701b        strb    r3, r3, #0
 
r3, #0意思是把常数0往r3保存的地址传送,而r3在前面被初始化为0地址,因此可以判断出是上面的c代码出了问题。
 
不幸的是,对于c++生成的so,输出的汇编和c代码跟地址对不上,因此不容易找到具体位置。还有,有时出错的原因不容易从上面的方法分析出来,这时只能借助这个方法来缩小代码范围,通过打印和检视代码来慢慢分析。

What should we do when meet a crash in android?的更多相关文章

  1. Android程序crash处理

    Android程序crash处理 时间 2014-11-24 13:45:37  CSDN博客 原文  http://blog.csdn.net/allen315410/article/details ...

  2. Android Crash 定位

    本文介绍了如何在 Android 手机发生 Crash 时进行 Log 分析的方法, 它可以帮助测试人员快速定位 Android 手机 Crash 发生的原因,同时给研发人员提供有效修改 Bug 的 ...

  3. 阿里提前批校招内推offer经历

    经过一个半月的阿里内推面试,今天终于收到了阿里的offer邮件 .阿里的内推面试一共有四轮,本人是7月19号投的内推邮件,8月28号收到了offer的邮件.首先本人谈谈内推的看法.内推是公司招聘人才的 ...

  4. Android中处理崩溃异常

    转自:http://my.eoe.cn/817027/archive/17997.html 大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不 ...

  5. Android中处理崩溃异常和记录日志

    大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了 ...

  6. Material Design使用记录

    出现过的问题记录: 1.Crash on Android 6.0 in RippleView.draw() 解决方法: This has very simple solution. Just down ...

  7. 【Bugly干货】关于 Android N 那些你不知道的事儿

    今年3月,Google 破天荒提前半年发布了 Android N 开发者预览版.当然,作为一个不合格的谷粉并没有第一时间体验安装,因为至今仍然能够回忆起来去年今日此门中(雾)兴冲冲刷了 Android ...

  8. Android中处理崩溃异常CrashHandler

    来源:http://blog.csdn.net/liuhe688/article/details/6584143 大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程 ...

  9. 常见Android Native崩溃及错误原因

    http://www.droidsec.cn/%E5%B8%B8%E8%A7%81android-native%E5%B4%A9%E6%BA%83%E5%8F%8A%E9%94%99%E8%AF%AF ...

随机推荐

  1. 2016-XCTF Final-Richman

    抽时间将XCTF Final中Richman这个题总结了下.题目及ida idb所在的链接在:http://files.cnblogs.com/files/wangaohui/richman-blog ...

  2. java序列化ClassNotFoundException

    简单的想从保存的对象中重新解析出对象,用了逆序列化,可是报错: java.lang.ClassNotFoundException: xxxxxxxxxxxx at java.net.URLClassL ...

  3. web验证码

    前台引用.aspx: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="YanZh ...

  4. 新浪微博客户端开发之OAuth认证篇

    新浪微博客户端开发之OAuth认证篇 2013年7月29日新浪微博客户端开发 OAuth2.0授权机制我在这里就不浪费口舌了,有很多大牛都发表过相关的文章解释OAuth2.0认证的流程,我就随便找了一 ...

  5. Scrapinghub执行spider抓取并显示图片

    序 最近在学习Scrapy的时候发现一个很有意思的网站,可以托管Spider,也可以设置定时抓取的任务,相当方便.于是研究了一下,把其中比较有意思的功能分享一下: 抓取图片并显示在item里: 下面来 ...

  6. python笔记之hashlib模块

    涉及加密服务:14. Cryptographic Services其中 hashlib是涉及安全散列和消息摘要,提供多个不同的加密算法借口,如SHA1.SHA224.SHA256.SHA384.SHA ...

  7. LFS,编译自己的Linux系统 - 完成准备工作

    $LFS 确保环境变量$LFS已被定义. 定义:export LFS=/mnt/lfs 检查:echo $LFS 建立目录 $LFS/tools $LFS/tools目录用于存放和编译一些临时使用的工 ...

  8. GTW likes gt(BC 模拟 or 优先队列)

    GTW likes gt Accepts: 54 Submissions: 782 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 13107 ...

  9. TEA加密算法的文件加密和解密的实现

    一.TEA加密算法简介 TEA加密算法是由英国剑桥大学计算机实验室提出的一种对称分组加密算法.它采用扩散和混乱方法,对64位的明文数据块,用128位密钥分组进行加密,产生64位的密文数据块,其循环轮数 ...

  10. TEA加密

    TEA(Tiny Encryption Algorithm)是一种小型的对称加密解密算法,支持128位密码,与BlowFish一样TEA每次只能加密/解密8字节数据.TEA特点是速度快.效率高,实现也 ...