100个GDB小技巧(一)

来源:互联网 发布:js删除对象元素 编辑:程序博客网 时间:2024/05/20 15:10

本文是100个GDB小技巧阅读总结,100个GDB小技巧.

列出函数的名字

在这个例子中源代码如下:

#include <stdio.h>#include <pthread.h>void *thread_func(void *p_arg){        while (1)        {                sleep(10);        }}int main(void){        pthread_t t1, t2;        pthread_create(&t1, NULL, thread_func, "Thread 1");        pthread_create(&t2, NULL, thread_func, "Thread 2");        sleep(1000);        return;}

然后保存文件为fucntion.c
gcc -g function.c -o function提示如下错误:
/tmp/ccCIJDjs.o: In function main':
/root/function.c:14: undefined reference to
pthread_create’
/root/function.c:15: undefined reference to `pthread_create’
collect2: error: ld returned 1 exit status

错误产生的原因是:
pthread库不是标准linux库,修改为如下方式即可:
gcc -pthread -g function.c -o function
然后gdb function即可.

退出正在调试的函数

例子

#include <stdio.h>int func(void){    int i = 0;    i += 2;    i *= 10;    return i;}int main(void){    int a = 0;    a = func();    printf("%d\n", a);    return 0;}

技巧

当单步调试一个函数时,如果不想继续跟踪下去了,可以有两种方式退出。

第一种用“finish”命令,这样函数会继续执行完,并且打印返回值,然后等待输入接下来的命令。以上面代码为例:

(gdb) n17      a = func();(gdb) sfunc () at a.c:55         int i = 0;(gdb) n7         i += 2;(gdb) finfind    finish(gdb) finishRun till exit from #0  func () at a.c:70x08050978 in main () at a.c:1717        a = func();Value returned is $1 = 20

可以看到当不想再继续跟踪func函数时,执行完“finish”命令,gdb会打印结果:“20”,然后停在那里。
第二种用“return”命令,这样函数不会继续执行下面的语句,而是直接返回。也可以用“return expression”命令指定函数的返回值。仍以上面代码为例:

(gdb) n17          a = func();(gdb) sfunc () at a.c:55            int i = 0;(gdb) n7            i += 2;(gdb) n8            i *= 10;(gdb) rerecord              remove-inferiors    return              reverse-next        reverse-steprefresh             remove-symbol-file  reverse-continue    reverse-nexti       reverse-stepiremote              restore             reverse-finish      reverse-search(gdb) return 40Make func return now? (y or n) y#0  0x08050978 in main () at a.c:1717          a = func();(gdb) n18          printf("%d\n", a);(gdb)     4019          return 0;

可以看到“return”命令退出了函数并且修改了函数的返回值。

打印函数堆栈帧信息

例子

#include <stdio.h>int func(int a, int b){    int c = a * b;    printf("c is %d\n", c);}int main(void) {    func(1, 2);    return 0;}

技巧
使用gdb调试程序时,可以使用“i frame”命令(i是info命令缩写)显示函数堆栈帧信息。以上面程序为例:
(gdb) b func
Breakpoint 1 at 0x4004d2: file main.c, line 4.
(gdb) r
Starting program: /root/play/main
Breakpoint 1, func (a=1, b=2) at a.c:5
5 printf(“c is %d\n”, c);
(gdb) i frame
Stack level 0, frame at 0x7fffffffe590:
rip = 0x40054e in func (a.c:5); saved rip = 0x400577
called by frame at 0x7fffffffe5a0
source language c.
Arglist at 0x7fffffffe580, args: a=1, b=2
Locals at 0x7fffffffe580, Previous frame’s sp is 0x7fffffffe590
Saved registers:
rbp at 0x7fffffffe580, rip at 0x7fffffffe588
(gdb) i registers
rax 0x2 2
rbx 0x0 0
rcx 0x0 0
rdx 0x7fffffffe688 140737488348808
rsi 0x2 2
rdi 0x1 1
rbp 0x7fffffffe580 0x7fffffffe580
rsp 0x7fffffffe560 0x7fffffffe560
r8 0x7ffff7dd4e80 140737351863936
r9 0x7ffff7dea560 140737351951712
r10 0x7fffffffe420 140737488348192
r11 0x7ffff7a35dd0 140737348066768
r12 0x400440 4195392
r13 0x7fffffffe670 140737488348784
r14 0x0 0
r15 0x0 0
rip 0x40054e 0x40054e

设置临时断点

#include <stdio.h>#include <pthread.h>typedef struct{        int a;        int b;        int c;        int d;        pthread_mutex_t mutex;}ex_st;int main(void) {        ex_st st = {1, 2, 3, 4, PTHREAD_MUTEX_INITIALIZER};        printf("%d,%d,%d,%d\n", st.a, st.b, st.c, st.d);        return 0;}

技巧

在使用gdb时,如果想让断点只生效一次,可以使用“tbreak”命令(缩写为:tb)。以上面程序为例:
(gdb) tb a.c:15
Temporary breakpoint 1 at 0x400500: file a.c, line 15.
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint del y 0x0000000000400500 in main at a.c:15
(gdb) r
Starting program: /data2/home/nanxiao/a
Temporary breakpoint 1, main () at a.c:15
15 printf(“%d,%d,%d,%d\n”, st.a, st.b, st.c, st.d);
(gdb) i b
No breakpoints or watchpoints.
首先在文件的第15行设置临时断点,当程序断住后,用“i b”(”info breakpoints”缩写)命令查看断点,发现断点没有了。也就是断点命中一次后,就被删掉了。

条件断点

#include <stdio.h>int main(void){        int i = 0;        int sum = 0;        for (i = 1; i <= 200; i++)        {            sum += i;        }        printf("%d\n", sum);        return 0;}

技巧
gdb可以设置条件断点,也就是只有在条件满足时,断点才会被触发,命令是“break … if cond”。以上面程序为例:
(gdb) start
Temporary breakpoint 1 at 0x4004cc: file a.c, line 5.
Starting program: /data2/home/nanxiao/a
Temporary breakpoint 1, main () at a.c:5
5 int i = 0;
(gdb) b 10 if i==101
Breakpoint 2 at 0x4004e3: file a.c, line 10.
(gdb) c
Continuing.

Breakpoint 2, main () at func.c:10
10 sum += i;
(gdb) p sum
$1 = 5050
可以看到设定断点只在i的值为101时触发,此时打印sum的值为5050。

忽略断点

#include <stdio.h>int main(void){    int i = 0;    int sum = 0;    for (i = 1; i <= 200; i++)    {        sum += i;    }    printf("%d\n", sum);    return 0;}

在设置断点以后,可以忽略断点,命令是“ignore bnum count”:意思是接下来count次编号为bnum的断点触发都不会让程序中断,只有第count + 1次断点触发才会让程序中断。以上面程序为例:
(gdb) b 9
Breakpoint 1 at 0x4004e3: file hello.c, line 9.
(gdb) ignore 1 5
Will ignore next 5 crossings of breakpoint 1.
(gdb) r
Starting program: /root/play/hello
Breakpoint 1, main () at hello.c:9
9 sum += i;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6.x86_64
(gdb) p i
$1 = 6
可以看到设定忽略断点前5次触发后,第一次断点断住时,打印i的值是6。如果想让断点从i=1处开始生效,可以将count置为0:“ignore 1 0”.

原创粉丝点击