GDB扩展之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堆栈到流程图

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Linux下使用VS Code进行快速调试C语言的步骤如下: 1. 首先,确保你的Linux系统已经安装了GCC编译器。如果没有安装,可以通过在终端中运行以下命令来安装: ``` sudo apt-get update sudo apt-get install build-essential ``` 2. 下载并安装VS Code。可以通过官方网站下载并按照指示安装。 3. 打开VS Code后,在左侧的扩展栏中搜索并安装C/C++扩展。 4. 创建一个新的C语言项目。选择“File”菜单中的“New File”,然后将文件保存为以`.c`为扩展名的文件。 5. 编写你的C源代码。 6. 在顶部菜单栏中选择“View” -> “Command Palette”(或使用键盘快捷键Ctrl+Shift+P)。然后在搜索框中输入“C/C++: Select a configuration”,选择“C/C++: Select a configuration”,选择“GCC”,以便配置C/C++扩展使用GCC编译器。 7. 接下来,在顶部菜单栏中选择“Run” -> “Add Configuration”,然后选择“C/C++: (gdb) Launch”作为调试器。 8. 在VS Code中的`launch.json`文件中,添加以下配置: ```json "version": "0.2.0", "configurations": [ { "name": "C/C++: (gdb) Launch", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/your_code.c", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb" } ] ``` 将`"program"`字段的值更改为你的C代码文件路径。 9. 现在,你可以在VS Code的编辑器窗口中设置断点。点击行号旁边的空白区域即可设置断点。 10. 最后,点击顶部菜单栏中的“Run”按钮或使用快捷键F5来开始调试你的C程序。 以上就是在Linux下使用VS Code进行快速调试C语言的步骤。在调试过程中,可以使用VS Code提供的调试控制台来查看程序的输出和变量的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值