gdb 调试高级命令

原文链接:http://blog.csdn.net/hejinjing_tom_com/article/details/9472041


1. gdb 运行初始化命令 -x usercmd

    在.gdbinit 初始化命令中, 可以用#(同bash 注释符合)来注释

    可以用source 在启动gdb 后运行gdb 命令文件

    可以用file 在启动gdb 后再加载文件

2. gdb 传递命令行 参数
a. run
b. set args  
可用 show args 查看

3. gdb 中宏的操作
默认编译的时候,调试过程是看不见宏的值的。编译时候需要给选项。-g3
gcc  -g3 -o test.c  test
gdb test
察看宏(macro)命令: p macroname(...)  
就像察看一个普通变量一样。如果只想看宏的展开形势,就用如下命令:
macro expand macroname(...) 查看展开形式

还可以用info macro macroname 查看宏定义。


4. gdb 临时断点: tbreak

5. gdb 设置显示选项 . 
例如 set print pretty

打印结构变量类型. ptype struct 类型名

----------------------------------------
6.  让GDB记录输出信息到文件
----------------------------------------
(gdb) set logging on    -> 打开记录功能。
(gdb) set logging off -> 关闭记录功能。
(gdb) show logging -> 显示记录功能中每个选项的设置。
Future logs will be written to gdb.txt.   ---> 表示log 没有打开
Currently logging to "gdb.txt".    --> 表示log 已经打开

----------------------------------------

7. gdb 调试运行的进程

gdb -p <进程号>

或者:

gdb

attach <进程号>

----------------------------------------

下面不常用的功能,供了解
set logging file -> 改变记录文件,默认记录文件是gdb.txt。
set logging overwrite [on|off] -> 默认这个项目是关闭,
也就是以添加的形式将记录信息写入文件,这样之前文件中的信息不会被覆盖掉。
注意:如果设置这个选项的时候记录功能已经打开,需要关闭记录功能再重新打开才能起作用。
set logging redirect [on|off] -> 设置输出信息只记录到文件不作显示。
默认这个项目是关闭的,GDB将输出信息到终端和记录文件。如果打开这个项目,GDB将只输出信息到记录文件。
注意:如果设置这个选项的时候记录功能已经打开,需要关闭记录功能再重新打开才能起作用。
注意:记录功能只能记录GDB的输出信息,被调试程序的输出信息仍然会输出到终端。

---------------------------------------
7. 为什么没有core文件生成呢?

---------------------------------------
有时候程序down了, 但是core文件却没有生成. 
core文件的生成跟你当前系统的环境设置有关系, 可以用下面的语句设置一下, 然后再运行程序便生成了core文件.
ulimit -c unlimited
gdb a.out core

----------------------------------------
8. gdb加载内核模块符号信息:
add-symbol-file ADDR

例:

root@ubuntu:/home/hjj/software/uxfs_now/kern# cat debug
set remotebaud 115200
target remote /dev/ttyS1
add-symbol-file uxfs.ko 0xe0886000 -s .exit.text 0xe0888404

-------------------------------------------------
附录:gdb  常用调试命令
-------------------------------------------------
(gdb) l :(字母l)列出源码
(gdb) b n :在第n行处设置断点
(gdb) b func:在函数func()的入口处设置断点

(gdb) 条件断点:条件可以是任何合法的c 表达式。 例如 b n if val1==val2

          当已经设置了断点,可以用condition 命令对断点号添加条件, 例: condition 2 val1==val2 , 注意,没有if 单词

          当对变量的改变更感兴趣时,可以用watch 命令

 (gdb) info break: 查看断点信息
(gdb) r:运行程序
(gdb) n:单步执行
(gdb) s:单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的
(gdb) c:继续运行
(gdb) p 变量 :打印变量的值     也能够修改变量的值(用 = 赋值) // 打印寄存器值。 p $eax

(gdb) x/nfu 显示内存  // n为个数,f 为格式,u为每单元长度
(gdb) bt:查看函数堆栈
(gdb) finish:退出函数

(gdb) display 每次中断或单步都显示你关心的变量

(gdb)undisplay <编号>
(gdb) shell 命令行:执行shell命令行
(gdb) set args 参数:指定运行时的参数
(gdb) show args:查看设置好的参数
(gdb)info program: 来查看程序的是否在运行,进程号,被暂停的原因。 // 打印寄存器数组, info reg,  简写 i reg
(gdb)clear 行号n:清除第n行的断点
(gdb)delete 断点号n:删除第n个断点
(gdb)disable 断点号n:暂停第n个断点
(gdb)enable 断点号n:开启第n个断点


----------------------------------------
gdb 条件调试
----------------------------------------
“break ... if cond" 命令
例: b fun() if i==20

ignore bnum count
watch var    // 此时监测var的变化

----------------------------------------
gdb 多线程调试
----------------------------------------
info threads
thread ID 来切换
set scheduler-locking off|on|step 估计实际使用过多线程调试的人都可以发现,
在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,
怎么只让被调试程序执行呢?通过这个命令就可以实现这个需求。
off 不锁定任何线程,也就是所有线程都执行,这是默认值。 
on 只有当前被调试程序会执行。 
设置 on 之后, step 在单步的时候, 只有当前线程会执行。
next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)。

1.gdb有个很友好的调式界面,就是layout方式调试,可以让你边调试变查看源码,
但是layout方式有时候有点bug,不过基本上还可以使用,
可以用ctrl+x和ctrl+a 来切换。可能layout会造成控制台花屏,使用ctrl+L清屏。


----------------------------------------
 GDB堆栈跟踪的方法
----------------------------------------
程序“调用堆栈”是当前函数之前的所有已调用函数的列表(包括当前函数)。每个函数及其变量都被分配了一个“帧”,
最近调用的函数在 0 号帧中(“底部”帧)。要打印堆栈,发出命令 'bt'('backtrace' [回溯] 的缩写):
(gdb) bt
#0  0x80483ea in wib (no1=8, no2=8) at eg1.c:7
#1  0x8048435 in main (argc=1, argv=0xbffff9c4) at eg1.c:21
此结果显示了在 main() 的第 21 行中调用了函数 wib()(只要使用 'list 21' 就能证实这一点),而且 wib() 在 0 号帧中,
main() 在 1 号帧中。由于 wib() 在 0 号帧中,那么它就是执行程序时发生算术错误的函数。
实际上,发出 'info locals' 命令时,gdb 会打印出当前帧中的局部变量,缺省情况下,这个帧中的函数就是被中断的函数(0 号帧)。
可以使用命令 'frame' 打印当前帧。要查看 main 函数(在 1 号帧中)中的变量,可以发出 'frame 1' 切换到 1 号帧,
然后发出 'info locals' 命令:
(gdb) frame 1
#1  0x8048435 in main (argc=1, argv=0xbffff9c4) at eg1.c:21
21          result = wib(value, div);
(gdb) info locals
value = 8
div = 8
result = 4
i = 2
total = 6
   
此信息显示了在第三次执行 "for" 循环时(i 等于 2)发生了错误,此时 "value" 等于 "div"。
可以通过如上所示在 'frame' 命令中明确指定号码,或者使用 'up' 命令在堆栈中上移以及 'down' 命令在堆栈中下移来切换帧。
要获取有关帧的进一步信息,如它的地址和程序语言,可以使用命令 'info frame'。
gdb 堆栈命令可以在程序执行期间使用,也可以在 core 文件中使用,因此对于复杂的程序,可以在程序运行时跟踪它是如何转到函数的。
 查看栈信息
当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的。 当你的程序调用了一个函数,
函数的地址,函数参数,函数内的局部变量都会被压入“栈”(Stack)中。你可以用GDB命令来查看当前的栈中的信息。
下面是一些查看函数调用栈信息的GDB命令:
    Backtrace,bt 打印当前的函数调用栈的所有信息。如:        
        (gdb) bt
        #0 func (n=250) at tst.c:6
        #1 0x08048524 in main (argc=1, argv=0xbffff674) at tst.c:30
        #2 0x400409ed in __libc_start_main () from /lib/libc.so.6        
从上可以看出函数的调用栈信息:__libc_start_main --> main() --> func()    
    backtrace , bt n是一个正整数,表示只打印栈顶上n层的栈信息。
    backtrace <-n> ,bt <-n> -n表一个负整数,表示只打印栈底下n层的栈信息。        
如果你要查看某一层的信息,你需要在切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。
frame ,f n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。
   up          表示向栈的上面移动n层,可以不打n,表示向上移动一层。
down 表示向栈的下面移动n层,可以不打n,表示向下移动一层。
上面的命令,都会打印出移动到的栈层的信息。如果你不想让其打出信息。你可以使用这三个命令:
     select-frame 对应于 frame 命令。
      up-silently 对应于 up 命令。
      down-silently 对应于 down 命令。
查看当前栈层的信息,你可以用以下GDB命令:
frame 或 f       会打印出这些信息:栈的层编号,当前的函数名,函数参数值,函数所在文件及行号,函数执行到的语句。
info frame,info f 这个命令会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内内地址。比如:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等。如:
       (gdb) info f
       Stack level 0, frame at 0xbffff5d4:
         eip = 0x804845d in func (tst.c:6); saved eip 0x8048524
         called by frame at 0xbffff60c
         source language c.
         Arglist at 0xbffff5d4, args: n=250
         Locals at 0xbffff5d4, Previous frame's sp is 0x0
         Saved registers:
         ebp at 0xbffff5d4, eip at 0xbffff5d8              
     info args      打印出当前函数的参数名及其值。     
     info locals     打印出当前函数中所有局部变量及其值。        
     info catch      打印出当前的函数中的异常处理信息。


gdb 跟踪远程调试命令交互过程
"set debug remote 1" 将显示gdb 远程调试的过程。

gdb 内存断点设置。
rwatch, watch, awatch 分别代表读,写,读写内存断点,用的是硬件断点。

------------------------------------------------------------------
gdbtui  gdb 图形化接口。方便调试
启动gdb, 按ctrl-x cta-a 也可进入tui 模式
------------------------------------------------------------------

 help layout
     layout src
     layout asm
     layout split

 help winheight
     winheight src +5
     winheight src -4

help focus
    focus cmd
    focus src
    focus next
简记为
    fs next
    fs src
    fs cmd

--------------------------------------------------------------------------------
help info
Generic command for showing things about the program being debugged.
关于被调试程序的一些信息
help show
Generic command for showing things about the debugger
关于debugger状态的一些信息
--------------------------------------------------------------------------------

常用命令:

set args

file

source

set logging overwrite on
set logging on
set print pretty
show logging
set pagination off   // 不要出现 Type to continue 的提示信息 
info functions
info variables

list

list [函数名称]


与调试控制相关的命令

  • continue    继续运行程序直到下一个 断点(类似于VS里的F5)
  • next        逐过程步进,不会进入子函数(类似VS里的F10)
  • step        逐语句步进,会进入子函数(类似VS里的F11)
  • until        运行至当前语句块结束
  • finish  运行至函数结束并跳出,并打印函数的返回值(类似VS的Shift+F11)

s : step in

fin: step out, 跳出函数

until 行号。 可用于跳出循环,加快了调试速度。


----------------------------------------
gdb 调试跟踪多进程程序
----------------------------------------
gdb只能跟踪一个进程(默认是跟踪父进程),而不能同时跟踪多个进程,
可以设置gdb跟踪父进程还是子进程, 命令如下:
set follow-fork-mode parent 跟踪父进程, 默认
set follow-fork-mode child  跟踪子进程

你可能感兴趣的:(gdb)