gdb 内存操作

watch 某个地址的读写操作  

watch *(int*)0xaaaaa

使用gdb调试程序,读写操作是很普遍的事情。其中,读操作包括:

  • 读取某个变量的值
  • 读取某个内存地址里的内容
  • 读取某个寄存器的值

对应地,写操作包括:

  • 修改某个变量的值
  • 修改某个内存地址里的内容
  • 修改某个寄存器的值

本文将首先简单介绍一下读操作,然后重点介绍一下写操作。

1. 读操作

  • 读取某个变量的值: p <var>
  • 读取某个内存地址里的内容: x /NFU <memaddr>
  • 读取某个寄存器的值: info r <register>

2. 写操作

先上个例子// foo.c

 1 #include <stdio.h>
 2 
 3 typedef enum {false, true} bool;
 4 
 5 static bool g_verbose = 0;
 6 
 7 static void
 8 dump(int a[], int n)
 9 {
10         for (int i = 0; i < n; i++)
11                 printf("%-2d ", a[i]);
12         printf("\n");
13 }
14 
15 int main(int argc, char *argv[])
16 {
17         int a[] = {0x1, 0x2, 0x3, 0x4, 0x5};
18         int n = sizeof(a) / sizeof(int);
19 
20         if (g_verbose) {
21                 printf("Now dump a[] ...\n");
22                 dump(a, n);
23         }
24 
25         int m = 0;
26         for (int i = 0; i < n; i++)
27                 m += a[i];
28 
29         return m;
30 }

在上面的代码中,第5行我们定义了一个变量g_verbose, 其值为false。现在,我们将通过gdb在第20行将其修改为true,给出三种方法,贯穿了修改变量的值,修改内存地址内容和修改寄存器。

2.1 修改某个变量的值

set var <name> = <value>

e.g.

$ gcc -g -Wall -std=c99 -o foo foo.c

$ gdb foo
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
...<snip>.......................................................................
(gdb) l main
11                      printf("%-2d ", a[i]);
12              printf("\n");
13      }
14
15      int main(int argc, char *argv[])
16      {
17              int a[] = {0x1, 0x2, 0x3, 0x4, 0x5};
18              int n = sizeof(a) / sizeof(int);
19
20              if (g_verbose) {
(gdb) b 20
Breakpoint 1 at 0x8048500: file foo.c, line 20.
(gdb) r
Starting program: /tmp/foo

Breakpoint 1, main (argc=1, argv=0xbffff054) at foo.c:20
20              if (g_verbose) {
(gdb) p g_verbose
$1 = false
(gdb) set var g_verbose = true
(gdb) p g_verbose
$2 = true
(gdb) c
Continuing.
Now dump a[] ...
1  2  3  4  5
[Inferior 1 (process 5544) exited with code 017]
(gdb)

 

2.2 修改某个内存地址里的内容

set *(unsigned char      *)<memaddr> = <value>  ; write 1 byte
set *(unsigned short     *)<memaddr> = <value>  ; write 2 bytes
set *(unsigned int       *)<memaddr> = <value>  ; write 4 bytes
set *(unsigned long long *)<memaddr> = <value>  ; write 8 bytes

or

set *(char      *)<memaddr> = <value>           ; write 1 byte
set *(short     *)<memaddr> = <value>           ; write 2 bytes
set *(int       *)<memaddr> = <value>           ; write 4 bytes
set *(long long *)<memaddr> = <value>           ; write 8 bytes

e.g.

$ gdb foo
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
...<snip>.......................................................................
(gdb) l main
11                      printf("%-2d ", a[i]);
12              printf("\n");
13      }
14
15      int main(int argc, char *argv[])
16      {
17              int a[] = {0x1, 0x2, 0x3, 0x4, 0x5};
18              int n = sizeof(a) / sizeof(int);
19
20              if (g_verbose) {
(gdb)
21                      printf("Now dump a[] ...\n");
22                      dump(a, n);
23              }
24
25              int m = 0;
26              for (int i = 0; i < n; i++)
27                      m += a[i];
28
29              return m;
30      }
(gdb) b 20
Breakpoint 1 at 0x8048500: file foo.c, line 20.
(gdb) r
Starting program: /tmp/foo

Breakpoint 1, main (argc=1, argv=0xbffff054) at foo.c:20
20              if (g_verbose) {
(gdb) #
(gdb)
(gdb) p &g_verbose
$1 = (bool *) 0x804a02c <g_verbose>
(gdb) #
(gdb)
(gdb) x /x 0x804a02c
0x804a02c <g_verbose>:  0x00000000
(gdb) #
(gdb)
(gdb) set *(unsigned int *)0x804a02c = 0x1
(gdb) #
(gdb)
(gdb) x /x 0x804a02c
0x804a02c <g_verbose>:  0x00000001
(gdb) #
(gdb)
(gdb) c
Continuing.
Now dump a[] ...
1  2  3  4  5
[Inferior 1 (process 5731) exited with code 017]
(gdb) q

2.3 修改某个寄存器的值

set $<register> = <value>
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GDB是一种功能强大的调试工具,可用于定位和调试程序中的内存泄漏问题。以下是使用GDB进行内存泄漏定位的常见步骤。 1. 编译程序时,加入-g选项以启用调试信息。例如,使用以下命令编译程序: `gcc -g -o your_program your_code.c` 2. 运行程序时,添加--leak-check选项以启用内存泄漏检查。例如,使用以下命令运行程序: `valgrind --leak-check=yes ./your_program` 3. 当程序运行结束后,Valgrind将会报告内存泄漏情况。在报告中,它将列出所有的内存泄漏,并显示泄漏的内存地址、大小、泄漏的位置等信息。 4. 在报告中找到泄漏的内存地址,这将帮助我们找到泄漏发生的位置。 5. 使用GDB调试器定位到发生泄漏的位置,可以通过以下命令启动GDB调试器: `gdb ./your_program` 6. 在GDB中,使用以下命令设置断点,将程序暂停在泄漏的位置: `break function_name` 或者 `break file_name:line_number` 7. 运行程序并让其在断点处停下来,使用以下命令: `run` 8. 当程序停在断点处时,可以使用GDB的各种命令来检查程序状态,例如使用`print`命令查看变量的值,使用`backtrace`命令查看调用堆栈等。 9. 通过分析程序状态和内存使用情况,可以找出引起内存泄漏的原因。可能是未正确释放动态分配的内存,或是不正确的内存管理操作。 10. 根据定位到的问题,修改代码以解决内存泄漏问题。 11. 重新编译和运行经过修改的程序,确保问题已经解决。 使用GDB进行内存泄漏定位需要对GDB的使用有一定的了解。这只是一种常见的使用方式,具体的操作和命令可能会因情况而有所不同。因此,针对具体问题使用GDB调试工具时,还应结合具体情况进行相应的操作和分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值