gdb查看,修改CPU中寄存器的值
- 打印寄存器的值
debug的时候,如果想查看register中的内容,可以使用"i register"命令,i是info命令的缩写,表示列出寄存器的信息。
(gdb) i registers
rax 0x7ffff7dd9f60 140737351884640
rbx 0x0 0
rcx 0x0 0
rdx 0x7fffffffe608 140737488348680
rsi 0x7fffffffe5f8 140737488348664
rdi 0x1 1
rbp 0x7fffffffe510 0x7fffffffe510
rsp 0x7fffffffe4c0 0x7fffffffe4c0
r8 0x7ffff7dd8300 140737351877376
r9 0x7ffff7deb9e0 140737351956960
r10 0x7fffffffe360 140737488348000
r11 0x7ffff7a68be0 140737348275168
r12 0x4003e0 4195296
r13 0x7fffffffe5f0 140737488348656
r14 0x0 0
r15 0x0 0
rip 0x4004cd 0x4004cd <main+9>
eflags 0x206 [ PF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
以上输出不包括浮点寄存器和向量寄存器的内容。使用“i all-registers”命令,可以输出所有寄存器的内容:
(gdb) i all-registers
rax 0x7ffff7dd9f60 140737351884640
rbx 0x0 0
rcx 0x0 0
rdx 0x7fffffffe608 140737488348680
rsi 0x7fffffffe5f8 140737488348664
rdi 0x1 1
rbp 0x7fffffffe510 0x7fffffffe510
rsp 0x7fffffffe4c0 0x7fffffffe4c0
r8 0x7ffff7dd8300 140737351877376
r9 0x7ffff7deb9e0 140737351956960
r10 0x7fffffffe360 140737488348000
r11 0x7ffff7a68be0 140737348275168
r12 0x4003e0 4195296
r13 0x7fffffffe5f0 140737488348656
r14 0x0 0
r15 0x0 0
rip 0x4004cd 0x4004cd <main+9>
eflags 0x206 [ PF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
st0 0 (raw 0x00000000000000000000)
st1 0 (raw 0x00000000000000000000)
st2 0 (raw 0x00000000000000000000)
st3 0 (raw 0x00000000000000000000)
st4 0 (raw 0x00000000000000000000)
st5 0 (raw 0x00000000000000000000)
st6 0 (raw 0x00000000000000000000)
st7 0 (raw 0x00000000000000000000)
......
要打印单个寄存器的值,可以使用“i registers regname”或者“p $regname”,例如:
(gdb) i registers eax
eax 0xf7dd9f60 -136470688
(gdb) p $eax
$1 = -136470688
- 修改PC寄存器的值
例子
#include <stdio.h>
int main(void)
{
int a =0;
a++;
a++;
printf("%d\n", a);
return 0;
}
PC寄存器会存储程序下一条要执行的指令,通过修改这个寄存器的值,可以达到改变程序执行流程的目的。上面的程序会输出“a=2”,下面介绍一下如何通过修改PC寄存器的值,改变程序执行流程。
4 int a =0;
(gdb) disassemble main
Dump of assembler code for function main:
0x08050921 <main+0>: push %ebp
0x08050922 <main+1>: mov %esp,%ebp
0x08050924 <main+3>: sub $0x8,%esp
0x08050927 <main+6>: and $0xfffffff0,%esp
0x0805092a <main+9>: mov $0x0,%eax
0x0805092f <main+14>: add $0xf,%eax
0x08050932 <main+17>: add $0xf,%eax
0x08050935 <main+20>: shr $0x4,%eax
0x08050938 <main+23>: shl $0x4,%eax
0x0805093b <main+26>: sub %eax,%esp
0x0805093d <main+28>: movl $0x0,-0x4(%ebp)
0x08050944 <main+35>: lea -0x4(%ebp),%eax
0x08050947 <main+38>: incl (%eax)
0x08050949 <main+40>: lea -0x4(%ebp),%eax
0x0805094c <main+43>: incl (%eax)
0x0805094e <main+45>: sub $0x8,%esp
0x08050951 <main+48>: pushl -0x4(%ebp)
0x08050954 <main+51>: push $0x80509b4
0x08050959 <main+56>: call 0x80507cc <printf@plt>
0x0805095e <main+61>: add $0x10,%esp
0x08050961 <main+64>: mov $0x0,%eax
0x08050966 <main+69>: leave
0x08050967 <main+70>: ret
End of assembler dump.
(gdb) info line 6
Line 6 of "a.c" starts at address 0x8050944 <main+35> and ends at 0x8050949 <main+40>.
(gdb) info line 7
Line 7 of "a.c" starts at address 0x8050949 <main+40> and ends at 0x805094e <main+45>.
通过“info line 6”和“info line 7”命令可以知道两条“a++;”语句的汇编指令起始地址分别是0x8050944和0x8050949。
(gdb) n
6 a++;
(gdb) p $pc
$3 = (void (*)()) 0x8050944 <main+35>
(gdb) set var $pc=0x08050949
当程序要执行第一条“a++;”语句时,打印pc寄存器的值,看到pc寄存器的值为0x8050944,与“info line 6”命令得到的一致。接下来,把pc寄存器的值改为0x8050949,也就是通过“info line 7”命令得到的第二条“a++;”语句的起始地址。
(gdb) n
8 printf("a=%d\n", a);
(gdb)
a=1
9 return 0;
接下来执行,可以看到程序输出“a=1”,也就是跳过了第一条“a++;”语句。