GDB的兩個技巧

2021-09-23 21:45:56 字數 2252 閱讀 5853

分享兩個gdb的小技巧:

1, gdb失效時手工得到stack;

2, gdb執行使用者命令指令碼;

除錯記憶體型服務程式的有時會遇到core dump或死鎖問題,且gdb或者pstack都無法顯示呼叫棧(call stack)。這是因為執行緒的呼叫棧被破壞了,而呼叫棧存放了函式的返回位址,gdb解析函式返回位址(根據位址查詢符號表)失敗,gdb也沒有進行容錯處理,只要有一處位址解析失敗就無法展開呼叫棧。然而幸運的是,呼叫棧往往只是部分被破壞,rsp堆疊暫存器中儲存的值往往也是正確的,可以通過手工的方法恢復。具體做法如下:

(gdb) set logging on

copying output to gdb.txt.

(gdb) x /2000a $rsp

0x426cb890: 0x0 0x4

0x426cb8a0: 0x426cb8c0 0x100

0x426cb8b0: 0x3e8 0x552f59 <_zn5tbnet16epollsocketevent9geteventseipns_7ioeventei+41>

0x426cb8c0: 0x1823c8a000000011 0x0

0x426cb8d0: 0x0 0x0

0x426cb8e0: 0x0 0x0

...

如上圖,類似」0x552f59 <_zn5tbnet16epollsocketevent9geteventseipns_7ioeventei+41>」這樣的**符號看起來是有效的。通過所有看似有效的程式**符號基本能夠得出core dump時的呼叫棧。

當然,有可能出現core dump執行緒的呼叫棧被完全破壞的情況,通過上述方法恢復的資訊仍然是無效的。由於每個執行緒堆疊位址空間的大小為10m,因此,執行緒之間互相破壞呼叫堆疊的可能性幾乎是不存在的,此時,可以通過其它執行緒的呼叫棧分析其行為,往往也能找到線索。如果所有執行緒的呼叫棧都「看似被破壞」,那麼,往往有兩種可能:

a, 可執行程式和core檔案對不上,被擺烏龍了,如發現core dump問題的時候可執行程式已經更新到最新版本,老版本沒有儲存;

b, 磁碟滿了或者ulimit設定太小,導致core dump檔案資訊不全;

如果core檔案對不上或者資訊不全的問題,還可以通過dmesg命令找到程式core dump時的指令暫存器rip的值,再通過addr2line獲取程式最後執行的**行。如:

[rizhao.ych@oceanbase036040 updateserver]$ dmesg | grep updateserver

updateserver[8099]: segfault at 0000000000000000 rip 0000000000500fbf rsp 000000004c296e30 error 4

[rizhao.ych@oceanbase036040 updateserver]$ addr2line -e updateserver 0000000000500fbf

/home/rizhao/dev/oceanbase/src/common/ob_base_server.cpp:222

另外乙個用得比較多的功能是gdb執行使用者命令指令碼。我們組無施同學有乙個例子:oceanbase系統有乙個obgetparam的類,是乙個陣列,裡面的每個元素是乙個obcellinfo,obgetparam中可能包含成百上千個obcellinfo,現在需要在gdb除錯的時候輸出陣列中所有的obcellinfo物件資訊。指令碼如下:

define dumpgetparam

set $cell_list = ($arg0)

set $cell_num = ($arg1)

set $cell_idx = (0)

while ($cell_idx < $cell_num)

printf "cell_idx:%d,table_id:%llu,column_id:%llu\n", $cell_idx,

$cell_list[$cell_idx].table_id_, $cell_list[$cell_idx].column_id

set $cell_idx = $cell_idx + 1

endend

上面的**定義了乙個命令叫dumpgetparam,其第乙個引數$arg0是cell陣列的位址,第二個引數$arg1是陣列大小,**的功能就是列印所有cell的資訊。

把上面的**寫入乙個文字檔案dump_get_param.txt,在gdb中執行source dump_get_param.txt,然後就可以使用dumpgetparam命令了。

ntsd的兩個技巧

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!ntsd是win2000開始自帶的命令列除錯工具 一.簡易後門 ntsd server tcp port 22 cmd.exe 在另一台機上 ntsd remote tcp server 192.168.1.33,port 22 shell 結果 ...

兩個 Python 的冷技巧

記得剛開始工作的時候,老大給我們上 c 基礎課,告訴我們字串字面量可以換行 如下 感覺真是如夢如幻。include int main int argc,char argv 輸出 hello world.後來在寫了很久的 python 以後,才知道 python 其實也可以的 t hello worl...

VO的兩個使用技巧

在as3中會經常使用vo 值物件 尤其是在cairngorm之類的框架中。下面是我在工作中使用vo而總結出的兩個使用技巧,與大家分享。一 可用遍歷方式賦值。如下面 package vo 如果vo的屬性與其它物件的屬性一一對應。在轉換時就可以用遍歷賦值。如下面 我們將xml屬性解析成vo屬性。var ...