天天看點

使用gdb調試多程序和多線程程式

  1. 預設設定下,在調試多程序程式時GDB隻會調試主程序。但是GDB(>V7.0)支援多程序的分别以及同時調試,換句話說,GDB可以同時調試多個程式。隻需要設定follow-fork-mode(預設值:parent)和detach-on-fork(預設值:on)即可。

    follow-fork-mode detach-on-fork 說明

    parent  on   隻調試主程序(GDB預設)

    child   on   隻調試子程序

    parent  off   同時調試兩個程序,gdb跟主程序,子程序block在fork位置

    child   off   同時調試兩個程序,gdb跟子程序,主程序block在fork位置

set follow-fork-mode [parent|child]   set detach-on-fork [on|off]      

  查詢正在調試的程序:info inferiors

  切換調試的程序: inferior

  添加新的調試程序: add-inferior [-copies n] [-exec executable] ,可以用file executable來配置設定給inferior可執行檔案。

  其他:remove-inferiors infno, detach inferior

2.GDB預設支援調試多線程,跟主線程,子線程block在create thread。

   查詢線程:info threads

   切換調試線程:thread

測試代碼:

/*************************************************************************
    > File Name: multithread.c
    > Author: sunxingying
    > Mail: [email protected] 
    > Created Time: 2017年06月04日 星期日 04時22分41秒
 ************************************************************************/

#include<stdio.h>
#include <pthread.h>

void processA();
void processB();
void * processAworker(void *arg);

int main(int argc, const char *argv[])
{
    int pid;
    pid = fork();

     if(pid != 0)
        processA();
     else
       processB();

     return 0;
}

void processA() 
{
    pid_t pid = getpid();
    char prefix[] = "ProcessA: ";
    char tprefix[] = "thread ";
    int tstatus;
    pthread_t pt;

    printf("%s%lu %s\n", prefix, pid, "step1");

    tstatus = pthread_create(&pt, NULL, (void*)processAworker, NULL);
    if( tstatus != 0 )
    {
        printf("ProcessA: Can not create new thread.");                         }

    processAworker(NULL);
    sleep(1);
}

void * processAworker(void *arg)
{
    pid_t pid = getpid();
    pthread_t tid = pthread_self();
    char prefix[] = "ProcessA: ";
    char tprefix[] = "thread ";

    printf("%s%lu %s%lu %s\n", prefix, pid, tprefix, tid, "step2");
    printf("%s%lu %s%lu %s\n", prefix, pid, tprefix, tid, "step3");

    return NULL;
}

void processB()
{
    pid_t pid = getpid();
    char prefix[] = "ProcessB: ";
    printf("%s%lu %s\n", prefix, pid, "step1");
    printf("%s%lu %s\n", prefix, pid, "step2");
    printf("%s%lu %s\n", prefix, pid, "step3");

}      

調試:

1. 調試主程序,block子程序。

[dasheng@localhost wangluo]$ gdb multithread
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-90.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/dasheng/code/wangluo/multithread...done.
(gdb) set detach-on-fork off
(gdb) show detach-on-fork
Whether gdb will detach the child of a fork is off.
(gdb) catch fork
Catchpoint 1 (fork)
(gdb) r
Starting program: /home/dasheng/code/wangluo/multithread 
[Thread debugging using libthread_db enabled]

Catchpoint 1 (forked process 3185), 0x00129424 in __kernel_vsyscall ()
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) break mu
multithread.c   munlockall      [email protected]  munmap_chunk
munlock         munmap          munmap@plt      muntrace
(gdb) break multithread.c :20
Breakpoint 2 at 0x8048546: file multithread.c, line 20.
(gdb) cont
Continuing.
[New process 3185]
[Thread debugging using libthread_db enabled]

Breakpoint 2, main (argc=1, argv=0xbffff3c4) at multithread.c:20
20       if(pid != 0)
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) info inferiors
  Num  Description       Executable        
  2    process 3185      /home/dasheng/code/wangluo/multithread 
* 1    process 3182      

2.切換到子程序:

(gdb) inferior 2
[Switching to inferior 2 [process 3185] (/home/dasheng/code/wangluo/multithread)]
[Switching to thread 2 (Thread 0xb7ff16c0 (LWP 3185))] 
#0  0x00129424 in ?? ()
(gdb) info inferiors
  Num  Description       Executable        
* 2    process 3185      /home/dasheng/code/wangluo/multithread 
  1    process 3182      /home/dasheng/code/wangluo/multithread 
(gdb) inferior 1
[Switching to inferior 1 [process 3182] (/home/dasheng/code/wangluo/multithread)]
[Switching to thread 1 (Thread 0xb7ff16c0 (LWP 3182))] 
#0  main (argc=1, argv=0xbffff3c4) at multithread.c:20
20       if(pid != 0)
(gdb) info inferiors
  Num  Description       Executable        
  2    process 3185      /home/dasheng/code/wangluo/multithread 
* 1    process 3182      

3.設斷點繼續調試主程序,主程序産生兩個子線程:

(gdb) break multithread.c :55
Breakpoint 3 at 0x804867d: file multithread.c, line 55. (2 locations)
(gdb) cont
Continuing.
ProcessA: 3182 step1
[New Thread 0xb7ff0b70 (LWP 3462)]
ProcessA: 3182 thread 3086948032 step2

Breakpoint 3, processAworker (arg=0x0) at multithread.c:55
55      printf("%s%lu %s%lu %s\n", prefix, pid, tprefix, tid, "step3");
(gdb) info inferiors
  Num  Description       Executable        
  2    process 3185      /home/dasheng/code/wangluo/multithread 
* 1    process 3182      /home/dasheng/code/wangluo/multithread 
(gdb) info threads
  3 Thread 0xb7ff0b70 (LWP 3462)  0x00211d58 in clone ()
   from /lib/libc.so.6
  2 Thread 0xb7ff16c0 (LWP 3185)  0x00129424 in ?? ()
* 1 Thread 0xb7ff16c0 (LWP 3182)  processAworker (arg=0x0)
    at multithread.c:55      

4.切換到主程序中的子線程,注意:線程2為前面産生的子程序

(gdb) thread 3
[Switching to thread 3 (Thread 0xb7ff0b70 (LWP 3462))]#0  0x00211d58 in clone () from /lib/libc.so.6
(gdb) cont
Continuing.
ProcessA: 3182 thread 3086945136 step2
ProcessA: 3182 thread 3086948032 step3
[Switching to Thread 0xb7ff0b70 (LWP 3462)]

Breakpoint 3, processAworker (arg=0x0) at multithread.c:55
55      printf("%s%lu %s%lu %s\n", prefix, pid, tprefix, tid, "step3");
(gdb) info threads
* 3 Thread 0xb7ff0b70 (LWP 3462)  processAworker (arg=0x0)
    at multithread.c:55
  2 Thread 0xb7ff16c0 (LWP 3185)  0x00129424 in ?? ()
  1 Thread 0xb7ff16c0 (LWP 3182)  0x00129424 in __kernel_vsyscall ()
(gdb) thread 1
[Switching to thread 1 (Thread 0xb7ff16c0 (LWP 3182))]#0  0x00129424 in __kernel_vsyscall ()      

gdb調試常用指令:

$ gcc -g example.c -o example.x

通過上述指令對example.c編譯之後,使用下列指令進入到gdb調試:

$ gdb example.x      

在gdb調試中,常用的指令有以下幾個:

$ list 縮略為 l      

列出程式源碼,每次列出10行,按回車重複運作上一指令;

$ run 縮略為 r      

程式開始運作,在r後可以加入程式啟動參數,程式運作到斷點處暫停;

$ continue 縮略為 c      

程式繼續運作,到下一斷點處暫停;

單步調試

$ step 縮略為s

$ next 縮略為 n      

程式繼續運作到下一斷點;

$ break 縮略為 b      

在程式某一位置設定斷點;

$ info break 縮略為 i b      

檢視斷點資訊;

設定/檢視運作參數

$ set args ---/show args      

加載運作中的程序進行調試(Attach to the running process to be debugged.):

$ gdb attatch pid

Specifying source directories

$ dir dirname …      

以十六進制輸出記憶體塊資料

$ x/28hx ---      

段錯誤調試,core檔案樣例

$ gdb [exec file] [core file] | gdb -c corefile execfile      
$ bt      

繼續閱讀