gdb使用教程.md

GDB使用教程

gdb 通过系统调用 ptrace 来接管一个进程的执行。ptrace 系统调用提供了一种方法使得父进程可以观察和控制其它进程的执行,检查和改变其核心映像以及寄存器。它主要用来实现断点调试和系统调用跟踪。

gdb 的三种调试方式

  1. 运行并调试一个新进程

    运行 gdb,通过命令行或 file 命令指定目标程序。
    输入 run 命令, gdb 执行下面的操作:

    • 通过 fork() 系统调用创建一个新进程
    • 在新创建的子进程中执行操作:ptrace(PTRACE_TRACEME, 0, 0, 0)
    • 在子进程中通过 execv() 系统调用加载用户指定的可执行文件
  2. attach 并调试一个已经运行的进程
    用户确定需要进行调试的进程 PID
    运行 gdb,输入 attach ,gdb 将对指定进程执行操作:ptrace(PTRACE_ATTACH, pid, 0, 0)
    远程调试目标机上新创建的进程
    gdb 运行在调试机上,gdbserver 运行在目标机上,两者之间的通信数据格式由 gdb 远程串行协议(Remote Serial Protocol)定义
    RSP 协议数据的基本格式为: $..........#xx
    gdbserver 的启动方式相当于运行并调试一个新创建的进程

断点的实现

断点的功能是通过内核信号实现的,在 x86 架构上,内核向某个地址打入断点,实际上就是往该地址写入断点指令 INT 3,即 0xCC。目标程序运行到这条指令之后会触发 SIGTRAP 信号,gdb 捕获这个信号,并根据目标程序当前停止的位置查询 gdb 维护的断点链表,若发现在该地址确实存在断点,则可判定为断点命中。
常用命令
break – b

break <address> 指定地址下断点 (最常用),如
VYKgvQLEBl.png!large
break 在所选栈帧中执行的下一条指令处设置断点。
break <function> 函数入口处设置断电
break <line> 源文件指定行下断点
break -N break +N 在源代码文件当前行的偏移 N 下断点。
break <filename:line> 在源码文件 filename 的 line 行处打断点。
break <filename:function> 在源码文件 filename 的 function 函数入口处打断点。
break ... if <cond> 设置条件断点,... 代表上述参数之一(或无参数),cond 为条件表达式,仅在 cond 值非零时停住程序。
x
检查内存,常用。
x/nfu <addr>
x <addr>
    n, f, 和 u 都是可选参数,用于指定要显示的内存以及如何格式化。
    addr 是要开始显示内存的地址的表达式。
    n 重复次数(默认值是 1),指定要显示多少个单位(由 u 指定)的内存值。
    f 显示格式(初始默认值是 x),显示格式是 print('x','d','u','o','t','a','c','f','s') 使用的格式之一,再加 i(机器指令)。
    u 单位大小,b 表示单字节,h 表示双字节,w 表示四字节,g 表示八字节。

info

我们在安装的 gdb 插件中可以看到这些信息,大家可以当作一个手册来查阅。

info breakpoints -- i b 查看断点,观察点和捕获点的列表。
    info breakpoints [list…]
    info break [list…]
    list… 用来指定若干个断点的编号(可省略),可以是 2, 1-3, 2 5 等。
info display 打印自动显示的表达式列表,每个表达式都带有项目编号,但不显示其值。
info reg 显示当前寄存器信息。
info threads 打印出所有线程的信息,包含 Thread ID、Target ID 和 Frame。
info frame 打印出指定栈帧的详细信息。
info proc 查看 proc 里的进程信息。

disassemble – disas

反汇编命令。

disas <func> 反汇编指定函数
disas <addr> 反汇编某地址所在函数
disas <begin_addr> <end_addr> 反汇编从开始地址到结束地址的部分

delete – d

删除断点。参数使用空格分隔。不带参数时删除所有断点。
clear

在指定行或函数处清除断点。参数可以是行号,函数名称或 * 跟一个地址。
disable – dis

禁用断点,参数使用空格分隔。不带参数时禁用所有断点。
finish – fin

执行直到选定的栈帧返回。
watch

为表达式设置观察点。每当一个表达式的值改变时,观察点就会停止执行您的程序。
backtrace – bt

打印整个栈的回溯。

bt 打印整个栈的回溯,每个栈帧一行。
bt n 类似于上,但只打印最内层的 n 个栈帧。
bt -n 类似于上,但只打印最外层的 n 个栈帧。
bt full n 类似于 bt n,还打印局部变量的值。

    注意:使用 gdb 调试时,会自动关闭 ASLR,所以可能每次看到的栈地址都不变。

step – s

单步执行程序,直到到达不同的源码行。
step [N] 参数 N 表示执行 N 次(或由于另一个原因直到程序停止)。
next – n

单步执行程序,执行完子程序调用。
next [N]
与 step 不同,如果当前的源代码行调用子程序,则此命令不会进入子程序,而是继续执行,将其视为单个源代码行。
return

您可以使用 return 命令取消函数调用的执行。如果你给出一个表达式参数,它的值被用作函数的返回值。

return <expression> 将 expression 的值作为函数的返回值并使函数直接返回。

print – p

求表达式 expr 的值并打印。可访问的变量是所选栈帧的词法环境,以及范围为全局或整个文件的所有变量。

print [expr]
print /f [expr] 通过指定 /f 来选择不同的打印格式,其中 f 是一个指定格式的字母

原文作者:GQQQy
转自链接:https://www.wangan.com/docs/671
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。

原文地址:https://www.cnblogs.com/nsfoxer/p/14348108.html