gdb调试基础

2023年 10月 15日 116.5k 0

前言

GDB是程序员调试的必备工具,使用GDB可以解决大部分程序错误问题。

当然还有其他的使用方式,比如近期在项目中就使用GDB截图的方式通过了商密检测,截图作为一种方式证明了数据的确是真实的。

这几天刷头条,偶然刷到了GDB相关的文章,顺便搞个文章重新梳理一下GDB的知识结构及使用方法。

GDB

编译

为了便于调试,最好在程序编译时为gcc命令加上-g选项进行编译。测试程序随机生成给定数目的数据数据。

# test.c


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int max_length = 128;

static uint32_t get_rand(uint8_t *a, uint32_t byteLen)
{
    int result = 0;
    int fd = open("/dev/urandom", O_RDONLY);
    if (fd < 0) {
            fd = open("/dev/random", O_RDONLY);
    if (fd < 0) {
            fprintf(stderr, "get rand failn");
            return 0;
        }
    }

    result = read(fd, a, byteLen);
    if (result  max_length){
    num = max_length;
  }

  buffer = generate(num);

  printf ("Random string is: %sn",buffer);

  sleep(10);

  free (buffer);

  return 0;
}



启动调试

启动调试命令最简单的方式是:


gcc -g test.c -o test

GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
Copyright (C) 2022 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
.
Find the GDB manual and other documentation resources online at:
    .

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...
(gdb) b main
Breakpoint 1 at 0x12b2: file test.c, line 21.
(gdb)



断点

设置断点


break  main # 函数断点

b test.c:58 # 文件行号断点, b是break的省略写法

b test.c:28 58 num == 9 # 条件断点

tbreak test.c:58 # 临时断点,这个断点只会断一次,后续不会再断到

info b # 查看已经设置的断点

# 禁用断点

disable  	# 禁用所有断点
disable bnum # 禁用指定标号的断点
enable  	# 启用所有断点
enable bnum # 启用指点标号的断点
enable delete bnum      # 启动标号为bnum的断点,并且在断到后删除该断点

# 断点清除
 clear                   # 删除当前行所有breakpoints
clear function          # 删除函数名为function处的断点
clear filename:function # 删除文件filename中函数function处的断点
clear lineNum           # 删除行号为lineNum处的断点
clear f:lename:lineNum  # 删除文件filename中行号为lineNum处的断点
delete                  # 删除所有breakpoints,watchpoints和catchpoints  delete可以省略为d
delete bnum             # 删除断点号为bnum的断点 


变量查看

变量查看: 最常用的就是print(简写为p) 变量

查看内存: 使用examine(简写为x) 内存地址, 语法如下:


x/[n][f][u] addr

# 格式 f
b 字节
h 半字,即双字节
w 字,即四字节
g 八字节

n 表示要显示的内存单元数,默认值为1
f 表示要打印的格式,前面已经提到了格式控制字符
u 要打印的单元长度
addr 内存地址

# 例如:
(gdb) x/32b buffer
0x555555559ac0: 0xa2    0x0a    0xc6    0x6c    0xcb    0xe8    0xb4    0x66
0x555555559ac8: 0x5a    0x96    0xb1    0x6a    0x00    0xc4    0x5b    0x5b
0x555555559ad0: 0xa2    0x05    0x12    0x73    0x04    0x97    0x13    0xc6
0x555555559ad8: 0x9e    0x2c    0x5a    0x8f    0x18    0xb3    0xd2    0x35


查看寄存器: info registers

(gdb) info registers
rax            0x555555559ac0      93824992254656
rbx            0x0                 0
rcx            0x7ffff7d15157      140737351078231
rdx            0x20                32
rsi            0x555555559ac0      93824992254656
rdi            0x3                 3
rbp            0x7fffffffe350      0x7fffffffe350
rsp            0x7fffffffe320      0x7fffffffe320
r8             0x1999999999999999  1844674407370955161
r9             0x555555559ac0      93824992254656
r10            0x0                 0
r11            0x246               582
r12            0x7fffffffe468      140737488348264
r13            0x555555555388      93824992236424
r14            0x555555557d78      93824992247160
r15            0x7ffff7ffd040      140737354125376
rip            0x5555555553fd      0x5555555553fd 
eflags         0x207               [ CF PF IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0


调试

单步调试,使用next(简写为n), next num // 继续执行num行

单步进入, step(简写为s), 一般用于进入当前行的函数,但前提是该函数有调试信息并且有源码信息。

断点继续, continue(简写为c),直接继续后面的程序

源码查看list

我们可以使用list命令, 显示当前运行的代码。


(gdb) list  # 默认显示前后共10行代码
46
47        return buffer;
48      }
49
50      int main(int argc, char *argv[])
51      {
52        int num;
53        char * buffer;
54
55        printf ("Input the string length : ");
(gdb)

# 敲回车,继续显示后面10行
(gdb)
56        scanf ("%d", &num);
57
58        if(num > max_length){
59          num = max_length;
60        }
61
62        buffer = generate(num);
63
64        printf ("Random string is: %sn",buffer);
65

# list + 行号, 显示行号周围的10行

(gdb) list 10
5       #include 
6       #include 
7       #include 
8       #include 
9       #include 
10      #include 
11      #include 
12      #include 
13      #include 
14      #include 
(gdb)

# list  开始行号,结束行号 , 显示开始行号 ---》 结束行号的代码

(gdb) list 10, 20
10      #include 
11      #include 
12      #include 
13      #include 
14      #include 
15      #include 
16
17      int max_length = 128;
18
19      static uint32_t get_rand(uint8_t *a, uint32_t byteLen)
20      {


# list -  查看前面那个list命令前的10行

(gdb) list -
1
2       #include 
3       #include 
4       #include 
5       #include 
6       #include 
7       #include 
8       #include 
9       #include 

# list 函数名,查看函数附近的10行

(gdb) list  get_rand
15      #include 
16
17      int max_length = 128;
18
19      static uint32_t get_rand(uint8_t *a, uint32_t byteLen)
20      {
21          int result = 0;
22          int fd = open("/dev/urandom", O_RDONLY);
23          if (fd < 0) {
24                  fd = open("/dev/random", O_RDONLY);

# list  文件名:行号  查看指定文件的行号附近10行
# list 文件名:函数名 查看指定文件的函数附近10行

layout

layout命令可以分隔窗口,让我们一边看源码一边调试。

主要有以下几种用法:
layout src:显示源代码窗口
layout asm:显示汇编窗口
layout regs:显示源代码/汇编和寄存器窗口
layout split:显示源代码和汇编窗口
layout next:显示下一个layout
layout prev:显示上一个layout
Ctrl + L:刷新窗口
Ctrl + x,再按1:单窗口模式,显示一个窗口
Ctrl + x,再按2:双窗口模式,显示两个窗口

Ctrl + x,再按a:回到传统模式,即退出layout,回到执行layout之前的调试窗口。

gdb_layout.png

其他1

这段时间在忙一个新项目,项目组只有我一个人在吭哧吭哧的投入,其他人指望不了,工作一两年的那些同事真的没有战斗力。

硅前的工作,使用pld(paladin)环境进行验证,效率还是蛮低的,但是工作量却不少。

去年,做另一个项目的时候,投入了3个人搞了近两个月的时间,到这个项目的时候就我一个人,时间也只给三个月,呵呵,其中的滋味只有自己知道了。

而且工作量可以说比前面那个项目更多了,以前只验证基础的功能,这次还得测试各种不一样的场景及性能,加油吧。

So,忙的博客都没时间搞了,这边已经积累了很多素材了,争取每周末继续总结回顾,活到老学到老啊。

其他2

本来下半年准备报考系统架构师考试的,昨天才想起来,9月底报名的时间已经错过了,那就准备准备明年的系统分析师吧。

像我这等普通人,真的是没有毅力按计划自觉复习,进度慢而且不成体系,针对这种应试类的考试,就上网报了个班,也许只有花了真金白银了,才能驱使自己去努力了,不然每天的时间其实都是被浪费了。

加油吧,争取明年上半年通过系统分析师,明年下半年再考系统架构师。

在国企里面上班,学历已经落后他人了,虽然有想法想要提升学历,但是考研没有个一年半载的准备,自己肯定是拿不下的。先从职称这方面入手,一步步来,精力毕竟是有限的,各个击破吧。

回想高三那段拼搏的岁月,还是蛮怀念的,累是累,但是结果还是好的,毕竟考上了大学,走出了农村,不再需要如父辈那般干着体力活,为基本的生活而奔波。

行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。

博客地址: fishmwei.github.io

掘金主页: juejin.cn/user/208432…

相关文章

服务器端口转发,带你了解服务器端口转发
服务器开放端口,服务器开放端口的步骤
产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
如何使用 WinGet 下载 Microsoft Store 应用
百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

发布评论