一、基础命令
1、前提
当前文件夹下有源代码,可以编译成可执行文件
编译时引入调试信息,以供gdb使用。需加上-g参数 gcc -o test test.c -g
2、选取要调试的文件
(1)、gdb回车
进入gdb调试界面
指定要执行的程序 调试程序的加载:file 可执行文件名
(2)、gdb 可执行文件名
gdb a.out
(3)、gdb 进程号
gdb --pid xxxx
gdb -p xxx
3、启动 退出
启动run 简写r
run,直接运行整个程序,程序直接运行
start,启动程序,程序停留在main函数开始的地方,这时候可以做一些前置工作,如设置断电、参数等等
如在调试过程中,程序退出,需要重新run
退出quit 简写q
4、断点
设置断点:break 简写b
三种方式:
(1)、break 函数名 --> run 运行到到此函数处(接下来要执行的语句,还未执行)如想继续,可继续continue,程序运行到最后
(2)、break 源码文件名:行号 ps:b test.c:9 设置断点在test.c第九行
(3)、break 函数名 if 条件。条件断点设置,如 b function if a>b。
删除断点:delete 断点序号 不加序号则删除所有断点
5、向下执行
单步执行 next 简写n
6、进入到函数内部
step,单步执行遇到函数,想进入到函数内部,可以用step进入。简写 s
7、查看
查看程序接下来要执行的代码list
查看一些信息info 如:info b查看断点。简写i
8、查看打印变量/函数的值
print 表达式 简写p
print 变量的名字 查看变量的值
print 函数名 查看函数的值,即地址
print 数组名 查看数组的值
print 数组名[n] 查看数组某一元素的值
9、让GDB记录输出信息到文件
(gdb) set logging on -> 打开记录功能。
(gdb) set logging off -> 关闭记录功能。
(gdb) show logging -> 显示记录功能中每个选项的设置。
Future logs will be written to gdb.txt. —> 表示log 没有打开
Currently logging to “gdb.txt”. --> 表示log 已经打开
# (gdb) set logging file <文件名>
# (gdb) set logging on
# (gdb) thread apply all bt
# (gdb) set logging off
# (gdb) quit
10、多进程调试
调试父进程: set follow-fork-mode parent(缺省)
调试子进程:set follow-fork-mode child
设置调试模式:set detach-on-fork [on|off],缺省时on,表示调试当前进程的时候,其他的进程继续运行,如果用off。调试当前进程的时候,其他的进程被gdb挂起。
查看调试的进程:info inferiors
切换当前调试的进程:inferior 进程id
11、多线程调试
在shell中执行:
执行当前运行的进程:ps -aux | grep 需要查看的进程名
查看当前运行的轻量级进程,即线程:ps -aL | grep 进程名
查看主线程和新线程的关系:pstree -p 主线程id
在gdb中调试:
查看线程:info threads
切换线程:thread 线程id
只运行当前线程:set scheduler-locking on
运行全部的线程:set scheduler-locking off
指定某线程执行某gdb命令:thread apply 线程id 命令
全部的线程执行某gdb命令:thread apply all 命令
二、命令
运行指令:
- run(简写r): 运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步命令
- continue(简写c) : 继续执行,到下一个断点停止(或运行结束)
- next(简写n) : 单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同 step 的主要区别是,step 遇到用户自定义的函数,将步进到函数中去运行,而 next 则直接调用函数,不会进入到函数体内。
- step (简写s):单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的
- until(简写u):当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。
- until+行号: 运行至某行,不仅仅用来跳出循环
- finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
- call 函数(参数):调用程序中可见的函数,并传递“参数”,如:call gdb_test(55)
- quit(简写q) : 退出gdb
设置断点:
- break n (简写b n):在第n行处设置断点(可以带上代码路径和代码名称: b OAGUPDATE.cpp:578)
- b fn1 if a>b:条件断点设置
- break func(break缩写为b):在函数func()的入口处设置断点,如:break cb_button
- delete 断点号n:删除第n个断点
- disable 断点号n:暂停第n个断点
- enable 断点号n:开启第n个断点
- clear 行号n:清除第n行的断点
- info b (info breakpoints) :显示当前程序的断点设置情况
- delete breakpoints:清除所有断点:
查看源代码:
- list :简记为 l ,其作用就是列出程序的源代码,默认每次显示10行。
- list 行号:将显示当前文件以“行号”为中心的前后10行代码,如:list 12
- list 函数名:将显示“函数名”所在函数的源代码,如:list main
- list :不带参数,将接着上一次 list 命令的,输出下边的内容。
打印表达式
- print 表达式(简记p): 其中“表达式”可以是任何当前正在被测试程序的有效表达式,比如当前正在调试C语言的程序,那么“表达式”可以是任何C语言的有效表达式,包括数字,变量甚至是函数调用。
- print a:将显示整数 a 的值
- print ++a:将把 a 中的值加1,并显示出来
- print name:将显示字符串 name 的值
- print gdb_test(22):将以整数22作为参数调用 gdb_test() 函数
- print gdb_test(a):将以变量 a 作为参数调用 gdb_test() 函数
- display 表达式:在单步运行时将非常有用,使用display命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式及值。如: display a
- watch 表达式:设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序。如: watch a
watch log_sys->lsn - whatis :查询变量或函数
- info function: 查询函数
- 扩展info locals: 显示当前堆栈页的所有变量
查询运行信息
- where/bt :当前运行的堆栈列表;
- bt backtrace 显示当前调用堆栈
- up/down 改变堆栈显示的深度
- set args 参数:指定运行时的参数
- show args:查看设置好的参数
- info program: 来查看程序的是否在运行,进程号,被暂停的原因。
- finish :执行完当前函数返回到调用它的函数:
这里,运行程序,直到当前函数运行完毕返回再停止。例如进入的单步执行如果已经进入了某函数,而想退出该函数返回到它的调用函数中,可使用命令finish.
1、调试技巧
(1)、回车继续上一次操作
(2)、字母+tab键 自动获取当前以字母开头的命令。如n+tab 可以找到next nexti
(3)、上下方向箭头,可以查看历史命令(与shell一样)
(4)、Ctrl+x+a 或者tui enable
(5)、Ctrl+x+2进入到寄存器界面Ctrl+x+1回到tui代码界面 up down
查看寄存器 tui reg Ctrl+p可以查看之前的命令 Ctrl+n向后
2、使用GDB调试时attach ID不被允许
在进入gdb后,直接使用attach ID,出现下面的情况:
Could not attach to process. If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user. For more details, see /etc/sysctl.d/10-ptrace.conf
原因是Ubuntu 16.04 的/etc/sysctl.d/10-ptrace.conf文件中最后一行默认
kernel.yama.ptrace_scope = 1
这个值不允许用户使用普通账户使用attach ID连接程序进行调试,需要使用超级用户权限才能连接。
可以把kernel.yama.ptrace_scope的值改为 0,即
sudo vim /etc/sysctl.d/10-ptrace.conf
将最后一行改为 kernel.yama.ptrace_scope = 0,保存退出。
重启系统后,普通用户就可以使用attach ID连接程序调试了。