gdb深入学习手册

1.4 log

如果你想把GDB命令输出到一个文件有,有几种方法控制

set logging on
set logging off
set logging file <filename>
set logging overwrite [on|off]     #默认会追加到logfile里
set logging redirect [on|off]        #默认GDB输出会在terminal和logfile里显示,用redirect让它只在logfile里显示
show logging

可以用下面命令得到相应行的地址:

(gdb) i line gdbprog.cc:14
Line 14 of "gdbprog.cc" starts at address 0x4007d9 <InitArrays(int*)+17> and ends at 0x4007f7 <InitArrays(int*)+47>.

或者

(gdb) disas /m InitArrays
Dump of assembler code for function InitArrays(int*):
8    void InitArrays(int* array)
  0x00000000004007c8 <+0>:    push  %rbp
  0x00000000004007c9 <+1>:    mov    %rsp,%rbp
  0x00000000004007cc <+4>:    mov    %rdi,-0x18(%rbp)

9    {
10    
11    
12        for(int i = 0;i < 10;i++)
  0x00000000004007d0 <+8>:    movl  $0x0,-0x4(%rbp)
  0x00000000004007d7 <+15>:    jmp    0x40080a <InitArrays(int*)+66>
  0x0000000000400807 <+63>:    incl  -0x4(%rbp)
  0x000000000040080a <+66>:    cmpl  $0x9,-0x4(%rbp)
  0x000000000040080e <+70>:    jle    0x4007d9 <InitArrays(int*)+17>

13        {
14            ptrArray[i] = array + i;
  0x00000000004007d9 <+17>:    mov    -0x4(%rbp),%ecx
  0x00000000004007dc <+20>:    mov    -0x4(%rbp),%eax
  0x00000000004007df <+23>:    cltq  
  0x00000000004007e1 <+25>:    shl    $0x2,%rax
  0x00000000004007e5 <+29>:    mov    %rax,%rdx
  0x00000000004007e8 <+32>:    add    -0x18(%rbp),%rdx
  0x00000000004007ec <+36>:    movslq %ecx,%rax
  0x00000000004007ef <+39>:    mov    %rdx,0x6013e0(,%rax,8)

15            iArray[i] = i;
  0x00000000004007f7 <+47>:    mov    -0x4(%rbp),%eax
  0x00000000004007fa <+50>:    movslq %eax,%rdx
  0x00000000004007fd <+53>:    mov    -0x4(%rbp),%eax
  0x0000000000400800 <+56>:    mov    %eax,0x6013a0(,%rdx,4)

16        }
17    }
  0x0000000000400810 <+72>:    leaveq 
  0x0000000000400811 <+73>:    retq  

End of assembler dump.

4.2.Pending breakpoints

如果试图将断点设在位于还未加载的shared library代码内,那么就会显示类似下面warning

Make breakpoint pending on future shared library load? (y or [n])

但它可能永远不会工作,如果是下列情况:

  • shared library不包含任何debugging symbols (被用‘strip’命令移除掉)
  • GDB无法检测到library被加载 (比如,在android上使用GDB 6.x)
  • 你输入的是一个错误文件名或函数名

所以可以用下面几个命令来做调试

  • info sharedlibrary : 目前加载的shared library
  • info sources: 被GDB识别的源文件
  • info breakpoints : 创建的断点和它们的状态

4.3. 条件断点

大约有以下几种形式

break main if argc > 1
break 180 if (string == NULL && i < 0)
break test.c:34 if (x & y) == 1
break myfunc if i % (j+3) != 0
break 44 if strlen(mystring) == 0
b 10 if ((int)$gdb_strcmp(a,"chinaunix") == 0)
b 10 if ((int)aa.find("dd",0) == 0)

经常犯的一个错误就是 在if和后面的之间没放空格
另外注意条件表达式的返回值类型是int

当设置了断点后, 后面可以使用conditionignore来修改这个断点条件

4.4.condition

condition <break_list> (condition)

比如

cond 3 (i==4)

上面命令把breakpoint 3的条件修改成(i==4)

4.5. ignore

ignore <break_list> count

上面命令表示break_list指定的断点将被忽略count
比如现在i=0, 设置i>4为条件,那么忽略3次后,它停在i=8, 忽略了i=5, 6, 7

4.6. commands

commands <break_list>

当断点被触发时,运行相应的命令
可以用info breakpoints来查看相应断点上附着的命令

(gdb) i b
Num    Type          Disp Enb Address            What
3      breakpoint    keep y  0x00000000004007d9 in InitArrays(int*) at gdbprog.cc:14
    stop only if (i>4)
    breakpoint already hit 5 times
        silent
        printf "hz: i=%d\n",i
        c
7      breakpoint    keep y  0x0000000000400962 in main() at gdbprog.cc:51
    breakpoint already hit 1 time

一个断点上只允许附着一条命令,再次调用commands 3后会覆盖掉前面的命令
因此如果要删除相应的命令,只需用空的commands 3就行了

4.7. define

define可以录制宏,这些宏就像shell脚本一样,可以传入参数,依次是arg1, ...
可以把这些宏放在.gdbinit文件中
录制好宏后就可以在commands中使用
宏并不支持所有GDB命令,比如silent就不能用于宏中, 它会在运行时报错: Undefined commands: "silent"

(gdb) define printAndGo
Type commands for definition of "printAndGo".
End with a line saying just "end".
>printf "i=%d\n",$arg0
>cont
>end
(gdb) commands 3
Type commands for breakpoint(s) 3, one per line.
End with a line saying just "end".
>silent
>printAndGo
>end
(gdb) i b
Num    Type          Disp Enb Address            What
3      breakpoint    keep y  0x00000000004007d9 in InitArrays(int*) at gdbprog.cc:14
    stop only if (i>4)
        silent
        printAndGo i
7      breakpoint    keep y  0x0000000000400962 in main() at gdbprog.cc:51

如果要查看这些宏的定义,可以用show user来查看

(gdb) show user
User command "pbuf":
  set $i=0
  while ($i<strlen(netiring.supply))
    print netiring.supply[$i]
    set $i=$i+1
  end

User command "pobuf":
  set $i=0
  while ($i<strlen(netoring.consume))
    print netoring.consume[$i]
    set $i=$i+1
  end

4.8 tbreak

只生效一次临时断点

4.9 rbreak

在所有匹配regexp的函数名处都设置断点。它的regexpgrep相同

4.10 管理

clear localtion
location可以是function, file:func, linenum, file:linenum
delete [breakpoints] [range...]
[breakpoints]是可选项
disable|enable [breakpoints] [range...]
禁用|启用断点
enable [breakpoints] once range...
启用断点一次
enable [breakpoints] once range...
雇用断点cnt次
enable [breakpoints] delete range...
临时启用断点,一旦被激活就会把删除,和tbreak相似

五. 检查数据

pirnt
x
display
set
watch
catch
tracepoint

5.1 print

print接受表达式和计算它的值。任何该语言支持常值,变量和操作符都可以使用,像条件表达式,函数调用,类型转换,字符常量。GDB还支持数组常量,语法是{element, element...}, 比如print {1,2,3}.GDB支持还支持下面操作符

  • @

二进制操作符, 可以把momery当成数组。

int *array = (int*) malloc( len * sizeof(int));

可以使用下面命令来打印它的值:

(gdb) p *array@len
(gdb) p/x (short[2])0x12345678
$1 = {0x1234, 0x5678}

另外还可以自定义变量

set $i = 0
p dtab[$i++]->fv
RET
RET

上面的RET表示重复上面的表达式

  • ::

定义属于某个文件或函数的变量

  • {type} addr
    addr的变量按{type}类型解释

5.2 x

x/nfu addr
x addr
x

n, the repeat count
f, the display format (x, d, u, o, t, a, c, f, s, i)
u, the unit size (b: bytes, h: halfwords, w: words, g: giant words)

(gdb) x/5i $pc-6
  0x804837f <main+11>: mov    %esp,%ebp
  0x8048381 <main+13>: push  %ecx
  0x8048382 <main+14>: sub    $0x4,%esp
=> 0x8048385 <main+17>: movl  $0x8048460,(%esp)
  0x804838c <main+24>: call  0x80482d4 <puts@plt>

5.3display

如果你发现你经常要打印某个表达式,你可以把它加入到"automatic display list"

display expr
display/fmt expr
display/fmt addr
undisplay <dnums>
delete display dnums
disable display dnums
enable display dnums

5.4 set

可以使用set <var>=<expr>来修改程序中变量的值

5.5 数值历史(value Hisitory)

通过使用print命令显示的值会被自动保存在GDB的数值历史当中,该值会一直被保留直到符号表被重新读取或者放弃的时候(比如使用filesymbol-file),此时所有的值历史将会被丢弃。
在使用print打印值的时候,会将值编以整形的历史编号,然后可以使用&dollar;num的方式方便的引用,单个的&dollar;表示最近的数值历史,而&dollar;&dollar;表示第二新的数值历史,&dollar;&dollar;n表示倒数第n新的数值历史(所以可以推断&dollar;&dollar;0==&dollar;; &dollar;&dollar;1==&dollar;&dollar;;)。
  比如刚刚打印了一个指向结构体的指针,那么print $就可以显示结构体的信息,而命令print $.nex甚至可以显示结构体中的某些字段。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值