制造一个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程序crash处理
Android程序crash处理 时间 2014-11-24 13:45:37 CSDN博客 原文 http://blog.csdn.net/allen315410/article/details ...
- Android Crash 定位
本文介绍了如何在 Android 手机发生 Crash 时进行 Log 分析的方法, 它可以帮助测试人员快速定位 Android 手机 Crash 发生的原因,同时给研发人员提供有效修改 Bug 的 ...
- 阿里提前批校招内推offer经历
经过一个半月的阿里内推面试,今天终于收到了阿里的offer邮件 .阿里的内推面试一共有四轮,本人是7月19号投的内推邮件,8月28号收到了offer的邮件.首先本人谈谈内推的看法.内推是公司招聘人才的 ...
- Android中处理崩溃异常
转自:http://my.eoe.cn/817027/archive/17997.html 大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不 ...
- Android中处理崩溃异常和记录日志
大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了 ...
- Material Design使用记录
出现过的问题记录: 1.Crash on Android 6.0 in RippleView.draw() 解决方法: This has very simple solution. Just down ...
- 【Bugly干货】关于 Android N 那些你不知道的事儿
今年3月,Google 破天荒提前半年发布了 Android N 开发者预览版.当然,作为一个不合格的谷粉并没有第一时间体验安装,因为至今仍然能够回忆起来去年今日此门中(雾)兴冲冲刷了 Android ...
- Android中处理崩溃异常CrashHandler
来源:http://blog.csdn.net/liuhe688/article/details/6584143 大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程 ...
- 常见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 ...
随机推荐
- UIImage与UIColor互转
Objective-C UIColor -> UIImage ? 1 2 3 4 5 6 7 8 9 10 11 - (UIImage*) createImageWithColor: (UICo ...
- C++入门学习——标准模板库之vector
vector(向量容器),是 C++ 中十分实用一个容器.vector 之所以被觉得是一个容器,是由于它可以像容器一样存放各种类型的对象,简单地说,vector 是一个可以存放随意类型(类型可以是in ...
- 2. QT窗体间值的传递
一.主窗体与子窗体传参 方法有很多,这里介绍一种通过重载子窗体的构造函数实现主窗体参数传入到子窗体,并通过QT信号和槽的机制实现子窗口到主窗口值的传递. 主和子窗体的设置如下: 主要实现功能为: 1 ...
- 将集合类转换成DataTable
/// <summary> /// 将集合类转换成DataTale /// </summary> /// <param name="list"> ...
- Android界面优化方法
我们在推出一款APP之后,中间出现了一些体验上的问题,一个明显的是界面卡顿,针对此问题我们采取了如下的一些措施,起到了一些效果. 1.优化界面层次 针对可以合并的界面层次进行合并,减少界面的渲染,这个 ...
- Apache 2.4.7在CentOS6.4中安装配置反向代理解决单外网IP对应多个内网主机的方法实践
欢迎转载,转载时请保留全文及出处. Apache 2.4.7在CentOS6.4中安装配置反向代理解决单外网IP对应多个内网主机的方法实践 Apache安装 下载源程序(http://httpd.ap ...
- UITextView(文本视图) 学习之初体验
UITextView文本视图相比与UITextField直观的区别就是UITextView可以输入多行文字并且可以滚动显示浏览全文.常见UITextView使用在APP的软件简介.内容详情显示.小说阅 ...
- HttpClient中异步方法的同步调用
在System.Net.Http中,提供了使用Http与远程服务器通讯的httpClient,但是里面都是异步方法,有时候我们并不需要使用异步操作.这个时候可以使用如下的方式来进行同步调用. clas ...
- HDU 1556 Color the ball - from lanshui_Yang
Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a ...
- Windows,Linux换行知识
换行符在写文件的时候用得上 Linux: "\n"Windows: "\r\n" 注意:换行符一定要加上双引号,单引号是没有用的.