gdb 调试高级命令

  • Post author:
  • Post category:其他




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




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

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

可以用source <cmd file> 在启动gdb 后运行gdb 命令文件

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


2. gdb 传递命令行 参数




a. run <args>




b. set args <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 <file name> -> 改变记录文件,默认记录文件是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 <MODULE_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 <addr> 显示内存  // n为个数,f 为格式,u为每单元长度

(gdb) bt:查看函数堆栈

(gdb) finish:退出函数

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



(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 <n>, bt <n> n是一个正整数,表示只打印栈顶上n层的栈信息。

backtrace <-n> ,bt <-n> -n表一个负整数,表示只打印栈底下n层的栈信息。

如果你要查看某一层的信息,你需要在切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。

frame <n>,f <n> n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。

up <n>         表示向栈的上面移动n层,可以不打n,表示向上移动一层。

down <n> 表示向栈的下面移动n层,可以不打n,表示向下移动一层。

上面的命令,都会打印出移动到的栈层的信息。如果你不想让其打出信息。你可以使用这三个命令:

select-frame <n> 对应于 frame 命令。

up-silently <n> 对应于 up 命令。

down-silently <n> 对应于 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 <return> to continue 的提示信息

info functions

info variables

list

list [函数名称]

与调试控制相关的命令


  • c

    ontinue    继续运行程序直到下一个

    断点

    (类似于VS里的F5)

  • n

    ext        逐过程步进,不会进入子函数(类似VS里的F10)

  • s

    tep        逐语句步进,会进入子函数(类似VS里的F11)

  • u

    ntil        运行至当前语句块结束

  • fin

    ish  运行至函数结束并跳出,并打印函数的返回值(类似VS的Shift+F11)


s : step in

fin: step out, 跳出函数

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

—————————————-

gdb 调试跟踪多进程程序

—————————————-

gdb只能跟踪一个进程(默认是跟踪父进程),而不能同时跟踪多个进程,

可以设置gdb跟踪父进程还是子进程, 命令如下:

set follow-fork-mode parent 跟踪父进程, 默认

set follow-fork-mode child  跟踪子进程