GDB除錯資訊——No symbol "xxx" in current context
在使用GDB除錯C++時遇到過一些很奇怪的問題:
1.GDB斷點除錯可執行檔案或者Dumped Core檔案時,無法顯示原始碼
2.GDB可以顯示原始碼,但單步除錯或者列印區域性資訊時錯誤,顯示No symbol “xxx” in current context.
在此將排查過程和解決方案梳理並分享如下。
GCC編譯選項
先是查詢GCC的文件:
Debug Option
最主要的就是這樣一行:To tell GCC to emit extra information for use by a debugger, in almost all cases you need only to add -g to your other options.
也就是說gcc需要這個選項把額外的debug資訊以特定的格式寫入到可執行檔案中,這樣在使用GDB或者其他除錯工具的時候,才能正常除錯;文件中還有提到如果你使用了-O的選項的話,編譯器會做一些編譯優化,這樣可能會導致除錯時區域性變數值不對、程式執行流程不對等問題。文件中推薦在使用-g選項的時候,同時使用-Og可以關閉編譯優化。例如
g++ main.cpp -g -Og -o a.out
。 我做到這一步的時候,已經解決了GDB不顯示原始碼的問題,但另外一個問題又出現了。
GCC 除錯資訊格式
我除錯使用的原始碼如下
int main()
{
int a = 1;
++a;
}
執行到第四行的時候,GDB中輸入print a
:顯示No symbol “a” in current context.
我又仔細看了看GCC的文件,GCC還提供了一些更多的選項比如-gstabs+, -gstabs, -gxcoff+, -gxcoff, -gdwarf
等,以把Debug Info儲存成不同的格式。
我就開始懷疑是不是預設的-g儲存的格式GDB沒有辦法識別,我使用的GCC是8.1版本的。後來發現GCC在4.8版本的更新時修改了預設的Debug Info格式:
DWARF4 is now the default when generating DWARF debug information. When -g is used on a platform that uses DWARF debugging information, GCC will now default to -gdwarf-4 -fno-debug-types-section.
GDB 7.5, Valgrind 3.8.0 and elfutils 0.154 debug information consumers support DWARF4 by default. Before GCC 4.8 the default version used was DWARF2. To make GCC 4.8 generate an older DWARF version use -g together with -gdwarf-2 or -gdwarf-3. The default for Darwin and VxWorks is still -gdwarf-2 -gstrict-dwarf.
簡而言之,DWARF4這種格式是生成dwarf除錯資訊(並不是所有platform -g預設輸入dwarf4)的預設格式,GDB7.5以後的版本預設支援DWARF4。可以使用-gdwarf-2指定輸出DWARF2格式。
我嘗試到-gdwarf-2的時候,print a
就能正常列印了。我的GCC版本是8.1,GDB版本是7.2,所以就會導致,GCC中使用-g選項輸出的DWARF4格式GDB無法正確解析。
不同平臺,不同版本的預設選項不同,只是提供一個排查的思路。
後來又學到了一個這樣的命令:readelf --debug-dump=info
用於把可執行檔案(elf)中的除錯資訊dump出來。
我把不同編譯選項下的DebugInfo匯出到檔案,然後diff一下,也證實了這個想法。
GCC 8.1預設使用的是dwarf-4,GDB 7.2不支援,所以就會出現上述問題。