GDB扩展之Command File - 提高调试效率

简介: 工欲善其事,必先利其器。GDB的扩展可以通过command file和python脚本完成,这里针对Command file,一个简单高效的扩展方案。

工欲善其事,必先利其器。GDB的扩展可以通过command file和python脚本完成,这里针对Command file,一个简单高效的扩展方案。


一.简介

GDB Command File可以简单地理解为一串自定义的GDB指令,GDB同时允许用户使用define将一串GDB操作定义为一个指令。比如在命令行模式下将断点保存起来,下次执行时再加载进来,就可以通过两个自定义命令来完成:

define bsave

    shell rm -f brestore.txt

    set logging file brestore.txt

    set logging on

    info break

    set logging off

    # reformat on-the-fly to a valid gdb command file

    shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt >brestore.gdb

end


define brestore

  source brestore.gdb

end


在使用时就可以使用initGDB来代替执行其中的一组指令了。bsave可以把现有的断点以设定断点的指令存放到brestore.gdb中,加载时相当于直接执行brestore.gdb中的断点指令完成断点设定。 其中每一行都是有效的GDB指令或者注释。


如果这些指令定义在一个command文件中并由GDB在执行时自动加载,就可以简化操作。


二.GDB Command File的加载与使用

GDB Command File是一个纯文本文件,包含一串GDB指令,也包括define定义的自定义指令。在加载时使用GDB指令:

   source [-s] [-v] filename

  

   -s 表示在系统的PATH中搜索指定的文件,找到后加载。

   -v 表示打开verbose模式,会显示每条指令的执行。

  *-s和-v并不是所有的gdb都能支持。


在使用时,可以在GDB的命令行里手动执行,也可以在gdb的启动文件里(.gdbinit)定义。如果使用Eclipse调试时,还可以在Debugger里的Command File中指定:

   


2.1 为新指令添加帮助


使用document可以方便地为已通过define定义的指令添加注释,注释的内容也是以end结束。

比如:

document showKURL

  显示KRURL的内容,直接传入KRUL变量即可。

  *Horky

end


在gdb里分别使用show显示函数说明如下:

(gdb) help user-defined

showkurl -- 显示KRURL的内容

(gdb) help showkurl

显示KRURL的内容,直接传入KRUL变量即可。

*Horky

(gdb)



三.自定义指令的撰写


一个自定义指令可以理解为一个函数,基本结构如下:

define command_name

  #GDB指令或注释

end


几个要点:

  1. 函数的参数可以使用$arg0,$arg1,..来取得。

  2. 变量使用GDB指令set赋值,如set $var=2

  3. 返回值  因为各个自定义指令中的变量是共享的,就可以直接前面函数中定义的变量。

  4. 注释使用#打头即可。

  5. 一个代码块都是以end结束的。

  6. 指令间可以相互调用。

  


3.1 流程控制指令

在自定义指令中可以使用如下的控制语句,做一些比较复杂的操作。

1. 条件判断语句if

if {expression} 

else

end

  条件判断语句, if 后面所带的表达式为一般的GDB表达式, 可以使用==,&&,||之类的逻辑操作符。如:

   if $a==5

     #do something

   else 

     #do something else

   end


 2.循环语句while

   while {expression}

   end

 对应于C++循环中的break和continue, 可以使用loop_break和loop_continue指令。



3.2 补充指令

1. 变量赋值

  对于一变量直接赋值即可。字串变量可以使用下面的指令:

     set $string="value is %d",5

  详见参考1. 


2. 输出内容

程序中的输出可以使用以下几个指令:

echo

  echo用于输出字串, 不会自换行, 字串的引号会同样输出,适用输出一些提示信息。比如:

  echo "ouput is:"

  echo output\n


  输出的结果会是: "output is:"output

  

output {expression}

  用于输出表达式的结果。与print的区别在于,它的输出结果不会生成新的变量,且不会自动换行。比如:

  (gdb) output index

    2 (gdb)

  而print则会是下面的效果:

  (gdb) print index

   $1=2

  (gdb)


printf

  输出格式化字串. 比如printf "Value will be 0x%x",value


最后一个是最常用的print了, 前面已经分析过它与output的区别了,print还有一个好处,可以在后面的语句使用$取出上次print的结果。这是因为GDB定义了一组内部变量:

 $ : 取出上次的值

 $_ : 取出上次x指令最后输出的位置地址


   详见参考2.


3. 内存输出

内存输出操作x, 功能强大。基本格式为

   x/FMT address


FMT的详细格式为:nfu

  n : 是输出的个数

  f : 以什么格式输出, 比如 s:字串,i:机器指令,  x:16进制

  u : 输出数据的单位长度,比如b:单字节,h:双字节,  w: Words,四字节,g: Gian words, 八字节


 比如,下面示例中会用的,x/s 是输出ASCII字串,而x/hs则是输出UTF-16字串。

 

其它不在这里赘述。详见参考6.



四. 应用

4.1. 打印出JSDOMWindowShell关系列表

这个简单,就是基于一个值,打出它的上下依赖关系

#Print Hierarchy of JSDOMWindowShell

define showDOMWindowShell

  p $arg0

  p $arg0->world()

  p $arg0->window()

  p $arg0->window()->impl()

  p $arg0->window()->shell()

  p $arg0->impl()

  p $arg0->impl()->frame()

  p $arg0->impl()->document()

end


4.2. 打印出WTF::String的内容

在调用WebKit代码时,字串内容没办法直接显示出来。可以使用下面的指令完成:

define showStringVar

  showStringContent $arg0

 

  echo String:\n 

  if $flag&(1<<6)||$flag==0

       echo [ASCII]:

       x/s *(int *)((char *)($arg0.m_impl.m_ptr)+8)

  end

 

  echo [Unicode]:

  x/hs *(int *)((char *)($arg0.m_impl.m_ptr)+8)

 

   if $flag&(1<<2)

       print "*This is a identifier."

   end

    

   if $flag&(1<<1)

        print "*Masked Buffer Ownership."

   end

end


一开始先调用了一个指令showStringContent,内容如下:

#Paramter: String

define showStringContent

  echo Reference Count:

  p *(int *)($arg0.m_impl.m_ptr)

 

  echo Length:

  p *(int *)((char *)($arg0.m_impl.m_ptr)+4)

 

  echo Flag:

  set $flag = *(int *)((char *)($arg0.m_impl.m_ptr)+16)

  p/x $flag

end


转载请注明出处:http://blog.csdn.net/horkychen


参考:

  1. Convenience Variables

  2. Expressions

  3. Commands for Controlled Output

  4. [WebKit]C++类的数据结构及在反汇编上的应用

  5. 使用LLDB脚本简化打印复杂数据的操作

  6. Examine Memory

  7. User defined commands

   8. 转换GDB堆栈到流程图

相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
7月前
|
NoSQL 搜索推荐 openCL
【C/C++ 调试 GDB指南 】gdb调试基本操作
【C/C++ 调试 GDB指南 】gdb调试基本操作
396 2
|
7月前
|
NoSQL Linux 开发工具
【深入解析git和gdb:版本控制与调试利器的终极指南】(下)
【深入解析git和gdb:版本控制与调试利器的终极指南】
|
4月前
|
NoSQL Linux C语言
Linux GDB 调试
Linux GDB 调试
66 10
|
4月前
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
105 3
|
4月前
|
NoSQL
技术分享:如何使用GDB调试不带调试信息的可执行程序
【8月更文挑战第27天】在软件开发和调试过程中,我们有时会遇到需要调试没有调试信息的可执行程序的情况。这可能是由于程序在编译时没有加入调试信息,或者调试信息被剥离了。然而,即使面对这样的挑战,GDB(GNU Debugger)仍然提供了一些方法和技术来帮助我们进行调试。以下将详细介绍如何使用GDB调试不带调试信息的可执行程序。
108 0
|
6月前
|
NoSQL Linux C语言
Linux gdb调试的时候没有对应的c调试信息库怎么办?
Linux gdb调试的时候没有对应的c调试信息库怎么办?
45 1
|
6月前
|
NoSQL Linux C语言
Linux gdb调试的时候没有对应的c调试信息库怎么办?
Linux gdb调试的时候没有对应的c调试信息库怎么办?
34 0
|
6月前
|
NoSQL Linux C++
Linux C/C++ gdb调试正在运行的程序
Linux C/C++ gdb调试正在运行的程序
|
6月前
|
NoSQL Linux C++
Linux C/C++ gdb调试core文件
Linux C/C++ gdb调试core文件
|
6月前
|
NoSQL Linux C++
Linux C/C++ gdb调试
Linux C/C++ gdb调试