Reading symbols from /root/workspace/test...done.
(gdb) start
Temporary breakpoint 1 at 0x40053c: file test.c, line 5.
Starting program: /root/workspace/./test
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe638) at test.c:5
5 char p1[] = "Sam";
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb) n
6 char *p2 = "Bob";
(gdb) n
8 printf("p1 is %s, p2 is %s\n", p1, p2);
(gdb) set main::p1="ivan1001"
Too many array elements
(gdb) set main::p1="Jil"
(gdb) set main::p2="Bill"
(gdb) n
p1 is Jil, p2 is Bill
9 return 0;
可以看到
p1
和
p2
字符串都发生了变化,也可以通过访问内存地址的方法来改变字符串的值:
# gdb -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) start
Temporary breakpoint 1 at 0x40053c: file test.c, line 5.
Starting program: /root/workspace/./test
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe638) at test.c:5
5 char p1[] = "Sam";
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb) n
6 char *p2 = "Bob";
(gdb) n
8 printf("p1 is %s, p2 is %s\n", p1, p2);
(gdb) p p1
$1 = "Sam"
(gdb) p &p1
$2 = (char (*)[4]) 0x7fffffffe540
(gdb) set p1[0]='C'
(gdb) p p1
$3 = "Cam"
(gdb) set {char [4]} 0x7fffffffe540 = "Ace"
(gdb) n
p1 is Ace, p2 is Bob
9 return 0;
在改变字符串的值时候,一定要注意内存越界的问题。
1.2 设置变量的值
1) 示例程序
#include <stdio.h>
int func()
int i = 2;
return i;
int main(int argc, char *argv[])
int a = 0;
a = func();
printf("%d\n", a);
return 0;
2) 调试技巧
在GDB中,可以用set var variable=expr命令设置变量的值,以上面代码为例:
# gcc -g -c -o test.o test.c
# gcc -o test test.o
# gdb -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) b func
Breakpoint 1 at 0x400531: file test.c, line 5.
(gdb) b test.c:15
Breakpoint 2 at 0x400560: file test.c, line 15.
(gdb) r
Starting program: /root/workspace/./test
Breakpoint 1, func () at test.c:5
5 int i = 2;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb) set var i=8
(gdb) p i
$1 = 8
(gdb) c
Continuing.
Breakpoint 2, main (argc=1, argv=0x7fffffffe638) at test.c:15
15 printf("%d\n", a);
(gdb) n
17 return 0;
(gdb)
# gdb -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) b func
Breakpoint 1 at 0x400531: file test.c, line 5.
(gdb) r
Starting program: /root/workspace/./test
Breakpoint 1, func () at test.c:5
5 int i = 2;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb) n
7 return i;
(gdb) p &i
$1 = (int *) 0x7fffffffe51c
(gdb) set {int}0x7fffffffe51c=8
(gdb) p i
$2 = 8
(gdb) c
Continuing.
[Inferior 1 (process 82849) exited normally]
可以看到i的值被修改成为8
另外寄存器也可以作为变量,因此同样可以修改寄存器的值:
# gdb -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) b func
Breakpoint 1 at 0x400531: file test.c, line 5.
(gdb) r
Starting program: /root/workspace/./test
Breakpoint 1, func () at test.c:5
5 int i = 2;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb) n
7 return i;
(gdb) si
8 }
(gdb) disassemble func
Dump of assembler code for function func:
0x000000000040052d <+0>: push %rbp
0x000000000040052e <+1>: mov %rsp,%rbp
0x0000000000400531 <+4>: movl $0x2,-0x4(%rbp)
0x0000000000400538 <+11>: mov -0x4(%rbp),%eax
=> 0x000000000040053b <+14>: pop %rbp
0x000000000040053c <+15>: retq
End of assembler dump.
(gdb) set var $eax=100
(gdb) c
Continuing.
[Inferior 1 (process 82909) exited normally]
# gdb -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) start
Temporary breakpoint 1 at 0x400559: file test.c, line 12.
Starting program: /root/workspace/./test
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe638) at test.c:12
12 int i = 1;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb) n
14 func(i--);
(gdb) n
15 func(i--);
(gdb) n
16 func(i--);
(gdb) n
error
18 return 0x0;
(gdb) b test.c:16
Breakpoint 2 at 0x400580: file test.c, line 16.
(gdb) jump 16
Continuing at 0x400580.
Breakpoint 2, main (argc=1, argv=0x7fffffffe638) at test.c:16
16 func(i--);
(gdb) s
func (x=-2) at test.c:6
6 if(x < 0)
(gdb) p x
$1 = -2
(gdb) n
7 puts("error");
#include <stdio.h>
#include <stdlib.h>
void drawing(int n)
if(n != 0)
puts("Try again?\nAll you need is a dollar, and a dream");
puts("You win $3000!");
int main(int argc, char *argv[])
int n;
srand(time(NULL));
n = rand() % 10;
printf("Your number is %d\n", n);
drawing(n);
return 0x0;
2) 调试技巧
这个例子程序可能不太好,只是可以用来演示下断点命令的用法:
# gcc -g -c -o test.o test.c
# gcc -o test test.o
# gdb -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) b drawing
Breakpoint 1 at 0x400658: file test.c, line 6.
(gdb) command 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>silent
>set var n=0
>continue
(gdb) r
Starting program: /root/workspace/./test
Your number is 1
You win $3000!
[Inferior 1 (process 89237) exited normally]
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb)
#include <stdio.h>
#include <stdlib.h>
void drawing(int n)
if(n != 0)
puts("Try again?\nAll you need is a dollar, and a dream");
puts("You win $3000!")
int main(int argc, char *argv[])
int n;
srand(time(NULL));
n = rand() % 10;
printf("Your number is %d\n", n);
drawing(n);
return 0x0;
# gcc -g -c -o test.o test.c
# gcc -o test test.o
# gdb --write -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) show write
Writing into executable and core files is on.
(gdb)
也可以在GDB中使用命令设置并重新加载程序:
# gdb -q
(gdb) set write on
(gdb) file ./test
Reading symbols from /root/workspace/test...done.
接下来查看反汇编:
(gdb) disassemble /mr drawing
Dump of assembler code for function drawing:
5 {
0x000000000040064d <+0>: 55 push %rbp
0x000000000040064e <+1>: 48 89 e5 mov %rsp,%rbp
0x0000000000400651 <+4>: 48 83 ec 10 sub $0x10,%rsp
0x0000000000400655 <+8>: 89 7d fc mov %edi,-0x4(%rbp)
6 if(n != 0)
0x0000000000400658 <+11>: 83 7d fc 00 cmpl $0x0,-0x4(%rbp)
0x000000000040065c <+15>: 74 0c je 0x40066a <drawing+29>
7 puts("Try again?\nAll you need is a dollar, and a dream");
0x000000000040065e <+17>: bf 90 07 40 00 mov $0x400790,%edi
0x0000000000400663 <+22>: e8 88 fe ff ff callq 0x4004f0 <puts@plt>
0x0000000000400668 <+27>: eb 0a jmp 0x400674 <drawing+39>
8 else
9 puts("You win $3000!");
0x000000000040066a <+29>: bf c1 07 40 00 mov $0x4007c1,%edi
0x000000000040066f <+34>: e8 7c fe ff ff callq 0x4004f0 <puts@plt>
10 }
0x0000000000400674 <+39>: c9 leaveq
0x0000000000400675 <+40>: c3 retq
End of assembler dump.
修改二进制代码(注意大小端和指令长度):
(gdb) set var *(short *)0x000000000040065c=0x0ceb
(gdb) disassemble /mr drawing
Dump of assembler code for function drawing:
5 {
0x000000000040064d <+0>: 55 push %rbp
0x000000000040064e <+1>: 48 89 e5 mov %rsp,%rbp
0x0000000000400651 <+4>: 48 83 ec 10 sub $0x10,%rsp
0x0000000000400655 <+8>: 89 7d fc mov %edi,-0x4(%rbp)
6 if(n != 0)
0x0000000000400658 <+11>: 83 7d fc 00 cmpl $0x0,-0x4(%rbp)
0x000000000040065c <+15>: eb 0c jmp 0x40066a <drawing+29>
7 puts("Try again?\nAll you need is a dollar, and a dream");
0x000000000040065e <+17>: bf 90 07 40 00 mov $0x400790,%edi
0x0000000000400663 <+22>: e8 88 fe ff ff callq 0x4004f0 <puts@plt>
0x0000000000400668 <+27>: eb 0a jmp 0x400674 <drawing+39>
8 else
9 puts("You win $3000!");
0x000000000040066a <+29>: bf c1 07 40 00 mov $0x4007c1,%edi
0x000000000040066f <+34>: e8 7c fe ff ff callq 0x4004f0 <puts@plt>
10 }
0x0000000000400674 <+39>: c9 leaveq
0x0000000000400675 <+40>: c3 retq
End of assembler dump.
(gdb)
# gdb `find srcdir -type d -printf '-d %p '` -q prog
# gdb -q `find ../P2P_SDK/ -type d -printf '-d %p '` ./test
Reading symbols from /root/workspace/test...done.
(gdb) show directories
Source directories searched: /root/workspace/../P2P_SDK/headers:/root/workspace/../P2P_SDK/doc:/root/workspace/../P2P_SDK/linux-example/signal_server ...
(gdb)
使用info source可以查看当前源码信息,其中也包含编译信息:
(gdb) info source
Current source file is ../../net/tools/quic/quic_simple_client_bin.cc
Compilation directory is .
Source language is c++.
Producer is unknown.
Compiled with DWARF 2 debugging format.
Does not include preprocessor macro info.
使用pwd可以看到当前目录:
(gdb) pwd
Working directory /root/chromium/src.
2.2 示例1: 设置源文件查找路径
1) 程序示例
#include <stdio.h>
#include <time.h>
int main(int argc, char *argv[])
time_t now = time(NULL);
struct tm local = {0};
struct tm gmt = {0};
localtime_r(&now, &local);
gmtime_r(&now, &gmt);
return 0;
# gdb -q ./test
Reading symbols from /root/workspace/test...done.
(gdb) start
Temporary breakpoint 1 at 0x4005e5: file test.c, line 6.
Starting program: /root/workspace/./test
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe638) at test.c:6
6 test.c: No such file or directory.
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
(gdb) set substitute /root/workspace /root/workspace/src/moved
(gdb) n
7 struct tm local = {0};
(gdb) n
8 struct tm gmt = {0};
(gdb) n
10 localtime_r(&now, &local);
(gdb)