https://blog.atime.me/note/gdb-tricks.html

整理常用的gdb技巧。

常用命令

常用的gdb命令...

启动gdb

  1. 直接运行

    gdb --args prog arg1 arg2
    
  2. 运行gdb后使用run命令

    gdb prog
    run arg1 arg2
  3. attach到已运行的程序

    gdb --pid ${PID_OF_PROG}
    

ptype

ptype用于显示Symbol的类型,示例源码为:

struct ABC {
int val;
} int main() {
ABC abc;
return 0;
}

运行gdb:

(gdb) b 7
(gdb) r
(gdb) ptype abc type = struct XXX {
int val;
}

ptype可以输出表达式的返回类型,具体介绍可参考Examining the Symbol Table

print {type} variable

print(p)可以按照某种类型输出变量的值,示例源码如下:

struct ABC {
double val;
int val2;
} int main() {
ABC abc;
abc.val = 1.5;
abc.val2 = 10; void *pAbc = &abc; return 0;
}

运行gdb:

(gdb) b 13
(gdb) r (gdb) p pAbc
$1 = (void *) 0x7fffffffe710 (gdb) p {ABC} 0x7fffffffe710
$2 = {val = 1.5, val2 = 10} (gdb) p {ABC} pAbc
$3 = {val = 1.5, val2 = 10} (gdb) p * (ABC*) pAbc
$4 = {val = 1.5, val2 = 10} (gdb) p {double} pAbc
$5 = 1.5 (gdb) p * (double*) pAbc
$6 = 1.5 (gdb) p {int} (pAbc + sizeof (double))
$7 = 10 (gdb) p * (int*) (pAbc + sizeof (double))
$8 = 10

有时候,如果字符串太长,gdb可能只打印一部分,这时候如下设置来打印全部内容:

(gdb) set print elements 0

examine

examine(x)可以按照一定的格式打印内存地址处的数据,详细文档可参考这里

(gdb) x/{COUNT}{FMT}{SIZE} {ADDRESS}
  • {COUNT}: 打印的数目,默认为1。
  • {FMT}: 打印的格式1,默认为上次使用的{FMT}:
    • o(octal): 8进制整数
    • x(hex): 16进制整数
    • d(decimal): 10进制整数
    • u(unsigned decimal): 10进制非负整数
    • t(binary): 2进制整数
    • f(float): 浮点数
    • a(address): 输出相对于前面最近的符号的偏移
    • i(instruction): 输出地址处的汇编指令
    • c(char): 字符
    • s(string): c字符串(null-terminated string)
    • z(hex, zero padded on the left): 见说明
  • {SIZE}: 打印的字节数目,默认为上次使用的{SIZE}:
    • b(byte): 1个字节
    • h(halfword): 2个字节
    • w(word): 4个字节
    • g(giant, 8 bytes): 8个字节
  • {ADDRESS}: 目标地址

几个例子:

(gdb) x/a 0x401419
0x401419 <main()+113>: 0x55c3c900000000b8 (gdb) x/i 0x40138d
=> 0x40138d <crash(int, double)+41>: mov -0x10(%rbp),%eax (gdb) x/1fg 140737488346064
0x7fffffffdbd0: 10.125

设置源码目录

参考Specifying Source Directories,使用dir /path/to/your/sources可在调试时添加一个源码目录。

设置字符编码

gdb默认使用utf-8编码,可以使用如下命令修改编码。

set charset GBK

也可直接在~/.gdbinit里设置。

线程相关的命令

下面是一些调试多线程程序时常用的命令:

  • info threads: 查看线程列表
  • thread 2: 切换到2号线程,线程编号可由info threads得知
  • thread apply all bt: 打印所有线程的堆栈

高级技巧

一些不太广为人知的技巧...

加载独立的调试信息

gdb调试的时候可以从单独的符号文件中加载调试信息。

(gdb) exec-file test
(gdb) symbol-file test.debug

test是移除了调试信息的可执行文件, test.debug是被移除后单独存储的调试信息。参考stackoverflow上的一个问题,可以如下分离调试信息:

# 编译程序,带调试信息(-g)
gcc -g -o test main.c # 拷贝调试信息到test.debug
objcopy --only-keep-debug test test.debug # 移除test中的调试信息
strip --strip-debug --strip-unneeded test # 然后启动gdb
gdb -s test.debug -e test # 或这样启动gdb
gdb
(gdb) exec-file test
(gdb) symbol-file test.debug

分离出的调试信息test.debug还可以链接回可执行文件test中

objcopy --add-gnu-debuglink test.debug test

然后就可以正常用addr2line等需要读取调试信息的程序了

addr2line -e test 0x401c23

更多内容可阅读GDB: Debugging Information in Separate Files

在内存和文件系统之间拷贝数据

  1. 将内存数据拷贝到文件里

    dump binary value file_name variable_name
    dump binary memory file_name begin_addr end_addr
  2. 改变内存数据

    使用set命令

执行gdb脚本

常用的gdb操作,比如打断点等可以放在一个gdb脚本里,然后使用时导入即可。例如:

b main.cpp:15
b test.cpp:18

gdb运行时,使用source命令即可导入

(gdb) source /path/to/breakpoints.txt

或gdb运行时导入

gdb -x /path/to/breakpoints.txt prog

对于每次gdb运行都要调用的脚本,比如设置字符集等,可以放在~/.gdbinit初始文件里,这样每次gdb启动时都会自动调用。

输出到文件

可以通过set logging on将命令的输出保存到默认的gdb.txt文件中。当然也可以通过set logging file my_log.txt来设置输出文件的路径。

执行命令并退出

有时候需要gdb执行若干条命令后就立即退出,而不是进入交互界面,这时可以使用-batch选项。

gdb -ex "set pagination 0" -ex "thread apply all bt" -batch -p $pid

上面的命令打印$pid进程所有线程的堆栈并退出。

自定义命令

参考gdb/Define,可以在gdb中自定义命令,比如:

(gdb) define hello
(gdb) print "welcome"
(gdb) print "hello $arg0"
(gdb) end

然后如此调用

(gdb) hello world

即可输出

(gdb) $1 = "welcome"
(gdb) $2 = "hello world"

条件断点

在条件断点里可以调用标准库的函数,比如下面这个:

# 如果strA == strB,则在断点处暂停
(gdb) b main.cpp:255 if strcmp(strA.c_str(), strB.c_str()) == 0 # 还是上面的场景,直接用string类的compare函数
(gdb) b main.cpp:255 if strA.compare(strB) != 0

捕获exception

gdb遇到未处理的exception时,并不会捕获处理。但是参考Set Catchpoints,可以使用catch catch命令来捕获exception。

阅读资料

  1. Copy between memory and a file
  2. HowTo: Writing into process memory with GDB
  3. Specifying Source Directories
  4. Examining the Symbol Table

GDB技巧整理的更多相关文章

  1. IT第十天 - String和StringBuffer的比较、编程设计技巧整理、本周总结 ★★★

    IT第十天 上午 String 1.String在进行多次的+扩展时,会严重的降低处理效率,因为String长度是不可变的,在进行+运算改变字符串时,会自动创建很多临时字符串,并不是在原字符串上追加, ...

  2. Tensorflow小技巧整理:修改张量特定元素的值

    TensorFlow小技巧整理:修改张量特定元素的值 最近在做一个摘要生成的项目,过程中遇到了很多小问题,从网上查阅了许多别人解决不同问题的方法,自己也在旁边开了个jupyter notebook搞些 ...

  3. sqlmap常用技巧整理

    言 通过在乌云网上出现的很多SQL注入漏洞,因此来总结一下,大致使用SQLMAP所遇到的参数. 基本结构 基本SQLMAP的使用方式就如下所示,使用参数式的方式,按需求添加. 12 sqlmap.py ...

  4. aptana studio 使用技巧整理

    aptana studio 使用技巧整理 https://192.168.1.16/web/punica/adaptana studio 使用技巧整理http://uedfans.cn/ 推荐一个网站 ...

  5. sql事务的使用及其技巧整理

    sql事务的使用及其技巧整理 概述: 在实际项目开发中,为了确保数据操作结果的一致性等要求,事务是一个必不可少的解决利器. 根据SQLSERVER实现原理,其实,SQLSERVER的每一条执行语句都是 ...

  6. apache环境.htaccess设置301跳转及常用.htaccess技巧整理

    apache环境.htaccess设置301跳转及常用.htaccess技巧整理 无论是Nginx,还是Apache都各自有优势,对于我们普通用户而言基本上也没有多大的区别.在虚拟主机环境中,基本上都 ...

  7. linux下gdb调试方法与技巧整理

    参考博客:  https://blog.csdn.net/niyaozuozuihao/article/details/91802994 1.运行命令run:简记为 r ,其作用是运行程序,当遇到断点 ...

  8. CSS对浏览器的兼容性(IE和Firefox)技巧整理

    CSS对浏览器的兼容性有时让人很头疼,或许当你了解当中的技巧跟原理,就会觉得也不是难事,从网上收集了IE7,6与Fireofx的兼容性处理技巧并整理了一下.对于web2.0的过度,请尽量用xhtml格 ...

  9. Linux/Mac OS 个人常用Terminal技巧整理

    刚开始接触linux有些不适应,走了不少弯路,一直没有系统的学过linux应用,基本都是零零散散Google出来的知识,在这里做个整理: Vi/Vim 基本操作: 刚开始接触linux时,不懂vi吃了 ...

随机推荐

  1. 【python】闰年规则

    公历闰年判定遵循的规律为: 四年一闰,百年不闰,四百年再闰. 公历闰年的简单计算方法(符合以下条件之一的年份即为闰年)1.能被4整除而不能被100整除.2.能被400整除.

  2. 用Django搭建个人博客—(2)

    今日任务: 1 blog的数据库模型定义 2 简单的注册登录功能的实现 项目的源文件已经推送到git@oschina.net. 所以,如果想要参阅源码的请移步 (Fork) http://git.os ...

  3. 常用webservice接口案例

    商业和贸易: 1.股票行情数据 WEB 服务(支持香港.深圳.上海基金.债券和股票:支持多股票同时查询) Endpoint: http://webservice.webxml.com.cn/WebSe ...

  4. NET Core站点部署到Linux服务器

    .NET跨平台之旅:将QPS 100左右的ASP.NET Core站点部署到Linux服务器上 今天下午我们将生产环境中一个单台服务器 QPS(每秒请求数)在100左右的 ASP.NET Core 站 ...

  5. Laravel之路——事务

    准备: 表必须是InnoDB引擎 DB::beginTransaction(); try{ $name = 'abc'; $result1 = Test::create(['name'=>$na ...

  6. leetcode power(x,n)

    class Solution { public: double pow(double x, int n) { double a=1; if(n==0)return 1; if(x==1)return ...

  7. ubuntu下为opera26.0安装flash

    因为 Adobe Flash 不再支持 linux Google 便开发了PepperFlashPlayer来替代原来的 Adobe Flash 下面介绍 PepperFlashPlayer 在安装方 ...

  8. h.264 scanning process for transform coefficients

    宏块在经过变换.量化后,得到大小为4x4或者8x8的矩阵,矩阵中的数据被称为transform coefficient levels.这些level在后面会被用于熵编码,因此我们需要把矩阵按照一定顺序 ...

  9. SlimFTPd, LFTP和FileZilla Client/Server

    https://lftp.yar.ru/ 绝好的Socket项目

  10. [LeetCode#246] Missing Ranges Strobogrammatic Number

    Problem: A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked a ...