Gdb調試多進程程序

http://www.cnblogs.com/zhenjing/archive/2011/06/01/gdb_fork.html

程序經常使用fork/exec創建多進程程序。多進程程序有自己獨立的地址空間,這是多進程調試首要注意的地方。Gdb功能強大,對調試多線程提供很多支持。

方法1:調試多進程最土的辦法:attach pid

Attach是調試進程的常用辦法,只要有可執行程序以及相應PID,即可工作。當然,爲方便調試,可以在進程啓動後,設定sleep一段時間,如30s,這樣即可有充足的時間來attach。

方法2: set follow-fork-mode child + main斷點

當設置set follow-fork-mode child,gdb將在fork之後直接執行子進程,知道碰到斷點後停止。如何設置子進程的斷點呢?在父進程中是無法知道子進程的地址空間的(只有等程序載入後方可知)。Gdb提供一個很方便的機制:main函數的斷點將被子進程繼承(畢竟main是任何程序的入口)。

注意:程序在main停下後,可嘗試設置斷點。斷點是否有效,取決於gdb是否已經載入目標程序的地址空間。

方法3: set follow-fork-mode child + catch exec

Cache點是一種特殊的breakpoint。Gdb能夠catch的事件很多,如throw/catch/exception/syscall/exec/fork/vfork等。其中和多進程關係最大的就是exec/fork事件。

舉例:

GNU gdb Fedora (6.8-27.el5)
Copyright (C) 2008 Free Software Foundation, Inc.
(gdb) catch exec
Catchpoint 1 (exec)
(gdb) set follow-fork-mode child
(gdb) r  -d ***
Catchpoint 1 (exec'd /****/binary), 0x0000003c68800a70 in _start ()
   from /lib64/ld-linux-x86-64.so.2
(gdb) bt
#0  0x0000003c68800a70 in _start () from /lib64/ld-linux-x86-64.so.2
#1  0x0000000000000003 in ?? ()
#2  0x00007fff65c6e85a in ?? ()
#3  0x00007fff65c6e85d in ?? ()
#4  0x00007fff65c6e860 in ?? ()
(gdb) b lib.cc:8720
No symbol table is loaded.  Use the "file" command.
(gdb) c
Continuing
(gdb) bt
#0  0x0000003c68800a70 in _start () from /lib64/ld-linux-x86-64.so.2
#1  0x0000000000000002 in ?? ()
#2  0x00007fff1af7682a in ?? ()
#3  0x0000000000000000 in ?? ()
(gdb)  b lib.cc:8720
Breakpoint 2 at 0x15f9694: file lib.cc, line 8720.
(gdb) c
Continuing.
[Thread debugging using libthread_db enabled]
[Thread 0x40861940 (LWP 12602) exited]
[Switching to process 12630]
0x0000003c6980d81c in vfork () from /lib64/libpthread.so.0
Warning:
Cannot insert breakpoint 2.
Error accessing memory address 0x15f9694: Input/output error.
(gdb) bt
#0  0x0000003c6980d81c in vfork () from /lib64/libpthread.so.0
#1  0x000000000040c3fb in ?? ()
#2  0x00002adeab604000 in ?? ()
#3  0x01000000004051ef in ?? ()
#4  0x00007fffff4a42f0 in ?? ()
#5  0x686365746e6f6972 in ?? ()
#6  0x0000000d0000000c in ?? ()
#7  0x0000000b0000000a in ?? ()
#8  0x0000000000000000 in ?? ()
(gdb) delete 2  --此處當breakpoint無效時,必須刪除,否則程序無法繼續
(gdb) c
Continuing.
[New process 12630]
Executing new program: /****/binary
warning: Cannot initialize thread debugging library: generic error
[Switching to process 12630]
 
Catchpoint 1 (exec'd /****/binary), 0x0000003c68800a70 in _start ()
   from /lib64/ld-linux-x86-64.so.2
(gdb) bt
#0  0x0000003c68800a70 in _start () from /lib64/ld-linux-x86-64.so.2
#1  0x0000000000000009 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb) b lib.cc:8720
Breakpoint 4 at 0x15f9694: file lib.cc, line 8720.
(gdb) b type.cc:32
Breakpoint 5 at 0x1693050: file type.cc, line 32.
(gdb) c
Continuing.
(gdb)  -- 和正常程序調試一樣

說明:catch exec後,程序將在fork/vfork/exec處停下。並非每次停下後,設置斷點都是有效的。如提供斷點無效,需要刪除,否則程序無法繼續。要能夠在新進程中設置斷點,一定要等到新進程的地址空間被載入後,設置斷點是纔有效(exec將改變原程序的地址空間)。上述例子,主要想展示如何對新進程設置斷點!

注意:
1)程序地址非常重要(代碼和數據地址一樣重要)。使用gdb時,多多注意和利用地址信息。
2)On some systems, when a child process is spawned by vfork, you cannot debug the child or parent until an exec call completes.

方法4info inferiors/inferiors inferiors

設置set detach-on-fork off/set follow-exec-mode new

If you choose to set `detach-on-fork' mode off, then gdb will retain control of all forked processes (including nested forks). You can list the forked processes under the control of gdb by using the info inferiors command, and switch from one fork to another by using the inferior command.

所使用的gdb不支持set detach-on-fork off/set follow-exec-mode new/info inferiors。不清楚。


補充一下原博主沒有的測試,我試了用detach-on-fork設爲off,然後在子進程裏面設置斷點,然後catch fork後,inferior 子進程id然後continue,這樣就可以直接進去調試子進程了,會在斷點處停住。還可以切換回主進程,而且測試的結果驗證主進程的斷點全部繼承給了子進程,而不只是原博主說的只有main裏面的繼承了。另外感覺方法3裏面的給lib.cc設置斷點不太常用,一般都不會去設置庫文件的源碼斷點。

用的操作系統是ubuntu10.04。

發佈了81 篇原創文章 · 獲贊 7 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章