一、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快速入门相关推荐

  1. python开发工具pycharm快速入门

    本教程是关于什么的 本教程旨在引导您完成创建,运行和调试一个简单的Python项目,使用PyCharm一步一步 - Python的IDE有一整套完整的生产性的开发工具. 本教程不是关于哪些的 Pyth ...

  2. python开发工具与pycharm_python开发工具pycharm快速入门

    本教程旨在引导您完成创建,运行和调试一个简单的Python项目,使用PyCharm一步一步 - Python的IDE有一整套完整的生产性的开发工具. 本教程不是关于哪些的 Python编程超出了本教程 ...

  3. Windriver驱动开发工具使用快速入门

    平台:ise14.7,Win driver10.21,Visual Studio 2015 操作系统:Windows7 硬件设备:PCI板卡 最近在开发过程中,作为一个逻辑开发人员,在有的的情况下需要 ...

  4. GNU开发工具的使用方法

    GNU开发工具的使用方法 一.vi编辑器使用方法 1.1 vi编辑器 1.2 vi的基本命令 二.makefile的编写 2.1 makefile简介 2.2 make命令 2.3 隐含规则 三.gc ...

  5. GNU开发工具简介(一)

    第一节 GNU Tools开发工具简介 GNU开发工具 为了有效地进行嵌入式开发,至少需要了解和掌握如下几类工具: 编译开发工具:即能够把一个源程序编译生成一个可执行程序的软件,如gcc等. 调试工具 ...

  6. ppt制作工具python-pptx 快速入门

    ppt制作工具python-pptx 快速入门 转载:https://www.jianshu.com/p/23734d34d788 hello #!/usr/bin/env python3 # -*- ...

  7. 游戏开发的HelloWorld,快速入门,新手上路,使用CocosCreator+JS,flyBird(飞翔小鸟)

    游戏开发的HelloWorld,快速入门,新手上路,使用CocosCreator+JS,flyBird(飞翔小鸟) 介绍 开发环境 游戏原理 文件结构 详细操作 全部代码 介绍 拓展什么的都没有,真正 ...

  8. HTML5+app开发学习之快速入门篇

    HTML5+app开发学习之快速入门篇 5+app开发概念理解相关 开发环境与支持 快速入门实战 5+app开发概念理解相关 见博文:学习跨平台移动应用开发必须理解的一些概念 开发环境与支持 开发环境 ...

  9. ecshop二次开发的简单快速入门教程

    ecshop二次开发的简单快速入门教程,具体请下载文档 ecshop_dwt_lbi_详解.rar (106 KB) 下载次数: 9 转载于:https://my.oschina.net/u/3360 ...

最新文章

  1. awk rand函数问题
  2. 高手勿入:不肝不氪,又能有参与证明的13个比赛活动来了
  3. Springboot整合缓存
  4. Nagios 监控平台快速安装
  5. cookie分号后面没有值_浏览器Cookie介绍
  6. 一段简单的python代码_一个简单的python写的C/S程序
  7. leetcode—10.栈题型python解答
  8. 西门子step7安装注册表删除_如何完全删除step 7
  9. 博科光纤交换机IP+端口策略应用
  10. 最长公共子串计算C++
  11. 读《大数据时代:生活,工作与思维的大变革》
  12. 《刻意练习》读书心得 驳斥1万小时定律、有目的的练习、自我实现的预言、走出舒适区
  13. sp01事务码_修复了Server 2003 SP2上的“新事务无法在指定事务协调器中登记”
  14. lua深拷贝一个table
  15. 腾讯云CentOS7运行基于SSM的个人博客----第三节:使用Dokcer安装JDK、Tomcat环境
  16. 小米会成为三星没落的因素吗?
  17. Blueprint介绍和使用
  18. C#安装Newtonsoft.Json并调用
  19. 自然图像抠图/视频抠像技术发展情况梳理(image matting, alpha matting, video matting)--计算机视觉专题1
  20. 如何实现MySQL增量备份与恢复?

热门文章

  1. 房地产---那些事2
  2. 软件需求分析与设计 课后小测验 知识点总结 东北大学
  3. 网络运维(Python自动化运维)考点
  4. 用EasyPoi导出Excel中单元格图片(线上阿里云)
  5. scala的filter函数
  6. Nginx 学习笔记
  7. k8s args和command
  8. C语言程序:评委打分类题型
  9. 【刘浩运7.19作业】
  10. win10 激活脚本执行bat