ceph存储 dmesg和addr2line分析bug以及so动态库崩溃示例

Addr2line 工具(它是标准的 GNU Binutils 中的一部分)是一个可以将指令的地址和可执行映像转换成文件名、函数名和源代码行数的工具。这种功能对于将跟踪地址转换成更有意义的内容来说简直是太棒了

1.       首先把你编译的库文件中的LINK目录对象的so库放到手机里,

addr2line工具的使用 - 宁静致远 - 宁静致远的博客

 

2.       当出错是查看LogPC 的信息

3.       执行在LINKED目录下有运行

命令:addr2line –f –e xxx.so 地址

addr2line工具的使用 - 宁静致远 - 宁静致远的博客

在调用 Addr2line 工具时,要使用 -e 选项来指定可执行映像是 test。通过使用 -f 选项,可以告诉工具输出函数名


Linux下写C/C++程序的程序员,时常与Core Dump相见。在内存越界访问,收到不能处理的信号,除零等错误出现时,我们精心或不精心写就的程序就直接一命呜呼了,Core Dump是Linux仁慈地留下的程序的尸体,帮助程序员们解决了一个又一个问题。

有时配置不给力,Linux直接毁尸灭迹,没有了Core文件;又有时,刚好磁盘空间不足,Core文件写不下了。没有Core文件的时候,如何知道程序在什么地方出错了呢?addr2line就在这时派上用场。

这是一个示例程序,func函数返回参数a除以参数b的结果。这里使用0作为除数,结果就是程序因为除以0导致错误,直接中断了。


[cpp] view plain copy
  1. #include <stdio.h>  
  2.   
  3. int func(int a, int b)  
  4. {  
  5.   return a / b;  
  6. }  
  7.   
  8. int main()  
  9. {  
  10.   int x = 10;  
  11.   int y = 0;  
  12.   printf("%d / %d = %d\n", x, y, func(x, y));  
  13.   return 0;  
  14. }  

 

使用

$ gcc -o test1 -g test1.c

编译程序,test1.c是程序文件名。执行程序,结果程序异常中断。查看系统dmesg信息,发现系统日志的错误信息:

[54106.016179] test1[8352] trap divide error ip:400506 sp:7fff2add87e0 error:0 in test1[400000+1000]

这条信息里的ip字段后面的数字就是test1程序出错时所程序执行的位置。使用addr2line就可以将400506转换成出错程序的位置:

$ addr2line -e test1 400506
/home/hanfoo/code/test/addr2line/test1.c:5

这里的test1.c:5指的就是test1.c的第5行

return a / b;  

也正是这里出现的错误。addr2line帮助我们解决了问题。

 

addr2line如何找到的这一行呢。在可执行程序中都包含有调试信息,其中很重要的一份数据就是程序源程序的行号和编译后的机器代码之间的对应关系Line Number Table。DWARF格式的Line  Number Table是一种高度压缩的数据,存储的是表格前后两行的差值,在解析调试信息时,需要按照规则在内存里重建Line Number  Table才能使用。

Line Number Table存储在可执行程序的.debug_line域,使用命令

$ readelf -w test1

可以输出DWARF的调试信息,其中有两行

Special opcode 146: advance Address by 10 to 0x4004fe and Line by 1 to 5  

Special opcode 160: advance Address by 11 to 0x400509 and Line by 1 to 6  


这里说明机器二进制编码的0x4004fe位置开始,对应于源码中的第5行,0x400509开始就对应与源码的第6行了,所以400506这个地址对应的是源码第5行位置。

 

addr2line通过分析调试信息中的Line Number Table自动就能把源码中的出错位置找出来,再也不怕Linux毁尸灭迹了。

 

for example:

prebuilts/tools/gcc-sdk/addr2line -e out/target/product/z4dtg/obj/EXECUTABLES/xxxxx_intermediates/LINKED/xxxxxxxx  0x00007165

有些时候,我们的程序crash了,但是我们没有保存core dump信息,这时如果我们想要知道程序在哪个位置出错,就不是那么容易了。

下面有一种方法,可以大致判断出程序出错的大致位置。


1.用dmesg查找出错的代码段地址。
命令格式:
[plain] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. dmesg | grep program_name  
其中program_name是可执行文件,比如:
[plain] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. $ dmesg | grep test_prog  
  2. [103936.227079] test_prog[29319]: segfault at 40078c ip 0000000000400634 sp 00007fffe54d4680 error 7 in test_prog[400000+1000]  
其中的ip后面的地址是程序出错处的地址。

2.用addr2line将地址解析成函数名。
紧接上面的例子:
[plain] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. $ addr2line -e ./test_prog 0000000000400634 -f  
  2. _Z9errorFuncv  
  3. ??:0  

其中errorFunc即是出错的函数名,然后就可以找到相应的出错代码了。


猜你喜欢

转载自blog.csdn.net/skdkjxy/article/details/52818319