elf 符號表
2018-01-06 saturday linux , program
-rdynamic vs. -g
如果通過 readelf -s 檢視,可以發現,使用 -rdynamic 選項後,在 .dynsym 段中增加了很多符號,包括本程式內定義的符號。
-g 會新增除錯資訊(.debug_***),通常被 gdb 使用,可以通過 strip 刪除。
-rdynamic 是新增動態連線符號資訊,用於動態連線功能,比如 dlopen()、backtrace() 系列函式使用,不能被 strip 掉。
在 elf 檔案中包含了 .symtab 和 .dynsym 符號表,前者包含的內容更多,通過 strip 會去掉 .symtab 而不會去掉 .dynsym。
addr2line
addr2line 常見的用處就是根據程式崩潰時候列印的堆疊位址,用來檢視出錯的源**的行數。
其原理是,在通過 -g 引數編譯生成 elf 物件時,最終的生成檔案包含有幾個 .debug 段,例如,.debug_line 包含了每個彙編指令對應的位址和源**行數源**名字等資訊。
objdump、gdb 都是可以解析這個 .debug_line 段,可以通過如下命令檢視。
$ objdump -s -d test
如果通過 strip -d 把對應 elf 檔案的幾個 debug 段都刪除掉,那麼 addr2line、objdump、gdb 都不能顯示**行數和彙編的關係了。
----- 檢視elf檔案各個段的名稱
$ readelf --sections test
$ objdump -x test
----- 檢視除錯段的內容
$ readelf -wl test
$ readelf --debug-dump test
其中 .symtab 段只儲存函式名和變數名等基本的符號的位址和長度等資訊的,所以 backtrace() 可以根據位址得到出錯的是哪個函式和在函式中的偏移,但具體到原始碼的哪一行還是要靠 .debug_line 這裡面的資訊的。
gdb 裡面可以通過 file 或者 add-symbol-file 來載入符號表的,如果需要原始碼行數資訊就需要用 -g 重新編譯程式以生成 .debug_line 段才能檢視。
dmesg
在系統 dmesg 中可以發現系統日誌的錯誤資訊:
[54106.016179] test1[8352] trap divide error ip:400506 sp:7fff2add87e0 error:0 in test1[400000+1000]
這裡的 ip 字段後面的數字就是程式出錯時所程式執行的位置,可以使用 addr2line 將位址 400506 轉換成出錯程式的位置:
$ addr2line -e test 400506
/code/test/addr2line/test1.c:5
注意通常在使用 -o1 或者 -o2 編譯時會對**進行優化,包括了 inline 方式,此時可能會忽略部分的函式。
總結簡單來說,如果需要在 backtrace 中列印函式,需要新增 -rdynamic 引數,如果要通過 addr2line 顯示行數則需要新增 -g 引數。
邏輯符號表
邏輯符號表 跳轉到 導航,搜尋 在邏輯中,經常使用一組符號來表達邏輯結構。因為邏輯學家非常熟悉這些符號,他們在使用的時候沒有解釋它們。所以,給學邏輯的人的下列 列出了最常用的符號 它們的名字 讀法和有關的數學領域。此外,第三列包含非正式定義,第四列給出簡短的例子。要注意,在一些情況下,不同的符號有相...
數學符號表
符號 名稱定義 舉例讀法 數學領域 等號y xy1 1 2 等於所有領域 不等號x y xy 不等於 所有領域 嚴格不等號 xyx3 4 5 4 小於,大於 序理論 不等號x y x yx 3 4 5 5 5 4 5 5 小於等於,大於等於 序理論 加號 4 6 表示 4 加 6。2 7 9加算術 ...
核心符號表
linux核心為了實現模組化,需要提供乙個公共的核心符號表,它包含了所有的全域性核心項 函式以及變數 的位址。當模組載入到核心中後,它所匯出的任何符號都將成為核心公共符號表的一部分。核心模組只需要實現自己的功能而無需匯出任何符號,但這樣其他模組將無法使用該模組的功能,乙個新的模組可以使用自己其他模組...