GDB简单使用

发布于 2018-07-28  612 次阅读


  • 借鉴文章1
  • 借鉴文章2
  • 环境

    Kali Linux

    测试代码

    #include <stdio.h>
    
    int check (int num) {
        if (num == 10) {
            printf("Correct\n");
            return 1;
        }    
        return -1;
    }
    
    int main() {
        int num;
        printf("Please input a number:\n");
        scanf("%d", &num);
        while (1) {
            if (check(num) == 1)
                break;
            else {
                printf("Wrong number\n");
                printf("Please input a number:\n");
                scanf("%d", &num);
            } 
        }
    }
    

    要用gdb调试程序,必须在编译时加上-g选项,-g选项的作用是在可执行文件中加入源文件信息,但并不是将源文件嵌入可执行文件,所以在调试时必须保证gdb必须能找到源文件,输入gcc -g test.cpp -o test,然后会生成一个可调试test的可执行文件

    调试过程

    开始和退出调试

  • 输入gdb进入GDB调试器
  • 输入quit(q)或者按下Ctrl-d退出
  • 输入gdb test后的界面

  • GDB简单使用

    列文件清单list命令

  • list(l)显示10行代码,若再次运行该命令则显示接下来的10行代码
  • GDB简单使用

  • list(1) 5,10 显示源代文件test.c中的第5行到第10行的代码
  • GDB简单使用

  • list(1) check 显示check 函数周围的代码
  • GDB简单使用

    执行程序run,start,c,n,s,finish,until,kill命令

  • 输入run(r)连续执行程序,直到遇到断点
  • 输入start可以开始执行程序,gbd会自动在第一条语句的地方下一个断点
  • 输入continue(c)可以直接运行到下一个断点的位置
  • GDB简单使用

  • 输入nset(n)后可以单步步过调试
  • 输入step(s)可以单步步入调试
  • GDB简单使用

  • 输入finish可以退出已经进入的某函数返回到它的调用函数中
  • GDB简单使用

  • 输入until结束当前循环
  • 输入kill(k)可以终止程序
  • GDB简单使用

    显示数据print,ptype,examine命令

  • 输入print(p) 格式(可以不加) 变量名可以输出改变量的值
  • /x 按十六进制格式显示变量
  • /d 按十进制格式显示变量
  • /u 按十六进制格式显示无符号整型
  • /o 按八进制格式显示变量
  • /t 按二进制格式显示变量
  • /a 按十六进制格式显示变量
  • /c 按字符格式显示变量
  • /f 按浮点数格式显示变量
  • GDB简单使用

  • 输入print(p)后面加上'&'(取地址符)加上变量名可以输出改变量的值
  • GDB简单使用

  • 输入ptype后面加上一个变量名可以显示该变量类型
  • GDB简单使用

  • 输入examine(x)可以按照一定的格式打印内存地址处的数据
  • (gdb) x/{COUNT}{FMT}{SIZE} {ADDRESS}
  • {COUNT}: 打印的数目,默认为1。
  • {FMT}: 打印的格式1,默认为上次使用的
  • {FMT}:

  • o(octal): 8进制整数
  • x(hex): 16进制整数
  • d(decimal): 10进制整数
  • u(unsigned decimal): 10进制非负整数
  • t(binary): 2进制整数
  • f(float): 浮点数
  • a(address): 输出相对于前面最近的符号的偏移
  • i(instruction): 输出地址处的汇编指令
  • c(char): 字符
  • s(string): c字符串(null-terminated string)
  • z(hex, zero padded on the left): 见说明
  • {SIZE}: 打印的字节数目,默认为上次使用的{SIZE}:

  • b(byte): 1个字节
  • h(halfword): 2个字节
  • w(word): 4个字节
  • g(giant, 8 bytes): 8个字节
  • {ADDRESS}: 目标地址

    GDB简单使用

    backtrace,frame,call命令

  • 输入backtrace(bt)可以查看函数调用的栈帧。
  • #0  check (num=3) at test.cpp:4
    #1  0x00005555555546eb in main () at test.cpp:16
    

    num=3是我们输入的参数,#0,#1表示当前函数的执行顺序,at后面的地址就是在源代码里的位置。

  • 输入frame(f) n,n为栈的层次可以查看其调用函数的信息
  • GDB简单使用

  • 输入call 函数 可以调用和执行一个函数,显示其返回值(如果有的话)
  • GDB简单使用

    断点

  • 输入break(b)后面加上断点的行号或者函数名
  • GDB简单使用

  • 输入break(b)加上行号或者函数名加上条件,条件断点
  • GDB简单使用

  • 输入watch 变量名 当程序访问变量名指定的内存单元时,停止程序
  • GDB简单使用

  • 输入info breakpoints可以查看断点信息,clear加上行号可以删除断点或者delete断点编号也可以删除断点
  • GDB简单使用

    info命令(部分)

  • info args 打印出当前函数的参数名及其值。
  • info locals 打印出当前函数中所有局部变量及其值。
  • info catch 打印出当前的函数中的异常处理信息。
  • info line 打印出来要查看源代码在内存中的地址。info line后面可以跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”,这个命令会打印出所指定的源码在运行时的内存地
  • info break 打印出断点信息。
  • info threads 打印正在运行程序中的线程信息
  • info registers 打印寄存器的情况。(除了浮点寄存器)
  • info all-registers 打印所有寄存器的情况。(包括浮点寄存器)
  • info registers 查看所指定的寄存器的情况。

  • GDB简单使用