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>