使用gdb調試當前運行的程序

使用gdb調試當前運行的程序

 

http://blog.csdn.net/wfing/archive/2010/09/17/5890382.aspx

 http://blog.csdn.net/chenglian_999/archive/2009/11/15/4813469.aspx

用gdb可以調試當前的程序的使用情況,讀出他的參數。
以下用一個簡單的程序做爲例子:來說明gdb的調試。

第一步  編譯一個死循環程序。 

/* File name malloc.c*/

#include   <stdio.h>                                                            
#include   <stdlib.h>
#include   <string.h>

void getmem(void **p, int num){
    *p = (void *)malloc(num);
}

void test(void){
    char *str = NULL;
    getmem((void **)&str, 100);
        strcpy(str, "Hello");
    printf("%s\n", str);
}

int main(void){
    int i = 0;
    while(1){
        if (i == 1){ 
            test();
            return 1;
        }   
    }
    return 0;
}                 


我們可以看出,這個程序就是malloc一段內存空間,用來供strcpy使用,由於只是調試一下,就沒有在test程序中加上一些關於strcpy的正確性判斷語句。
函數的正常退出的情況是i==1,但是程序運行過程中根本無法使i==1成立。i的變量的值將會在使用gdb時用到。

開始編譯
$gcc -g malloc.c 

得用gdb,加上-g還是需要的。生成的可執行文件爲a.out

第二步  讓gdb連接到正在執行的進程上去 
首先運行程序。
$./a.out 
明顯的,是一個死循環。

重新開一個shell
$ps -u 
我的機器的運行情況如下所示:
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
wyc       7712  0.0  0.1   6092  3644 pts/8    Ss   10:24   0:00 bash
wyc       7880  0.0  0.1   6092  3608 pts/9    Ss   10:27   0:00 bash
wyc       7929  0.0  0.3  10848  6468 pts/9    S+   10:28   0:00 gdb
wyc       8347 93.0  0.0   1652   284 pts/8    R+   10:42   0:13 ./a.out
...

看到沒有? ./a.out的進程號是8347。

現在啓動gdb
$gdb 

由於是調試運行的進程,不是可執行文件,後面不需要跟任何參數。在用 gdb調試運行狀態下的程序時,最核心的就是gdb內部的attach命令
用法爲
 (gdb) attach 

這是我的機器上的例子:
$ gdb 
GNU gdb (GDB) 7.1.50.20100621
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
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-pc-linux-gnu".
For bug reporting instructions, please see:
.
(gdb) attach 8347
Attaching to process 8347
Reading symbols from /home/wyc/desktop/my_program/review/a.out...done.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
main () at malloc.c:19
19            if (i == 1){
(gdb) p i
$1 = 0
(gdb) set i=1
Ambiguous set command "i=1": .
(gdb) i=1
Undefined info command: "=1".  Try "help info".
(gdb) set i=1
Ambiguous set command "i=1": .
(gdb) set var i=1
(gdb) l
14    }
15    
16    int main(void){
17        int i = 0;
18        while(1){
19            if (i == 1){
20                test();
21                return 1;
22            }
23        }
(gdb) n
20                test();
(gdb) 
21                return 1;
(gdb) 
25    }
(gdb) 
0xb7f47775 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) 
Single stepping until exit from function __libc_start_main, 
which has no line number information.

Program exited with code 01.
(gdb) 

在運行到第20行命令的時候,可以看一下到運行./a.out的那個shell,應該hello字符串在標準輸出上了。當gdb中顯示進程退出時,./a.out的shell應該結束了當前進程了。
在gdb中用set var i=1 來修改變量i的值(用set i=1不能識別命令),使程序能夠正常退出。

在調試時,當前程序調用的所有庫也全部都出來了。這個例子中的
Reading symbols from /home/wyc/desktop/my_program/review/a.out...done.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
是a.out程序所調用的全部庫。可以用這種辦法分析當前運行的程序的庫的調用情況。

千萬不要關掉gdb,以下調試更精彩:

第三步 在gdb中重啓程序 
在上面已經知道了程序正常退出了,但是gdb還沒有退出,這時在gdb中運行run效果如何?

(gdb) run 
Starting program: /home/wyc/desktop/my_program/review/a.out 
下面是死循環了...
接下Ctrl+c,給gdb發個SIGINT的信號。

^C
Program received signal SIGINT, Interrupt.
main () at malloc.c:19
19            if (i == 1){
(gdb) p i
$2 = 0
(gdb) set var i=1
(gdb) n
20                test();
(gdb) n
Hello
21                return 1;
(gdb) n
25    }
(gdb) n
0xb7e7b775 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) n
Single stepping until exit from function __libc_start_main, 
which has no line number information.

Program exited with code 01.

可以看出,用gdb連接進程後,他會找到運行這個進程所需的全部文件,當前進程關閉後,仍然可以在gdb中啓動這個程序。

不得不佩服GDB的調試功能的強大

gdb中的其它命令,就看你分析程序時是否用到了,例如下面的一些簡單的命令:

常用的bt, p , p/x , setp, info registers, break , jump ......


在完成調試之後,不要忘記用detach命令斷開連接,讓被調試的進程可以繼續正常運行。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章