linux addr2line 定位so庫崩潰位置

轉自 https://www.cnblogs.com/zl1991/p/5893329.html

在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

發佈了195 篇原創文章 · 獲贊 53 · 訪問量 53萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章