基于linux命令行的gdb总结

时间:2022-02-22 04:04:43

基于linux命令行的gdb总结

基本使用

首先使用gdb的前提是编译的时候加上-g参数。例如有一下代码

/* bugging.c */
#include <stdio.h>
int foo(int n)
{
    int sum;
    int i;
    for (i=0; i<=n; i++)
    {
        sum = sum+i;
    }
    return sum;
}

int main(int argc, char** argv)
{
    int result = 0;
    int N = 100;
    result = foo(N);
    printf("1+2+3+...+%d= %d\n", N, result);
    return 0;
}

首先编译文件,如果gdb没安装的自行sudo安装下

g++ bugging.c -g

1,敲击run执行程序,结果如下,退出为quit

(gdb) run
Starting program: /home/cwl/Desktop/code/gdb/gdbtest/a.out 
1+2+3+...+100= 26895
[Inferior 1 (process 6322) exited normally]

其他相关命令

命令 简写形式 说明
list l 查看源码
backtrace bt、where 打印函数栈信息
next n 执行下一行
step s 一次执行一行,遇到函数会进入
finish 运行到函数结束
continue c 继续运行
break b 设置断点
info breakpoints 显示断点信息
delete d 删除断点
print p 打印表达式的值
run r 启动程序
until u 执行到指定行
info i 显示信息
help h 帮助信息

在 gdb 命令行界面,输入 help command 可以查看命令的用法,command 是你想要查询的命令。

在 gdb 命令行界面可以执行外部的 Shell 命令:!shell 命令

例一,查看源代码

list 行号
list 文件名:行号
list 函数名

例二,断点调试

  • 设置断点
break 行号,断点设置在该行开始处,注意:该行代码未被执行
break 文件名 : 行号,适用于有多个源文件的情况。
break 函数名,断点设置在该函数的开始处,断点所在行未被执行:
break 文件名 : 函数名,适用于有多个源文件的情况。
  • 查看断点信息
info breakpoints 命令用于显示当前断点信息。

其中
---
Num 列代表断点编号,该编号可以作为 delete/enable/disable 等控制断点命令的参数
Type 列代表断点类型,一般为 breakpoint
Disp 列代表断点被命中后,该断点保留(keep)、删除(del)还是关闭(dis)
Enb 列代表该断点是 enable(y) 还是 disable(n)
Address 列代表该断点处虚拟内存的地址
What 列代表该断点在源文件中的信息
  • 删除断点
delete Num,删除指定断点,断点编号可通过 info breakpoints 获得:
delete,不带任何参数,默认删除所有断点:
  • 关闭和启用断点

disable 命令和 enable 命令分别用于关闭和启用断点:

disable 命令用于关闭断点,有些断点可能暂时不需要但又不想删除,便可以 disable 该断点。

enable 命令用于启用断点。

disable Num,关闭指定断点,断点编号可通过 info breakpoints 获得:
disable,不带任何参数,默认关闭所有断点。
enable Num,启用指定断点,断点编号可通过 info breakpoints 获得。
enable,不带任何参数,默认启用所有断点。

disable 和 enable 命令影响的是 info breakpoints 的 Enb 列,表示该断点是启用还是关闭

  1. 打印变量

调试的过程中需要观察变量或者表达式的值,所以先介绍两个基本的显示变量值的命令:

  • info locals

    打印当前断点处所在函数的所有局部变量的值,不包括函数参数。

  • print 变量或表达式

    打印表达式的值,可显示当前函数的变量的值、全局变量的值等

    print/FMT 可以控制打印的格式,常见的有x(十六进制)、t(二进制)、c(显示为字符)等。

  1. 启动程序

run 命令用于启动待调试程序,并运行到断点处停下。

  • run

    不带任何参数,启动待调试程序,不传递参数。

  • run 参数

    有些程序需要跟参数,直接带上参数列表即可,会传递给 main 函数的 argc、argv 变量。

  1. 单步命令

next, step, finish, continue, until 用于控制整个调试过程中,程序执行的流程。

  • next

    next 单步执行,函数调用当做一条指令,不会进入被调用函数内部

    next N,表示单步执行N次

  • step

    step 单步执行,会进入到函数调用内部

    step N,表示单步执行N次

  • finish

    执行程序到当前函数结束

  • continue

    执行程序到下个断点

  • until

    until N,执行程序到源代码的某一行

例三,查看函数栈

gdb bugging
> (gdb) break foo
> (gdb) info breakpoints

run
info proc mappings  #查看待调试进程的内存分布情况

下面[STACK]就是进程栈空间了

process 12217
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
      0x555555554000     0x555555555000     0x1000        0x0 /home/cwl/Desktop/code/gdb/gdbtest/a.out
      0x555555754000     0x555555755000     0x1000        0x0 /home/cwl/Desktop/code/gdb/gdbtest/a.out
      0x555555755000     0x555555756000     0x1000     0x1000 /home/cwl/Desktop/code/gdb/gdbtest/a.out
      0x555555756000     0x555555777000    0x21000        0x0 [heap]
      0x7ffff70f2000     0x7ffff72a3000   0x1b1000        0x0 /lib/x86_64-linux-gnu/libc-2.27.so
      0x7ffff72a3000     0x7ffff74a2000   0x1ff000   0x1b1000 /lib/x86_64-linux-gnu/libc-2.27.so
      0x7ffff74a2000     0x7ffff74a6000     0x4000   0x1b0000 /lib/x86_64-linux-gnu/libc-2.27.so
      0x7ffff74a6000     0x7ffff74a8000     0x2000   0x1b4000 /lib/x86_64-linux-gnu/libc-2.27.so
      0x7ffff74a8000     0x7ffff74ac000     0x4000        0x0 
      0x7ffff74ac000     0x7ffff74c3000    0x17000        0x0 /lib/x86_64-linux-gnu/libgcc_s.so.1
      0x7ffff74c3000     0x7ffff76c2000   0x1ff000    0x17000 /lib/x86_64-linux-gnu/libgcc_s.so.1
      0x7ffff76c2000     0x7ffff76c3000     0x1000    0x16000 /lib/x86_64-linux-gnu/libgcc_s.so.1
      0x7ffff76c3000     0x7ffff76c4000     0x1000    0x17000 /lib/x86_64-linux-gnu/libgcc_s.so.1
      0x7ffff76c4000     0x7ffff7856000   0x192000        0x0 /lib/x86_64-linux-gnu/libm-2.27.so
      0x7ffff7856000     0x7ffff7a55000   0x1ff000   0x192000 /lib/x86_64-linux-gnu/libm-2.27.so
      0x7ffff7a55000     0x7ffff7a56000     0x1000   0x191000 /lib/x86_64-linux-gnu/libm-2.27.so
      0x7ffff7a56000     0x7ffff7a57000     0x1000   0x192000 /lib/x86_64-linux-gnu/libm-2.27.so
      0x7ffff7a57000     0x7ffff7bc9000   0x172000        0x0 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
      0x7ffff7bc9000     0x7ffff7dc9000   0x200000   0x172000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
      0x7ffff7dc9000     0x7ffff7dd3000     0xa000   0x172000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
      0x7ffff7dd3000     0x7ffff7dd5000     0x2000   0x17c000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
---Type <return> to continue, or q <return> to quit---
      0x7ffff7dd5000     0x7ffff7dd8000     0x3000        0x0 
      0x7ffff7dd8000     0x7ffff7dfd000    0x25000        0x0 /lib/x86_64-linux-gnu/ld-2.27.so
      0x7ffff7fce000     0x7ffff7fd4000     0x6000        0x0 
      0x7ffff7ff7000     0x7ffff7ffa000     0x3000        0x0 [vvar]
      0x7ffff7ffa000     0x7ffff7ffc000     0x2000        0x0 [vdso]
      0x7ffff7ffc000     0x7ffff7ffd000     0x1000    0x24000 /lib/x86_64-linux-gnu/ld-2.27.so
      0x7ffff7ffd000     0x7ffff7ffe000     0x1000    0x25000 /lib/x86_64-linux-gnu/ld-2.27.so
      0x7ffff7ffe000     0x7ffff7fff000     0x1000        0x0 
      0x7ffffffdc000     0x7ffffffff000    0x23000        0x0 [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]

backtrace 查看函数调用栈的情况

backtrace、where、info stack

这三个命令都可以查看函数的调用情况

backtrace full、where full、info stack full

这三个命令查看函数调用情况的同时,打印所有局部变量的值

  • 栈帧(stack frame)

    #1 是 main 函数用到的栈空间,这一部分可以称之为 main 函数的 stack frame

    #0 是 foo 函数用到的栈空间,同样可称之为 foo 函数的 stack frame,0 代表当前执行停在 foo 函数内

    可以得到函数调用关系为,main 调用 foo

  • info frame Num 查看某个函数栈帧的详细信息

(gdb) info frame 0 # <=============== commond ==================
Stack frame at 0x7fffffffcbd0:
 rip = 0x555555554680 in foo (bugging.c:13); saved rip = 0x5555555546b8
 called by frame at 0x7fffffffcc00
 source language c++.
 Arglist at 0x7fffffffcbc0, args: n=100
 Locals at 0x7fffffffcbc0, Previous frame's sp is 0x7fffffffcbd0
 Saved registers:
  rbp at 0x7fffffffcbc0, rip at 0x7fffffffcbc8
(gdb) info frame 1 # <=============== commond ==================
Stack frame at 0x7fffffffcc00:
 rip = 0x5555555546b8 in main (bugging.c:24); saved rip = 0x7ffff7113a87
 caller of frame at 0x7fffffffcbd0
 source language c++.
 Arglist at 0x7fffffffcbf0, args: argc=1, argv=0x7fffffffccd8
 Locals at 0x7fffffffcbf0, Previous frame's sp is 0x7fffffffcc00
 Saved registers:
  rbp at 0x7fffffffcbf0, rip at 0x7fffffffcbf8