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