addr2line用於得到程式指令位址所對應的函式,以及函式所在的源檔名和行號。
在不少嵌入式開發環境中,編譯器的名稱往往不是gcc,而是想arm-rtems-gcc這樣的,對於這種命名形式的編譯器,讀者通常可以找到arm-rtems-addr2line ,arm-rtems-objdump等相應名稱的工具,這是gnu工具集的一種命名慣例。
本文並不是binutils工具集的完整參考手冊,當需要得到更為詳細的幫助資訊時,可以參照對應工具的man和info資訊。另乙個更為簡單的方法時執行相應的工具並指定--help引數,可以獲得該工具的簡單幫助資訊。
用法:addr2line [選項] [位址]
將位址轉換成檔名/行號對。
如果沒有在命令列中給出位址,就從標準輸入中讀取它們
選項是:
@讀取選項從
-a --addresses 顯示位址
-b --target=設定二進位檔案格式
-e --exe=設定輸入檔名稱(預設為 a.out)
-i --inlines 解開內聯函式
-j --section=讀取相對於段的偏移而非位址
-p --pretty-print 讓輸出對人類更可讀
-s --basenames 去除目錄名
-f --functions 顯示函式名
-c --demangle[=style] 解碼函式名
-h --help 顯示本幫助
實戰操練:
建立main.c檔案如下:
輸入:一定要加-g選項,不然沒有除錯資訊。
編譯沒有任何警告(作為gcc來說不應該啊^_^)
執行
顯示在在我的目錄下 main.c的第七行出現段錯誤,現在回過頭去看第一幅,你應該會發現addr2line準確地得到了我們想要除錯的東西。
一般常用的兩個option為-f和-e。
下面,我們再來做一件有意思的事情:
main.c如下:
執行如下:
可以看出foo函式是有大小的,foo函式的大小就是main的位址減去foo的位址。如果傳遞給addr2line的位址是400526-400541之間的任意位址會輸出什麼呢?
執行如下:
首先和c語言一樣,addr2line找到了foo函式入口在main.cpp的第五行,(也可以看出函式呼叫是從大括號處開始),但是函式名卻是_z3f00v,這就有點奇怪了,怎麼不是foo呢?這是因為c++的過載使得這一現象產生。從c語言的角度來看c++的過載函式名稱必須不同,為了做到這一點,c++編譯器的處理方法就是對於每乙個函式,將根據輸入引數採取一定的編碼方式,形成不同的c函式名,這個過程就是名字**過程。如上的 _z3f00v就是c++程式中foo()函式的名字**後的形式。畢竟c++是從c語言上發展而來的。
我們可以通過--demangle選項獲得函式名:
--demangle=gnu-v3用於還原foo()函式。
binutils工具集之 nm
nm用於列出程式檔案中的符號。建立nmtest.c檔案 1 include2 3int global1 4 int global2 3 56static intstatic global1 7 static int static global2 3 89void foo 10 1516static ...
binutils工具集之 nm
nm用於列出程式檔案中的符號。建立nmtest.c檔案 1 include2 3int global1 4 int global2 3 56static intstatic global1 7 static int static global2 3 89void foo 10 1516static ...
後端工具集
判斷索引是否存在 param indexname return public boolean i istsindex string indexname actionget return response.i ists 重新建立索引 補救措施 如果索引誤刪 自動建立新的索引 postconstruct...