zoukankan      html  css  js  c++  java
  • What should we do when meet a crash in android?

    制造一个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代码跟地址对不上,因此不容易找到具体位置。还有,有时出错的原因不容易从上面的方法分析出来,这时只能借助这个方法来缩小代码范围,通过打印和检视代码来慢慢分析。
  • 相关阅读:
    深入Android 【一】 —— 序及开篇
    Android中ContentProvider和ContentResolver使用入门
    深入Android 【六】 —— 界面构造
    The service cannot be activated because it does not support ASP.NET compatibility. ASP.NET compatibility is enabled for this application. Turn off ASP.NET compatibility mode in the web.config or add the AspNetCompatibilityRequirements attribute to the ser
    Dynamic Business代码片段总结
    对文件的BuildAction以content,resource两种方式的读取
    paraview 3.12.0 windows下编译成功 小记
    百度网盘PanDownload使用Aria2满速下载
    netdata的安装与使用
    用PS给证件照排版教程
  • 原文地址:https://www.cnblogs.com/shakin/p/4268397.html
Copyright © 2011-2022 走看看