先前在《追踪 glibc 裡的程式》提到自己如何亂試, 試出讓 gdb 讀到 debug symbol。昨天聽 Scott 說明, 才知道背後是怎麼一回事。
在 Ubuntu 下以 libm 為例, 在 /lib/x86_64-linux-gnu/libm-2.13.so 裡面, 先看一些相關的 section header:
$ objdump -h /lib/x86_64-linux-gnu/libm-2.13.so | grep gnu /lib/x86_64-linux-gnu/libm-2.13.so: file format elf64-x86-64 0 .note.gnu.build-id 00000024 0000000000000238 0000000000000238 00000238 2**2 2 .gnu.hash 00000fa4 0000000000000280 0000000000000280 00000280 2**3 5 .gnu.version 00000298 00000000000038da 00000000000038da 000038da 2**1 6 .gnu.version_d 0000005c 0000000000003b78 0000000000003b78 00003b78 2**3 7 .gnu.version_r 00000030 0000000000003bd8 0000000000003bd8 00003bd8 2**3 27 .gnu_debuglink 00000014 0000000000000000 0000000000000000 000840e4 2**0
幾個重點
- .note.gnu.build-id 表示 binary id, 之後用來比對 debug symbol 是否出自 shared lib。看起來 Fedora 在找 debug symbol 時, 有用到 binary id; 而 Ubuntu 沒有的樣子, 我用 hexedit 亂改這個 section 的值, 仍能找到 debug symbol
- .gnu_debuglink 指向包含 debug symbol 的檔案, 若用 hexedit 改掉它的值, 執行 gdb /lib/x86_64-linux-gnu/libm-2.13.so, gdb 會表示找不到 libm 的 debug symbol
- 可用 objdump -s -j .gnu_debuglink /lib/x86_64-linux-gnu/libm-2.13.so 顯示 section 內容
若用 LD_PRELOAD=/usr/lib/debug/lib/x86_64-linux-gnu/libm-2.13.so ANY_PROGRAM 執行程式, 結果會 segmentation fault, 所以我推測 Ubuntu 下 X-dbg 裡包的檔案, 可能和 Fedora 一樣, 只有 debug symbol 而不是完整 strip 前的函式庫。不知要如何確認該檔案裡只有 debug symbol 沒有實際的 object code。
至於確認原本的 binary (object file / shared lib / executable) 是否有編入 debug symbol, 除了用 objdump -S 再找看看有沒有出現程式碼外, 更簡單的作法是用 objdump -h | grep debug:
$ objdump -h /usr/lib/debug/lib/x86_64-linux-gnu/libm-2.13.so | grep debug /usr/lib/debug/lib/x86_64-linux-gnu/libm-2.13.so: file format elf64-x86-64 28 .debug_aranges 00004770 0000000000000000 0000000000000000 000002b0 2**4 29 .debug_pubnames 00002e44 0000000000000000 0000000000000000 00004a20 2**0 30 .debug_info 000318ee 0000000000000000 0000000000000000 00007864 2**0 31 .debug_abbrev 00010fc3 0000000000000000 0000000000000000 00039152 2**0 32 .debug_line 00018c20 0000000000000000 0000000000000000 0004a115 2**0 33 .debug_str 000041bc 0000000000000000 0000000000000000 00062d35 2**0 34 .debug_loc 00062bc5 0000000000000000 0000000000000000 00066ef1 2**0 35 .debug_pubtypes 00003a11 0000000000000000 0000000000000000 000c9ab6 2**0 36 .debug_ranges 00003e30 0000000000000000 0000000000000000 000cd4c7 2**0
有上述 section 的話, 表示有含 debug symbols。
備註
1. hexedit 基本指令
- F1: 等同於 man hexedit
- F4: 跳到 offset, 對照 objdump -h X 看倒數第二欄使用
- TAB: 切換 hexadecimal 或 ascii 區, 之後取代內容或搜尋, 和這有關
- 直接在 byte 上打字取代
- /: 找字串
- ctrl+c / ctrl+x: 離開 / 存檔離開
2. 見《The DWARF Debugging Standard》了解 debug 資訊如何存在檔案, 只是留著備忘, 目前應該沒必要去讀。
3. 若是自己編含 debug symbol 的函式庫, 就不是上述那一回事了, 而是直接編進目前的函式庫裡。
4. 《Separate Debug Files - Debugging with GDB》說明 gdb 如何支援分離 debug symbol 到另一個檔案, 另外 man strip 或 man objcopy, 可在 "--only-keep-debug" 的部份看到相關說明。看來要知道到底各個 distribution 怎麼做這事, 去看該 distribution 官方的說明會比較確實。之後再看看吧。
沒有留言:
張貼留言