首页 > 其他分享 >GDB-3——GDB实用调试技巧

GDB-3——GDB实用调试技巧

时间:2022-11-08 12:02:17浏览次数:30  
标签:11 break gdb 实用 GDB 添加 100 断点 调试

 

1. 将 print 显示的字符串或字符数组显示完整

当我们使用 print 命令打印一个字符串或者字符数组时,如果该字符串太长,print 命令默认显示不全的,我们可以通过在 gdb 中输入 set print element 0 设置一下,这样再次使用 print 命令就能完整地显示该变量所有字符串了。

 

2. 让被gdb调试的程序接收信号

有两种方法:
(1) 在 gdb 中使用 signal 函数手动给我们的程序发送信号,这里就是 signal SIGINT。
(2) 改变 gdb 信号处理的设置,通过 handle SIGINT nostop print 告诉 gdb 在接收到 SIGINT 时不要停止、并把该信号传递给调试目标程序。(注:实测不行)

还有些程序如下配置,但是实验时都不好使。下面两个实测也没啥效果:
handle SIGPIPE noprint pass nostop
handle SIGUSR1 print pass nostop


3. 明明函数存在,添加断点时却无效

有时候,一个函数明明存在,并且我们的程序也存在调试符号,我们使用 break functionName 添加断点时,gdb 却提示:"Make breakpoint pending on future shared library load? y/n" 即使我们输入 y,添加的断点可能也不会被正确的触发。此时我们就需要改变添加断点的策略,使用该函数所在的代码文件和行号这种方式添加断点就能添加同样效果的断点。


4. 条件断点

实际调试中,我们一般会用到三种断点:普通断点、条件断点和硬件断点。
(1) 硬件断点又叫数据断点,这样的断点其实就是用 watch 命令添加的部分断点(为什么是部分,而不是全部,因为 watch 添加的断点,有部分是软中断实现的,不属于硬件断点)。硬件断点触发时机是当监视的内存地址或者变量值发送变化时,就会触发。
(2) 普通断点就是我们添加的断点除去条件断点和硬件断点以外的断点。
(3) 条件断点就是满足某个条件才会触发的断点。

这里重点来介绍一下条件断点,添加条件断点的命令之一是:break <lineNo> if <condition> 其中lineNo 是程序触发断点后需要停的位置,condition 是断点触发的条件。另一种方法是先添加一个普通断点,然后使用 condition <断点编号> <断点触发条件> 这样的格式来添加。

示例:

 1 #include <stdio.h>
 2 
 3 void do_something_func(int i)
 4 {
 5     printf("i*100 = %d\n", i*100);
 6 }
 7 
 8 int main()
 9 {
10     for(int i = 0; i < 10000; i++) {
11         do_something_func(i);
12     }
13     return 0;
14 }

调试记录:

//方法1:
lvm:~/origin_tmp/3.gdb$ gcc break_if.c -g -o break_if
lvm:~/origin_tmp/3.gdb$ gdb break_if
...
(gdb) b 11 if i==5 //直接设置为条件断点
Breakpoint 1 at 0x40055c: file break_if.c, line 11.
(gdb) r
Starting program: /origin_tmp/3.gdb/break_if 
i*100 = 0
i*100 = 100
i*100 = 200
i*100 = 300
i*100 = 400

Breakpoint 1, main () at break_if.c:11
11                      do_something_func(i);

//方法2:
(gdb) b 11
Breakpoint 1 at 0x40055c: file break_if.c, line 11.
(gdb) r
Starting program: /origin_tmp/3.gdb/break_if 

Breakpoint 1, main () at break_if.c:11
11                      do_something_func(i);
(gdb) condition 1 i==5  //将普通断点改为条件断点
(gdb) c
Continuing.
i*100 = 0
i*100 = 100
i*100 = 200
i*100 = 300
i*100 = 400

Breakpoint 1, main () at break_if.c:11
11                      do_something_func(i);

 

5. 自定义gdb调试命令

有些场景下,需要根据自己的程序情况,自定义一些可以在调试时输出我们程序特定信息的命令。这个在 gdb 中只要在 Linux 用户根目录下(root 用户就是 /root 目录,非 root 用户,是/home/用户名 这个目录)自定义一个 .gdbinit 文件,让后将命令定义在这个文件中。在 linux 系统中这是一个隐藏文件,需要使用 ls -a 命令查看,若是想在Window下修改,可以将前面的.去掉以便能显示出来,改过后再将.加上。

举个例子:
apache server的源码下载地址:http://httpd.apache.org/),在源码根目录下有个文件叫 .gdbinit,这个就是 apache server 自定义的 gdb 命令:

# gdb macros which may be useful for folks using gdb to debug
# apache. Delete it if it bothers you.
define dump_table
    set $t = (apr_table_entry_t *)((apr_array_header_t *)$arg0)->elts
    set $n = ((apr_array_header_t *)$arg0)->nelts
    set $i = 0
    while $i < $n
        if $t[$i].val == (void *)0L
            printf "[%u] '%s'=>NULL\n", $i, $t[$i].key
        else
            printf "[%u] '%s'='%s' [%p]\n", $i, $t[$i].key, $t[$i].val, $t[$i].val
        end
        set $i = $i + 1
    end
end
# 省略部分代码
# Set sane defaults for common signals:
handle SIGPIPE noprint pass nostop
handle SIGUSR1 print pass nostop

参考上面例子实现自己的gdb命令:

define judge_val
    set $val = $arg0
    if $val < 5
        printf "less than 5\n"
    else
        printf "bigger than 5\n"
    end
end

使用上面条件断点的程序进行实验:

lvm:~/origin_tmp/3.gdb$ gdb break_if
...
(gdb) b 11
Breakpoint 1 at 0x40055c: file break_if.c, line 11.
(gdb) r
Starting program: /origin_tmp/3.gdb/break_if 

Breakpoint 1, main () at break_if.c:11
11                      do_something_func(i);
(gdb) judge_val i
less than 5  //自己的命令执行成功了
(gdb) c
...
(gdb) judge_val i //当i大于5时也是执行成功的
bigger than 5

 

标签:11,break,gdb,实用,GDB,添加,100,断点,调试
From: https://www.cnblogs.com/hellokitty2/p/16869205.html

相关文章

  • GDB-4——Android设备中使用GDB调试程序的例子
     一、一个简单的例子1.实验Demo(1)Android.mkLOCAL_PATH:=$(callmy-dir)include$(CLEAR_VARS)LOCAL_SRC_FILES:=mytest.cLOCAL_MODULE:=mytestLOCAL_C_F......
  • GDB-2——GDB调试多线程
     一、简介前一博文实际上已经介绍了多线程的调试方法,这节专门进行一下总结。 二、调试多线程1.使用gdb将程序跑起来,然后按Ctrl+C将程序中断下来,使用infoth......
  • busybox-date.c调试
    注释代码/*vi:setsw=4ts=4:*//**Minidateimplementationforbusybox**byMatthewGrant<[email protected]>**iso-formathandlingaddedbyRobert......
  • 为可执行程序(sys/exe)生成公有调试符号
      自Win10推出以来,Windows的更新频度变为每年2次(赶上隔壁Ubuntu的更新节奏了)。每次更新,MS都会提出一堆新要求。对于2018年RS4的更新,MS要求所有提交到WU(WindowsUpdat......
  • 对<源码级调试WDF框架>一文进行补充
    MS曾在他的Github站点上提出过​​《源码级调试WDF框架》​​的方法,文中提到通过.srcfix命令使windbg源码服务器路径指向MS的源码服务器。这样当调试到wdf框架代码时,windbg......
  • 2种内核级反用户态调试方法
    0.前言  很久前写过一些应用层的反调试的文章,这类反调试方法的好处是易于实现,但缺点是很容易被绕过----保护因此失效。我们的危机公关手段是:将反调试功能放到内核中用驱......
  • windbg调试服务程序
       相比通过输出日志来跟踪程序运行状态,我更倾向使用调试器。虽然我早知调试服务很麻烦,总不会比调试驱动还麻烦吧?基于这个想法,我尝试了在win7上使用windbg调试服务并记......
  • 调试遗漏IoStartNextPacket引起的阻塞
       前面​​driververifier检测驱动死锁 ​​一文中本想检测一下驱动中潜在的死锁来解决驱动无响应的bug,然而并没有实质性的进展。后来通过一系列的调试终于找到了......
  • windbg调试窗口过程WindowProc(winxp 32bit)
      ollydbg在调试窗口程序方面做得很便捷,虽然windbg在这方面不如od,但通过命令的组合也能达到类似的效果。我借winxp的calc.exe为例来谈谈如何用windbg调试窗口过程。 ......
  • 编写windbg调试器扩展 入门篇1
      我博客的左侧专栏曾经转过windows下编写调试器的一系列文章,这类文章是从零打造调试器,而这篇文章是介绍如何为windbg编写调试器扩展命令。0.前言  windbg的命令......