1 使用汇编调试
1.1 disassemble
简写为disas,查看当前函数的汇编指令,并显示下一条要执行的执令,如下:
(gdb) disassemble
Dump of assembler code for function main.main:
0x00000000004872c0 <+0>: mov %fs:0xfffffffffffffff8,%rcx
0x00000000004872c9 <+9>: cmp 0x10(%rcx),%rsp
0x00000000004872cd <+13>: jbe 0x487311 <main.main+81>
0x00000000004872cf <+15>: sub $0x28,%rsp
0x00000000004872d3 <+19>: mov %rbp,0x20(%rsp)
0x00000000004872d8 <+24>: lea 0x20(%rsp),%rbp
0x00000000004872dd <+29>: movl $0x10,(%rsp)
0x00000000004872e4 <+36>: lea 0x38b6d(%rip),%rax # 0x4bfe58
0x00000000004872eb <+43>: mov %rax,0x8(%rsp)
0x00000000004872f0 <+48>: movq $0x64,0x10(%rsp)
0x00000000004872f9 <+57>: movq $0xc8,0x18(%rsp)
0x0000000000487302 <+66>: callq 0x4310b0 <runtime.newproc>
=> 0x0000000000487307 <+71>: mov 0x20(%rsp),%rbp
0x000000000048730c <+76>: add $0x28,%rsp
0x0000000000487310 <+80>: retq
0x0000000000487311 <+81>: callq 0x44f300 <runtime.morestack_noctxt>
0x0000000000487316 <+86>: jmp 0x4872c0 <main.main>
=>指示下一条要执行的指令。
1.2 nexti
简写为ni,执行当前执令,并指向下一条指令。示例如下:
@(指行前)
0x0000000000487302 <+66>: callq 0x4310b0 <runtime.newproc>
=> 0x0000000000487307 <+71>: mov 0x20(%rsp),%rbp
0x000000000048730c <+76>: add $0x28,%rsp
@(指行后)
0x0000000000487302 <+66>: callq 0x4310b0 <runtime.newproc>
0x0000000000487307 <+71>: mov 0x20(%rsp),%rbp
=> 0x000000000048730c <+76>: add $0x28,%rsp
1.3 stepi
简写为si,调转到call调用的函数。示例如下:
(gdb) disas
Dump of assembler code for function main.main:
...
0x00000000004872f9 <+57>: movq $0xc8,0x18(%rsp)
=> 0x0000000000487302 <+66>: callq 0x4310b0 <runtime.newproc>
0x0000000000487307 <+71>: mov 0x20(%rsp),%rbp
...
(gdb) si
runtime.newproc (siz=16, fn=<optimized out>) at /usr/local/go/src/runtime/proc.go:3239
3239 func newproc(siz int32, fn *funcval) {
(gdb) disas
Dump of assembler code for function runtime.newproc:
=> 0x00000000004310b0 <+0>: sub $0x40,%rsp
0x00000000004310b4 <+4>: mov %rbp,0x38(%rsp)
0x00000000004310b9 <+9>: lea 0x38(%rsp),%rbp
0x00000000004310be <+14>: nop
0x00000000004310bf <+15>: mov %fs:0xfffffffffffffff8,%rax
1.4 finish
跳出函数,能过si跳到一个函数后,可通过finish立即调出。完整示例如下:
(gdb) disas
Dump of assembler code for function main.main:
...
0x00000000004872f9 <+57>: movq $0xc8,0x18(%rsp)
=> 0x0000000000487302 <+66>: callq 0x4310b0 <runtime.newproc>
0x0000000000487307 <+71>: mov 0x20(%rsp),%rbp
...
(gdb) si
runtime.newproc (siz=16, fn=<optimized out>) at /usr/local/go/src/runtime/proc.go:3239
3239 func newproc(siz int32, fn *funcval) {
(gdb) ni
0x00000000004310b4 3239 func newproc(siz int32, fn *funcval) {
(gdb) ni
0x00000000004310b9 3239 func newproc(siz int32, fn *funcval) {
(gdb) ni
0x00000000004310be 3239 func newproc(siz int32, fn *funcval) {
(gdb) disas
Dump of assembler code for function runtime.newproc:
0x00000000004310b0 <+0>: sub $0x40,%rsp
0x00000000004310b4 <+4>: mov %rbp,0x38(%rsp)
0x00000000004310b9 <+9>: lea 0x38(%rsp),%rbp
=> 0x00000000004310be <+14>: nop
0x00000000004310bf <+15>: mov %fs:0xfffffffffffffff8,%rax
(gdb) finish
Run till exit from #0 0x00000000004310be in runtime.newproc (siz=16, fn=<optimized out>) at /usr/local/go/src/runtime/proc.go:3239
main.main () at /home/sandydu/program/golang/gotest/gotest.go:12
12 }
(gdb) disas
Dump of assembler code for function main.main:
...
0x0000000000487302 <+66>: callq 0x4310b0 <runtime.newproc>
=> 0x0000000000487307 <+71>: mov 0x20(%rsp),%rbp
0x000000000048730c <+76>: add $0x28,%rsp
...
End of assembler dump.
2 查看地址的值
p
(gdb) disassemble
Dump of assembler code for function main.main:
...
0x00000000004872d8 <+24>: lea 0x20(%rsp),%rbp
0x00000000004872dd <+29>: movl $0x10,(%rsp)
0x00000000004872e4 <+36>: lea 0x38b6d(%rip),%rax # 0x4bfe58
0x00000000004872eb <+43>: mov %rax,0x8(%rsp)
...
2.1 x
x
(gdb) x 0x4bfe58
0x4bfe58: 0x00487200
表示地址0x4bfe58的值为0x00487200。
3 查看寄存器的值
3.1 查看所有寄存器的值
info all-registers命令可查看所有寄存器的值,示例如下:
(gdb) info all-registers
rax 0xc000000180 824633721216
rbx 0x5585c0 5604800
rcx 0x5585c0 5604800
rdx 0x1 1
rsi 0x81 129
rdi 0xc000088148 824634278216
rbp 0xc000084f88 0xc000084f88
rsp 0xc000084f68 0xc000084f68
r8 0x0 0
r9 0x0 0
r10 0x0 0
r11 0x202 514
r12 0x8 8
r13 0xff 255
r14 0x4ce0b4 5038260
r15 0x39 57
rip 0x487307 0x487307 <main.main+71>
eflags 0x206 [ PF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x63 99
gs 0x0 0
st0-7 0 (raw 0x00000000000000000000)
fctrl 0x37f 895
fstat 0x0 0
ftag 0xffff 65535
fiseg 0x0 0
fioff 0x0 0
foseg 0x0 0
fooff 0x0 0
fop 0x0 0
mxcsr 0x1fa0 [ PE IM DM ZM OM UM PM ]
ymm0-15 ...
3.2 查看常用寄存器的值
info registers*命令可以查看常用寄存器的值,示例如下:
rax 0xc000000180 824633721216
rbx 0x5585c0 5604800
rcx 0x5585c0 5604800
rdx 0x1 1
rsi 0x81 129
rdi 0xc000088148 824634278216
rbp 0xc000084f88 0xc000084f88
rsp 0xc000084f68 0xc000084f68
r8 0x0 0
r9 0x0 0
r10 0x0 0
r11 0x202 514
r12 0x8 8
r13 0xff 255
r14 0x4ce0b4 5038260
r15 0x39 57
rip 0x487307 0x487307 <main.main+71>
eflags 0x206 [ PF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x63 99
gs 0x0 0
3.3 查看某个寄存器的值
p $reg命令可以查看某个寄存器的值,示例如下:
(gdb) p/x $rax
$8 = 0xc000000180
(gdb) p/x $ymm1
$9 = {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 <repeats 32 times>}, v16_int16 = {
0x0 <repeats 16 times>}, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {
0x00000000000000000000000000000000, 0x00000000000000000000000000000000}}
(gdb) p/x $st0
$10 = 0x0
(gdb) p/x $r8
$11 = 0x0