GNU开发工具——GDB快速入门
一、GDB简介
GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。GDB能够跟踪程序的执行,也能够恢复程序崩溃前的状态。
GDB常规功能如下:
A、自定义程序的启动方式(指定影响程序运行的参数)
B、设置条件断点(在条件满足时暂停程序的运行)
C、回溯检查导致程序异常结束的原因(Core Dump)
D、动态改变程序的执行流(定位问题的辅助方式)
二、GDB功能
1、core dump
核心转储文件(Core Dump)是进程内存的拷贝,ulimit -c显示核心转储文件大小的最大值,0表示禁止核心转储。ulimit -c unlimited设置核心转储文件大小无限制。
ulimit -c unlimited只对当前终端环境有效,重新登陆会被重置。永久有效需要修改ulimit配置文件/etc/security/limits.conf。
#<domain> <type> <item> <value>* soft core unlimited
generate-core-file命令或gcore命令可以为调试进程产生core dump文件。
gdb program core_file
加载可执行程序和core dump文件
2、GDB启动
(1)直接启动
gdb
进入GDB调试环境
gdb program
调试模式启动program
gdb program core
执行program程序和core文件
gdb -tui
启动gdb,并且分屏显示源代码
gdb --args program -f config.ini
启动gdb,并指定参数
(2)动态连接
gdb program pid
调试正在运行的程序,进程号为pid,GDB会自动进行attach
(3)运行程序
run
运行载入的可执行程序
run args arg1 arg2
带参数运行可执行程序
(4)GDB调试示例
gdb
启动GDB
file program
载入目标可执行文件
set args arg1 arg2
设置命令行参数
run
执行目标程序
attach pid
链接到目标进程,链接成功后目标进程将停止执行
continue
恢复执行目标进程
stop
停止运行
3、信息显示
show version
显示GDB版本
gdb -q
不显示提示信息启动GDB
set confirm off
退出时不显示提示信息
set pagination off
输出信息多时不会暂停输出
info sharedlibrary regex
显示共享连接库信息
set charset GBK
设置字符编码,GDB默认使用utf-8编码。
shell command
在GDB调试环境执行shell命令
4、源码查看
dir /path/to/your/sources
添加一个源码目录到调试环境
list line
显示程序第linenum行周围的程序
list function
显示函数名为function的函数的源程序
list
显示当前行后面的源程序
list -
显示当前行前面的源程序
set listsize n
设置list可以查看源码行数,默认为10行
5、环境变量
show convenience
查看当前的所有环境变量
set env env_name=value
设置环境变量
set var var_name=value
设置变量,var_name必须是调试环境中的变量名称
set args arg1 arg2
设置可执行程序的命令行参数
print var_name=value
修改变量值
6、函数
info functions
查看程序中函数符号
info args
frame N
查看当前函数参数的值
info locals
查看当前局部变量的值
info variables
查看程序中的变量符号
info registers
查看函数寄存器信息
info frame
查看当前函数调用的栈帧信息
frame n
切换到栈编号为N的函数栈帧
backtrace
查看函数调用的顺序,函数调用栈信息
set step-mode on
进入不带调试信息的函数
return expression或者finish
退出正在调试的函数
disassemble function
查看函数反汇编代码
set debug entry-values 1
打印尾调用堆栈帧信息
call function
强制调用某函数,会显示函数返回值(如果函数返回值不是void)。
start function
执行函数,并停在函数开始位置
7、Catch Point
tcatch
让catchpoint只触发一次
catch fork
为fork调用设置catchpoint
catch vfork
为vfork调用设置catchpoint
catch exec
为exec调用设置catchpoint
catch syscall name or num
为系统调用设置catchpoint
catch syscall ptrace set $rax=0
通过ptrace调用设置catchpoint破解anti-debugging的程序
8、打印
set print elements number-of-elements
设置打印数组元数的最大数量
set print elements 0set print elements unlimited
设置打印数组元素不限制
set print pretty on
优化打印格式,每行打印一个结构体成员
set print object on
按照派生类打印对象
set print address [on/off]
设置参数地址打印模式,GDB具有支持是否显示参数地址信息的功能,用户可以设置其为打开或者关闭
show print address
查看当前参数地址打印模式
set print array [on/off]
设置数组打印模式,如果打开数组显示,数组中每个元素都占用一行;如果关闭,每个元素都以逗号分开,默认关闭。
set print array-indexes on
设置打印时打印数组的索引下标
print vec
打印STL容器中的内容
print array[index]@num
打印数组中任意连续的元素值
print *array@num
打印数组中开头的前num各数组元素
backtrace fullinfo locals
打印函数局部变量的值
info proc mappingsinfo files
打印进程的内存信息
print 'file.c'::var_name
打印静态变量的值
print /Nuf var_name
打印变量
examine(x) /Nuf expression
检查存储区域的数据
N:要打印的单元数量
u:单元大小,b单字节,h双字节,w四字节,g八字节
f:数据打印格式,x十六进制,d有符号十进制,u无符号十进制,o八进制,t二进制,a地址,c字符,f浮点数
9、汇编
set disassembly-flavor intel disassemble main
设置汇编指令格式
break *main
在函数的第一条汇编指令打断点
set disassemble-next-line onset disassemble-next-line autoset disassemble-next-line off
自动反汇编后面要执行的代码
disas /m main
将源程序和汇编指令映射起来
display /i $pc
显示将要执行的汇编指令
info registers i all-registers i registers eax
打印寄存器的值
disassemble /r main
显示程序原始机器码, 反汇编命令,查看执行时源代码的机器码。
10、信号
info signals
查看信号
handle signal stop/nostop
信号发生时是否暂停程序
handle signal print/noprint
信号发生时是否打印信号信息
handle signal pass(noignore)/nopass(ignore)
信号发生时是否把信息丢给程序处理
signal signal_name
给程序发送信号
11、GUI支持
gdb -tui program
进入图形化调试界面
ctrl+x+a
TUI(terminal user interface)终端用户界面切换
layout asm
显示汇编代码窗口
layout regs
显示寄存器窗口
winheight <win_name> [+ | -]count
调整窗口大小
三、GDB断点调试
1、断点简介
软件断点:由非法指令异常实现(软件实现)
硬件断点:由硬件特性实现(数量有限)
数据断点:由硬件特性实现(数量有限)
2、软件断点
通过函数名设置断点
break func_name [if var = value]tbreak func_name [if var = value]
break设置的断点是永久断点,tbreak设置的断点是临时断点,运行一次后将失效。
通过文件名行号设置断点
break file_name:line_num [if var = value]tbreak file_name:line_num [if var = value]info breakpoints
查看所有断点
delete 1 2 n
删除断点
enable 1 2 n
开启断点
enable breakpoints
开启所有断点
disable 1 2 n
关闭断点
disable breakpoints
关闭所有断点
print name
变量查看
set var name=value
变量设置
next n
连续执行n行代码,默认为1行
return expression
强制当前函数返回
finish
运行至当前函数返回
until lineNum
执行至目标行
jump line
调转执行
break *address
在程序地址上打断点,如break *0x400522
break *0x400440
在程序入口处打断点,程序入口地址可以通过readelf -h program或在GDB调试环境中通过info files获取,Entry point: 0x400440。
break linebreak file:lineinfo breakpoints
在文件行号上打断点
save breakpoints file-breakpoints-to-savesource file-breakpoints-to-save
保存已经设置的断点
tbreak line
设置临时断点
break line if cond b 11 if i==10
设置条件断点
ignore bnum count
忽略断点
break +offset/-offset
在当前行号的前面或后面offset停住
break filename:linenum 在某文件的某行打断点break filename:function 在某文件某个函数入口停住break *address 在程序的运行地址处停住break where if condition 当某个条件满足时,在某一行停住
ignore <break_list> count
表示break_list所指定的断点号将被忽略count次。
step count
一次性执行count步,如果有函数会进入函数
next count
一次执行count,不进入函数
finish
运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值以及参数信息
until
退出循环体
continue命令
当程序被停住后,可以使用continue(c)命令,恢复程序的运行直到程序结束,或到达下一个断点。
在条件断点中可以调用标准库函数
break main.cpp:255 if strcmp(strA.c_str(), strB.c_str()) == 0break main.cpp:255 if strA.compare(strB) != 0
jump命令不会改变程序栈内容,一般只在同一函数内跳转。
jump linespec 指定下一条语句的运行点,linespec可以是linenum,filename+linenum,+offset几种形式
jump address 跳到代码行的地址
3、硬件断点
当代码位于只读存储器(flash)时,只能通过硬件断点调试。
硬件断点需要硬件支持,数量有限。
GDB通过hbreak命令支持硬件断点。
show can-use-hw-watchpoints
显示当前GDB支持硬件断点的数量
hbreak使用同break相同。
4、数据断点
GDB支持数据断点的设置。
watch用于观察某个表达式的值是否有变化,如果有变化,马上停住程序。
watch命令用于监视变量是否被改变(本质为硬件断点)。
watch expression
为表达式expression设置一个观察点,一旦表达式值有变化,马上停住程序
rwatch expression
当表达式expression被读时,停住程序
awatch expression
当表达式的值被读或被写时,停住程序。
info watchpoints
列出所有观察点
wacth *(type*)adress disable/enable/delete
设置观察点
info threads
watch expression thread threadnum
设置观察点只针对特定线程生效
四、多进程调试
1、多进程调试模式
(1)follow-fork-mode选项
Linux 2.5.60版本内核开始,GDB对使用fork/vfork创建子进程的程序提供了follow-fork-mode选项来支持多进程调试。
follow-fork-mode调试选项参数用于指示fork子进程后GDB对父进程还是子进程进行调试。
set follow-fork-mode [parent|child]
parent: fork后继续调试父进程,子进程不受影响,默认值。
child: fork后调试子进程,父进程不受影响。
如果不设置follow-fork-mode选项,GDB默认调试父进程。
(2)detach-on-fork选项
detach-on-fork调试选项参数用于指示GDB在fork后是否detach某个进程的调试还是都交由GDB控制。
set detach-on-fork [on|off]
on:断开调试follow-fork-mode指定的进程。
off:GDB将控制父进程和子进程。follow-fork-mode指定的进程将被调试,另一个进程置于暂停(suspended)状态。
(3)进程调试模式实践
默认设置下,在调试多进程程序时GDB只会跟踪调试主进程。GDB(>V7.0)支持多进程分别以及同时调试,需要设置follow-fork-mode(默认值:parent)和detach-on-fork(默认值:on)选项。
follow-fork-mode detach-on-fork 说明
parent on 只调试主进程(GDB默认)
child on 只调试子进程
parent off 同时调试两个进程,GDB跟踪主进程,子进程block在fork位置
child off 同时调试两个进程,GDB跟踪子进程,主进程block在fork位置
2、GDB进程调试命令
info inferiors
查询正在调试的进程
inferior pid
切换进程
3、子进程调试
(1)运行program,然后使用ps -ef | grep program搜索到子进程pid。
(2)启动GDB,在将子进程attach到GDB调试器上。
attach child-pid
被attach的进程会阻塞,进入T模式(ps 命令看到STATE为T),如果调试完毕使用 detach 命令就释放进程。
(3)恢复运行子进程
直接run即可
(4)detach子进程
五、多线程调试
1、GDB多线程调试模式
GDB调试一般有两种模式:all-stop模式和no-stop模式。
(1)all-stop模式
在all-stop模式下,GDB调试程序时一旦程序因为任何原因而停止,所有的线程都会停止,而不仅仅是当前线程。通常,GDB不能step所有的线程,因为线程调度是GDB无法控制的。因此,当GDB停止可执行程序时会自动切换到触发断点的线程。
(2)no-stop模式
在no-stop模式下,GDB调试程序时一旦程序因为任何原因而停止,只有当前线程会被停止,而其它线程会继续运行。step,next等单步调试命令只对当前线程起作用。
no-stop模式设置必须在程序运行前进行设置。
如果需要打开no-stop模式,可以向~/.gdbinit添加配置文件:
#Enable the async interfaceset target-async 1#If using the CLI, pagination breaks non-stopset pagination off#Finall, turn it onset non-stop on
GDB支持的命令有两种类型:同步和异步。同步的在输出提示符之前会等待程序report一些线程已经终止的信息,异步则是直接返回。
set pagination off不要出现 Type <return> to continue 的提示信息 。最后一步是打开。
(3)线程锁定模式
线程锁定模式必须在程序运行中进行设置,GDB在执行step/continue命令时,所有线程都会执行。通过设置线程锁定模式可以实现线程隔离控制。
set scheduler-locking [off/on/step]
off:不锁定任何线程,即所有线程同时执行命令;
on:只有当前被调试线程才会执行命令;
step:当执行step操作时,只有当前线程会被执行;执行continue时,所有线程会被执行。
2、GDB多线程调试命令
info threads
查看当前进程中所有线程,GDB会给每个运行中的线程分配一个id号,id号从1开始,前面带*的是当前正在调试的线程。
thread id
切换到线程号为id的线程,id为info threads表格中第一列的值,如果id为空,则打印当前所在的线程号。
break [,location] [,thread ]
为某个位置设置断点,多线程环境下Location对所有线程都适用。
thread apply [,ids...] [command]:
让一个线程id序列全部应用command包含的GDB命令。
thread apply all command
让所有线程执行GDB命令
break filename:linenum thread all
在所有线程相应行设置断点,注意如果主线程不会执行到该行,并且启动all-stop模式,主线程执行n或s会切换过去
show scheduler-locking
显示当前模式
3、Linux多线程调试命令
ps aux | grep [,name]
查看名为name的进程详细信息,通常用于获取进程号。
pstree -p [,id]
列出主线程与子线程的关系
ps stack [,threadId]
查看线程栈
4、多线程调试实例
生产者消费者模型源码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
#include <list>pthread_mutex_t g_mutex;
std::list<int> g_pool;void *consumer(void *param)
{while (1){pthread_mutex_lock(&g_mutex);int result = g_pool.front();g_pool.pop_front();printf("consume %d\n", result);pthread_mutex_unlock(&g_mutex);sleep(1);}return NULL;
}void *producer(void *param)
{static int n = 1;while (1){pthread_mutex_lock(&g_mutex);g_pool.push_back(n++);printf("produce %d\n", n - 1);pthread_mutex_unlock(&g_mutex);sleep(1);}return NULL;
}int main()
{pthread_t tid_c, tid_p;void *retval;g_pool.push_back(0);pthread_mutex_init(&g_mutex, NULL);pthread_create(&tid_p, NULL, producer, NULL);pthread_create(&tid_c, NULL, consumer, NULL);pthread_join(tid_p, &retval);pthread_join(tid_c, &retval);return 0;
}
编译:
g++ -g test.c -o test -pthread
调试:
gdb test
启动GDB调试环境,并载入test
watch g_pool
监视g_pool变量
display g_pool
断点时打印g_pool
run
运行程序
info threads
查看线程信息
thread 2
切换到线程2
continue
继续运行,查看线程2的g_pool的值变化情况
六、高级功能
1、独立调试信息加载
GDB调试时可以从单独的符号文件中加载调试信息。
gcc -g -o test main.c
编译带调试信息可执行文件
objcopy --only-keep-debug test test.debug
从可执行文件拷贝调试信息到test.debug
strip --strip-debug --strip-unneeded test
移除test中的调试信息
gdb -s test.debug -e test
指定调试符号信息文件和可执行文件,启动GDB
exec-file test
在GDB环境载入可执行文件
symbol-file test.debug
在GDB环境载入调试符号信息文件
objcopy --add-gnu-debuglink test.debug test
将分离的调试信息test.debug链接回可执行文件test中
addr2line -e test 0x401c23
addr2line读取调试信息
2、dump数据
dump binary value file_name variable_name
将内存数据拷贝到文件里
dump binary memory file_name begin_addr end_addr
改变内存数据
3、输出重定向
set logging on
将输出保存到默认gdb.txt文件中
set logging file log_file
设置输出文件
4、自定义命令
在GDB调试环境定义一个命令hello:
define hello
print "welcome"
print "hello $arg0"
end
调用hello命令:
hello world
输出结果:
$1 = "welcome"$2 = "hello world"
5、定义命令钩子
钩子用于在执行某个命令前或命令后,先执行某个或某些命令。
假如想在print命令前显示一段 “----------”,则:
define hook-print echo ----------/n end
hook-后接的必须是命令全称。
如果想在命令执行完,再执行某个或某些命令,则:
define hookpost-print echo ----------/n end
6、宏查看
默认情况下,在GDB中是不能查看宏的值及定义的,可以通过如下方法查看:
(1)编译源代码时,加上“-g3 -gdwarf-2”选项,必须为“-g3”。
(2)查看宏的值使用命令print macro_name。
(3)查看宏定义,使用macro expand macro_name命令。
GNU开发工具——GDB快速入门相关推荐
- python开发工具pycharm快速入门
本教程是关于什么的 本教程旨在引导您完成创建,运行和调试一个简单的Python项目,使用PyCharm一步一步 - Python的IDE有一整套完整的生产性的开发工具. 本教程不是关于哪些的 Pyth ...
- python开发工具与pycharm_python开发工具pycharm快速入门
本教程旨在引导您完成创建,运行和调试一个简单的Python项目,使用PyCharm一步一步 - Python的IDE有一整套完整的生产性的开发工具. 本教程不是关于哪些的 Python编程超出了本教程 ...
- Windriver驱动开发工具使用快速入门
平台:ise14.7,Win driver10.21,Visual Studio 2015 操作系统:Windows7 硬件设备:PCI板卡 最近在开发过程中,作为一个逻辑开发人员,在有的的情况下需要 ...
- GNU开发工具的使用方法
GNU开发工具的使用方法 一.vi编辑器使用方法 1.1 vi编辑器 1.2 vi的基本命令 二.makefile的编写 2.1 makefile简介 2.2 make命令 2.3 隐含规则 三.gc ...
- GNU开发工具简介(一)
第一节 GNU Tools开发工具简介 GNU开发工具 为了有效地进行嵌入式开发,至少需要了解和掌握如下几类工具: 编译开发工具:即能够把一个源程序编译生成一个可执行程序的软件,如gcc等. 调试工具 ...
- ppt制作工具python-pptx 快速入门
ppt制作工具python-pptx 快速入门 转载:https://www.jianshu.com/p/23734d34d788 hello #!/usr/bin/env python3 # -*- ...
- 游戏开发的HelloWorld,快速入门,新手上路,使用CocosCreator+JS,flyBird(飞翔小鸟)
游戏开发的HelloWorld,快速入门,新手上路,使用CocosCreator+JS,flyBird(飞翔小鸟) 介绍 开发环境 游戏原理 文件结构 详细操作 全部代码 介绍 拓展什么的都没有,真正 ...
- HTML5+app开发学习之快速入门篇
HTML5+app开发学习之快速入门篇 5+app开发概念理解相关 开发环境与支持 快速入门实战 5+app开发概念理解相关 见博文:学习跨平台移动应用开发必须理解的一些概念 开发环境与支持 开发环境 ...
- ecshop二次开发的简单快速入门教程
ecshop二次开发的简单快速入门教程,具体请下载文档 ecshop_dwt_lbi_详解.rar (106 KB) 下载次数: 9 转载于:https://my.oschina.net/u/3360 ...
最新文章
- awk rand函数问题
- 高手勿入:不肝不氪,又能有参与证明的13个比赛活动来了
- Springboot整合缓存
- Nagios 监控平台快速安装
- cookie分号后面没有值_浏览器Cookie介绍
- 一段简单的python代码_一个简单的python写的C/S程序
- leetcode—10.栈题型python解答
- 西门子step7安装注册表删除_如何完全删除step 7
- 博科光纤交换机IP+端口策略应用
- 最长公共子串计算C++
- 读《大数据时代:生活,工作与思维的大变革》
- 《刻意练习》读书心得 驳斥1万小时定律、有目的的练习、自我实现的预言、走出舒适区
- sp01事务码_修复了Server 2003 SP2上的“新事务无法在指定事务协调器中登记”
- lua深拷贝一个table
- 腾讯云CentOS7运行基于SSM的个人博客----第三节:使用Dokcer安装JDK、Tomcat环境
- 小米会成为三星没落的因素吗?
- Blueprint介绍和使用
- C#安装Newtonsoft.Json并调用
- 自然图像抠图/视频抠像技术发展情况梳理(image matting, alpha matting, video matting)--计算机视觉专题1
- 如何实现MySQL增量备份与恢复?