日期:2014-05-16 浏览次数:20776 次
玩linux系统,经常遇到的一件事就是做了某个操作之后系统会突然挂掉,这要怎么办?
1. 首先我们要看log,看看是否会留下一些蛛丝马迹,比如PC/LR是否有留下来。
PC是ARM的一个寄存器,即程序计数器,他记下的是当前程序执行的位置;
LR是link register,它保存的是当前函数的返回地址,
所以我们可以善用PC/LR来帮助我们查找问题的根源。
2. 假设我们知道系统挂掉时的PC值,同时我们要知道你的系统中挂掉的process是哪一个,
这样再使用ps aux | grep my_process获取这个process的pid。
获得了process的pid,我们可以使用cat /proc/pid/maps > ./pid_maps获取该procss的虚拟地址空间。
注意每一个用户process的虚拟地址空间都可能不一样,因为虚拟地址空间的关系,
在系统中每一个用户process都认为自己是系统中唯一的一个process。
3. 因为我们有了PC值,所以接下来在pid_maps中找到PC值位于哪一个shared library中,
也就是说系统挂掉的点是在哪个.so中挂掉。此时我们根据PC值结合这只挂掉的libtest.so
计算出在libtest.so中的偏移量。
4. readelf -a ./libtest.so | grep offset
或者nm ./libtest.so | grep offset
或者objdump -d libtest.so > libtest_disassemble.txt(建议使用objdump反汇编)
来查看offset对应的代码中的位置。
5. 结合源代码进行分析,找到系统挂掉的具体位置。
使用这种方法的缺点是:
1. 如果系统挂掉时已经破坏了线程栈,那利用PC值分析的意义不大;
2. 如果系统是挂在内核空间,那也无法确认问题点,除非能够恢复出用户空间的线程栈。
关于下面这几个问题点,稍后会做简单的介绍。
readelf
nm
objdump
为什么是取偏移量?