GDB基础


前言: GDB 是什么?

GDB 是软件仿真工具,使用场景大致分为两种
1、gdb用于host主机在线调试(断点、单步调试)
2、gdb用于调试corefile
以下示例结合场景1进行说明

一、编译要求

1. 源码

/*hello.c*/
#include <stdio.h>

struct Student
{
    int id;
    char *name;
};

void fool(void)
{
    int a = 10;
    int b = 9;
}

int bar(int x, int y)
{
    int sum =  x + y;
    return sum;
}

int hum(struct Student* str)
{
        return 0;
}


int main(void)
{
    printf("hello world\n");

    fool();
    bar(1,2);

    struct Student X;
    X.id = 99;
    X.name = "jianyan";
    hum(&X);
    return 0;
}

2. 编译方式

$gcc  -g hello.c -o hello.elf

对于GCC,必须加上-g选项(elf文件中将保存符号表)

二、基本用法

1. 启动gdb

$gdb hello.elf 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from hello.elf...
(gdb) 

2. 源码查阅

2.1 查阅函数

查阅函数附近的代码

$(gdb) list main
23	        return 0;
24	}
25	
26	
27	int main(void)
28	{
29	    printf("hello world\n");
30	
31	    fool();
32	    bar(1,2);
(gdb) 

2.2 查阅行号

查阅行号附近的代码

$(gdb) list 27
22	{
23	        return 0;
24	}
25	
26	
27	int main(void)
28	{
29	    printf("hello world\n");
30	
31	    fool();

3. 断点控制

设置断点

#在main函数设置断点
$(gdb) break main
Breakpoint 1 at 0x11b3: file hello.c, line 28.
$(gdb) break hello.c:
bar   fool  hum   main  
#在hello.c的bar函数设置断点
$(gdb) break hello.c:bar
Breakpoint 2 at 0x1182: file hello.c, line 16.
#在行号处设置断点
$(gdb) break 31
Breakpoint 3 at 0x11da: file hello.c, line 31.
#显示当前断点
$(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011b3 in main at hello.c:28
2       breakpoint     keep y   0x0000000000001182 in bar at hello.c:16
3       breakpoint     keep y   0x00000000000011da in main at hello.c:31

关闭、打开断点

$(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011b3 in main at hello.c:28
2       breakpoint     keep y   0x0000000000001182 in bar at hello.c:16
3       breakpoint     keep y   0x00000000000011da in main at hello.c:31
$(gdb) disable 1
$(gdb) disable 2
$(gdb) disable 3
$(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x00000000000011b3 in main at hello.c:28
2       breakpoint     keep n   0x0000000000001182 in bar at hello.c:16
3       breakpoint     keep n   0x00000000000011da in main at hello.c:31
$(gdb) enable 1 
$(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011b3 in main at hello.c:28
2       breakpoint     keep n   0x0000000000001182 in bar at hello.c:16
3       breakpoint     keep n   0x00000000000011da in main at hello.c:31
#enable all
$(gdb) enable 
$(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011b3 in main at hello.c:28
2       breakpoint     keep y   0x0000000000001182 in bar at hello.c:16
3       breakpoint     keep y   0x00000000000011da in main at hello.c:31

断点生命周期

#disable after hit once
$(gdb) enable once 1
#delete after hit once
$(gdb) enable delete 2
$(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     dis  y   0x00000000000011b3 in main at hello.c:28
2       breakpoint     del  y   0x0000000000001182 in bar at hello.c:16
3       breakpoint     keep y   0x00000000000011da in main at hello.c:31

删除断点

$(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     dis  y   0x00000000000011b3 in main at hello.c:28
2       breakpoint     del  y   0x0000000000001182 in bar at hello.c:16
3       breakpoint     keep y   0x00000000000011da in main at hello.c:31
$(gdb) delete 1
$(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
2       breakpoint     del  y   0x0000000000001182 in bar at hello.c:16
3       breakpoint     keep y   0x00000000000011da in main at hello.c:31
#delte all breakpoints
$(gdb) delete 
Delete all breakpoints? (y or n) y
$(gdb) info breakpoints 
No breakpoints or watchpoints.

4. 执行控制

4.1 单步执行

next/n 命令:next line call(但是line 内部call视为一个整体)
r命令用于启动program执行

$(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011b3 in main at hello.c:28
2       breakpoint     keep y   0x00000000000011da in main at hello.c:31
3       breakpoint     keep y   0x00000000000011ee in main at hello.c:35
$(gdb) r
Starting program: /home/jianleya/trainning/C/print/hello.elf 

Breakpoint 1, main () at hello.c:28
28	{
$(gdb) n
29	    printf("hello world\n");
$(gdb) n
hello world

Breakpoint 2, main () at hello.c:31
31	    fool();
$(gdb) n
32	    bar(1,2);
$(gdb) n

Breakpoint 3, main () at hello.c:35
35	    X.id = 99;
$(gdb) n
36	    X.name = "jianyan";
$(gdb) n
37	    hum(&X);
$(gdb) n
38	    return 0;
$(gdb) n
39	}

step/s 命令:执行下一行(line本身call会被展开)

$gdb hello.elf 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from hello.elf...
$(gdb) break main 
Breakpoint 1 at 0x11b3: file hello.c, line 28.
$(gdb) r
Starting program: /home/jianleya/trainning/C/print/hello.elf 

Breakpoint 1, main () at hello.c:28
28	{
$(gdb) s
29	    printf("hello world\n");
$(gdb) s
__GI__IO_puts (str=0x555555556004 "hello world") at ioputs.c:33
33	ioputs.c: No such file or directory.
$(gdb) s
35	in ioputs.c
(gdb) 

4.2 继续执行

continue/c命令 继续执行直到断点或者结束

$gdb hello.elf 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from hello.elf...
$(gdb) break main 
Breakpoint 1 at 0x11b3: file hello.c, line 28.
$(gdb) r
Starting program: /home/jianleya/trainning/C/print/hello.elf 

Breakpoint 1, main () at hello.c:28
28	{
$(gdb) s
29	    printf("hello world\n");
$(gdb) s
__GI__IO_puts (str=0x555555556004 "hello world") at ioputs.c:33
33	ioputs.c: No such file or directory.
$(gdb) s
35	in ioputs.c
$(gdb) c
Continuing.
hello world
[Inferior 1 (process 4068) exited normally]
$q
$

4.3 执行回退

reverse-continue/rc 命令执行回退到上一个断点
调试中我的主机不支持这一个功能,就不再追溯相关功能!

$(gdb) break 32
Breakpoint 1 at 0x11df: file hello.c, line 32.
$(gdb) break 37
Breakpoint 2 at 0x1200: file hello.c, line 37.
$(gdb) info  breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011df in main at hello.c:32
2       breakpoint     keep y   0x0000000000001200 in main at hello.c:37
$(gdb) r
Starting program: /home/jianleya/trainning/C/print/hello.elf 
hello world

Breakpoint 1, main () at hello.c:32
32	    bar(1,2);
$(gdb) c
Continuing.

Breakpoint 2, main () at hello.c:37
37	    hum(&X);
$(gdb) rc
Target native does not support this command.

5. 函数返回

$(gdb) break fool 
Breakpoint 1 at 0x1169: file hello.c, line 10.
$(gdb) r
Starting program: /home/jianleya/trainning/C/print/hello.elf 
hello world

Breakpoint 1, fool () at hello.c:10
10	{
#return from fool
$(gdb) finish 
Run till exit from #0  fool () at hello.c:10
main () at hello.c:32
32	    bar(1,2);
$(gdb) 

三、实用方法

1. 函数栈操作

bt 命令用来查看 stack frame,每一个frame显示一行
f 用来选择特定的帧号(bt命令的输出编号)
up向上跳一帧
down向下跳一帧
info f 用来显示当前frame的基本信息
info args显示当前帧(函数)被调用时的参数
info locals显示当前帧的局部变量

$(gdb) break 29
Breakpoint 1 at 0x11ce: file hello.c, line 29.
$(gdb) break 17
Breakpoint 2 at 0x1190: file hello.c, line 17.
$(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011ce in main at hello.c:29
2       breakpoint     keep y   0x0000000000001190 in bar at hello.c:17

$(gdb) bt
No stack.

$(gdb) r
Starting program: /home/jianleya/trainning/C/print/hello.elf 
Breakpoint 1, main () at hello.c:29
29	    printf("hello world\n");
$(gdb) bt
#0  main () at hello.c:29

$(gdb) c
Continuing.
hello world
Breakpoint 2, bar (x=1, y=2) at hello.c:17
17	    int sum =  x + y;
$(gdb) bt
#0  bar (x=1, y=2) at hello.c:17
#1  0x00005555555551ee in main () at hello.c:32

$(gdb) f 0
#0  bar (x=1, y=2) at hello.c:17
17	    int sum =  x + y;
$(gdb) info args
x = 1
y = 2
$(gdb) info locals
sum = 9
$(gdb) info f
Stack level 0, frame at 0x7fffffffdfd0:
 rip = 0x555555555190 in bar (hello.c:17); saved rip = 0x5555555551ee
 called by frame at 0x7fffffffe000
 source language c.
 Arglist at 0x7fffffffdfb8, args: x=1, y=2
 Locals at 0x7fffffffdfb8, Previous frame's sp is 0x7fffffffdfd0
 Saved registers:
  rbp at 0x7fffffffdfc0, rip at 0x7fffffffdfc8
(gdb) bt
#0  bar (x=1, y=2) at hello.c:17
#1  0x00005555555551ee in main () at hello.c:32

$(gdb) f 1
#1  0x00005555555551ee in main () at hello.c:32
32	    bar(1,2);
$(gdb) info args
No arguments.
$(gdb) info locals
X = {id = 0, name = 0x555555555080 <_start> "\363\017\036\372\061\355I\211\321^H\211\342H\203\344\360PTL\215\005\006\002"}

$(gdb) up
#1  0x00005555555551ee in main () at hello.c:32
32	    bar(1,2);
$(gdb) down
#0  bar (x=1, y=2) at hello.c:17
17	    int sum =  x + y;
(gdb) 

2. 内存操作

2.1 文件和内存

$(gdb) !cat  -n vector.c 
     1	int arr[1000];
     2	
     3	int main(void)
     4	{
     5	    arr[0] = 99;
     6	    return  0;
     7	}
$(gdb) break 6
Breakpoint 1 at 0x113b: file vector.c, line 6.
$(gdb) p &arr 
$1 = (int (*)[1000]) 0x4040 <arr>
$(gdb) dump memory vector_arr &arr[0] &arrr[1000]
No symbol "arrr" in current context.
$(gdb) dump memory vector_arr &arr[0] &arr[1000]
$(gdb) dump value dump_val 1000+1000
$(gdb) append memory vector_arr &arr[0] &arr[1]
$(gdb) append value dump_val 64+1

2.2 生成corefile

$(gdb) break 53
Breakpoint 1 at 0x1282: file check.c, line 54.
$(gdb) r
Starting program: /home/jianleya/trainning/C/data/a.out 

Breakpoint 1, main () at check.c:54
54	    fool();
$(gdb) gcore  corefile
warning: Memory read failed for corefile section, 4096 bytes at 0xffffffffff600000.
Saved corefile corefile

3. 数据检的查

3.1 静态变量

/*cat static.c*/
int g_val = 100;
void fool()
{
    static int l_val = 200;
}

int main(void)
{


}

$(gdb) list main
3	{
4	    static int l_val = 200;
5	}
6	
7	int main(void)
8	{
9	
10	
11	}
$(gdb) b 9
Breakpoint 1 at 0x1141: file static.c, line 11.
$(gdb) r
Starting program: /home/jianleya/trainning/C/data/a.out 

Breakpoint 1, main () at static.c:11
11	}
$(gdb) print 'static.c'::g_val 
$1 = 100
(gdb) print 'static.c'::fool::l_val
$2 = 200
(gdb) p g_val 
$3 = 100
(gdb) p fool::l_val
$4 = 200

3.2 局部变量

局部变量受到当前frame的影响,function::variable 的表达式为上一帧当中的某个变量的值

$(gdb) !cat local.c 
int bar(int num);

void process(int a)
{
}

void foo(int a)
{
    if(a < 10)
        bar(a);
    else
    process(a);
}

int bar (int a)
{
    foo(a+5);
}

int main(void)
{
    bar(0);
    return 0;
}
$(gdb) break process 
Breakpoint 1 at 0x1129: file local.c, line 4.
$(gdb) info  breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000001129 in process at local.c:4
$(gdb) r
Starting program: /home/jianleya/trainning/C/data/a.out 

Breakpoint 1, process (a=32767) at local.c:4
4	{
$(gdb) up 1
#1  0x0000555555555162 in foo (a=10) at local.c:12
12	    process(a);
$(gdb) p a
$1 = 10
$(gdb) p bar::a
$2 = 5
$(gdb) up 2
#3  0x0000555555555156 in foo (a=5) at local.c:10
10	        bar(a);
$(gdb) p a
$3 = 5
$(gdb) p bar::a
$4 = 0

3.3 数组类型

$(gdb) !cat -n arr.c 
     1	#include <stdlib.h>
     2	int main(void)
     3	{
     4	    int arr[2] = {1,3};
     5	
     6	    int *array_ptr = (int*) malloc(8 * sizeof(int));
     7	    array_ptr[0] = 100;
     8	    array_ptr[1] = 200;
     9	
    10	    return 0;
    11	}
$(gdb) break 10
Breakpoint 1 at 0x11b8: file arr.c, line 10.
$(gdb) r
Starting program: /home/jianleya/trainning/C/data/a.out 

Breakpoint 1, main () at arr.c:10
10	    return 0;
$(gdb) p arr
$1 = {1, 3}
$(gdb) p arr[0]
$2 = 1
$(gdb) p arr[1]
$3 = 3

$(gdb) p array_ptr
$5 = (int *) 0x5555555592a0
$(gdb) p *array_ptr@1
$7 = {100}

$(gdb) p *array_ptr@8
$8 = {100, 200, 0, 0, 0, 0, 0, 0}
$(gdb) p  *(int*)arr@2
$9 = {1, 3}

4. 线程并发

$(gdb) !cat -n threads.cpp 
     1	#include <iostream>
     2	using namespace std;
     3	
     4	extern "C"
     5	{
     6	#include <unistd.h>
     7	#include <pthread.h>
     8	}
     9	
    10	static int fool_ret = 99;
    11	void* fool(void *arg)
    12	{
    13	    int oldcancelstate = 0;
    14	
    15	    cout << "fool thread func" << endl;
    16	    return &fool_ret;
    17	}
    18	
    19	
    20	
    21	int main(void)
    22	{
    23	    pthread_t thread1;
    24	    pthread_create(&thread1,NULL,fool,NULL);
    25	
    26	    void* retval = NULL;
    27	    if( 0 == pthread_join(thread1,&retval))
    28	    {
    29	    	cout << "Fool thread exited with retval " << *(int*)retval
    30	    		<< endl;
    31	    }
    32	
    33	    return 0;
    34	}
    35	
$(gdb) break 15
Breakpoint 1 at 0x1240: file threads.cpp, line 15.
$(gdb) r
Starting program: /home/jianleya/trainning/C/data/a.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff7a49700 (LWP 4036)]
[Switching to Thread 0x7ffff7a49700 (LWP 4036)]

Thread 2 "a.out" hit Breakpoint 1, fool (arg=0x0) at threads.cpp:15
15	    cout << "fool thread func" << endl;
$(gdb) info  threads
  Id   Target Id                                Frame 
  1    Thread 0x7ffff7a4a740 (LWP 4032) "a.out" __pthread_clockjoin_ex (threadid=140737348146944, thread_return=0x7fffffffdfa0, clockid=<optimized out>, abstime=<optimized out>, block=<optimized out>)
    at pthread_join_common.c:145
* 2    Thread 0x7ffff7a49700 (LWP 4036) "a.out" fool (arg=0x0) at threads.cpp:15
$(gdb) t 2
[Switching to thread 2 (Thread 0x7ffff7a49700 (LWP 4036))]
#0  fool (arg=0x0) at threads.cpp:15
15	    cout << "fool thread func" << endl;
$(gdb) bt
#0  fool (arg=0x0) at threads.cpp:15
#1  0x00007ffff7f95609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#2  0x00007ffff7cdb293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值