c++ 符號表分離———objcopy(調試信息掛載)
https://blog.csdn.net/cyteven/article/details/13015511
gdb 如何調試release版本
https://blog.csdn.net/u012719556/article/details/45315089?utm_source=blogxgwz2
GDB調試Release版ELF文件
https://www.cnblogs.com/np10/archive/2013/01/24/2875573.html
最近在做遊戲的項目,項目中使用的服務器程序版本是release版本的,最近出現服務器宕機的情況,但是core文件通過gdb查看了一下宕機堆棧結果發現堆棧被破壞,可能的問題就是對指針和數組使用的不規範導致的。然後打算繼續通過gdb來調試一下core文件查看一下相關的變量,但是結果令人失望,但是發現debug版本的是可以查看的。比較一下debug和release的區別。
release的編譯選項中不包含有調試信息,並且做了代碼優化,編譯選項中爲 -O3。
debug版本發現debug版本是可以查到符號信息的,去看了下debug版本的編譯選項 -g3 。
此時就想如何能讓版本即擁有符號信息又效率得到保證呢,查看資料發現linux下有個指令是objcopy可以將可執行文件的符號表剝離處理。
下面用一些小例子來演示一下分離過程及分離後效果:
main.cpp文件
#include <iostream>
using std::cout;
using std::endl;
void my_print();
int main(int argc, char *argv[])
{
my_print();
cout<<"hello!"<<endl;
return 0;
}
void my_print()
{
int a = 10;
int b = 20;
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl;
}
然後我們來編譯一下這個內容,
一、[root@localhost testm]# g++ -O3 main.cpp -o mainO3
插曲:g++編譯選項的 -O3:-O0 -O1 -O2 -O3 編譯器的優化選項的4個級別,-O0表示沒有優化,-O1爲缺省值,-O3優化級別最高
這樣編譯後的可執行文件是不含有符號表的就是理論我們的release版本,我門使用readelf -S命令查看段
Readelf -S mainO3
裏面有有debug調試信息,那麼這樣的情況下我們能否使用objcopy來產生符號表呢,產生後又有什麼效果呢我們一起見證一下:
[root@localhost testm]# objcopy --only-keep-debug mainO3 mainO3.symbol //拷貝出一個符號表文件
[root@localhost testm]# objcopy --strip-debug mainO3 mainO3.bin //拷貝出一個執行文件
我門通過上面的命令生成文件如下
從大小來看我們可以瞭解到符號表的大小執行文件大小以及原來的release文件大小基本差不多,接下來我們分別看下一下段信息
經過比對我們發現這個三個文件的段一樣的。那我們在來執行一下main.bin 這個剝離出來的文件看看(可以正常執行和正常的文件也一樣)
這種情況的符號表分離是沒有任何作用的。
二、接下來我們要做的就是生成一個有debug信息的的可執行文件
[root@localhost testm]# g++ -g3 -o3 main.cpp -o maingo
同樣我們還做上面的操作進行符號表分離
[root@localhost testm]# objcopy --only-keep-debug maingo maingo.symbol
[root@localhost testm]# objcopy --strip-debug maingo maingo.bin
通過查看文件我們可以發現明顯debug版本編譯的含有debug信息的可執行文件maingo要比正常的版本文件mainO3大很多,在比較一下maingo、maingo.bin、maingo.symbol我們發現符號表文件同樣很大,剝離後的可執行文件很小。
接下來我們來看看他們的段信息又是如何呢
含有debug信息的可執行文件在段中我們可以找到debug段信息如上紅框
從上面這個被剝離處理的main.bin來看短信息中已經不含有debug段了,證明已經成功被剝離出來了
符號表文件是正常好友所有debug信息的段。
下面我門來執行一下看看這兩個文件有沒有什麼不同
三、接下來我們要驗證的就是release版的程序在調試的時候我們能看到什麼信息,debug版本我們能看到什麼信息
1、我們啓動gdb來加載我們的可執行文件斷點調試一下:
[root@localhost testm]# gdb //啓動gdb
(gdb) file mainO3 //載入可執行文件mainO3
(gdb) b my_print //打斷點
(gdb) r //執行
(gdb) info lo //查看局部變量
(gdb) n //下一步
我們發現局部變量和調試的時候報出來的都是(no debugging symbols found)
結論:release版調試時無法看到符號信息,不能定位調試問題
2、再看下debug版本調試如何(操作同上)
我們發我們在debug版本的時候可以清晰的看到文件名以及我們執行的行數以及每一行的代碼,局部變量的值我們都可以查到。
3、我們來看下maingo.bin結果如何
結果和release的一樣什麼信息都看不到
4、這個是我們驗證的關鍵的一點就是我們掛載符號表後看我們執行時候能含有符號信息呢
對於這種符號表與二進程序,可以在gdb 啓動時,通過 –s 指定符號表文件來解決. 如下例,通過 –s 指定maingo.symbol 後, gdb 調試時可以看到符號表了.
哈哈,看來我們成功了,掛在符號表後我們能查到函數的信息及局部變量的值。
5、據說有源文件在統一執行目錄就能看到更多信息了我們加上源文件看看執行結果如何
嗯,結果是我們看不到源碼了但是我們還是可以查看文件中的局部變量的值,嗯,還算滿意這樣的話我們就可以在外網掛我們的優化的文件並且有不會影響效率,同時我們還掛載了符號表後我們可以查看相關的信息。
————————————————————————————————————————————————————————————————————————————————————————————————————————————————