您的位置:首页 > 其它

利用gdb在汇编指令级调试C程序

2013-01-24 15:13 369 查看
关于GDB调试C程序常用命令与手段就不多说了,这里主要介绍一下如何对C程序做到汇编指令级别的调试。

首先是获取汇编代码,这可以通过disassemble命令或x命令或类似的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

[root@localhost test]# gdb ./a.out -q

(gdb) list

1 #include<stdio.h>

2 #include<malloc.h>

3

4 int callee(int a, int b, int c, int d, int e)

5 {

6 return 1;

7 }

8

9 int main(){

10 callee(1,2,3,4,5);

(gdb) disassemble main

Dump of assembler code for function main:

0x0000000000400463 <main+0>: push %rbp

0x0000000000400464 <main+1>: mov %rsp,%rbp

0x0000000000400467 <main+4>: mov $0x5,%r8d

0x000000000040046d <main+10>: mov $0x4,%ecx

0x0000000000400472 <main+15>: mov $0x3,%edx

0x0000000000400477 <main+20>: mov $0x2,%esi

0x000000000040047c <main+25>: mov $0x1,%edi

0x0000000000400481 <main+30>: callq 0x400448 <callee>

0x0000000000400486 <main+35>: mov $0x2,%eax

0x000000000040048b <main+40>: leaveq

0x000000000040048c <main+41>: retq

End of assembler dump.

(gdb) x/10i main

0x400463 <main>: push %rbp

0x400464 <main+1>: mov %rsp,%rbp

0x400467 <main+4>: mov $0x5,%r8d

0x40046d <main+10>: mov $0x4,%ecx

0x400472 <main+15>: mov $0x3,%edx

0x400477 <main+20>: mov $0x2,%esi

0x40047c <main+25>: mov $0x1,%edi

0x400481 <main+30>: callq 0x400448 <callee>

0x400486 <main+35>: mov $0x2,%eax

0x40048b <main+40>: leaveq

(gdb)

接着,利用display命令自动显示当前正要执行的汇编指令,display命令可以在每次程序暂停时自动打印指定变量的值。而我们要显示的汇编指令在ip寄存器内(当然,ip寄存器内存储的是机器码),我们可以看看(先得把程序执行起来):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

(gdb) b main

Breakpoint 1 at 0x400467: file t3.5.c, line 10.

(gdb) r

Starting program: /root/test/a.out

Breakpoint 1, main () at t3.5.c:10

10 callee(1,2,3,4,5);

(gdb) info reg

rax 0x3cd2153a60 261222644320

rbx 0x3cd101bbc0 261204589504

rcx 0x4004a0 4195488

rdx 0x7fffc5f6fa38 140736514685496

rsi 0x7fffc5f6fa28 140736514685480

rdi 0x1 1

rbp 0x7fffc5f6f940 0x7fffc5f6f940

rsp 0x7fffc5f6f940 0x7fffc5f6f940

r8 0x3cd21522d0 261222638288

r9 0x3cd0e0d620 261202433568

r10 0x0 0

r11 0x3cd1e1d8a0 261219276960

r12 0x0 0

r13 0x7fffc5f6fa20 140736514685472

r14 0x0 0

r15 0x0 0

rip 0x400467 0x400467 <main+4>

eflags 0x246 [ PF ZF IF ]

cs 0x33 51

ss 0x2b 43

ds 0x0 0

es 0x0 0

fs 0x0 0

gs 0x0 0

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 0x1f80 [ IM DM ZM OM UM PM ]

(gdb)

看汇编指令:

1
2
3
4
5

(gdb) p $rip

$2 = (void(*)()) 0x400467 <main+4>

(gdb) x/i $rip

0x400467 <main+4>: mov $0x5,%r8d

(gdb)

我们还可以利用一个名为pc的gdb内部变量:

1
2
3
4
5

(gdb) p $pc

$3 = (void(*)()) 0x400467 <main+4>

(gdb) x/i $pc

0x400467 <main+4>: mov $0x5,%r8d

(gdb)

结合display命令和寄存器或pc内部变量,我们做如下设置:

1
2
3
4

(gdb) display /i $pc

1: x/i $pc

0x400467 <main+4>: mov $0x5,%r8d

(gdb)

或同时显示多条汇编,比如3条:

1
2
3
4
5
6
7
8
9
10
11
12
13

(gdb) display /3i $pc

(gdb) b main

Breakpoint 1 at 0x400467: file t3.5.c, line 10.

(gdb) r

Starting program: /root/test/a.out

Breakpoint 1, main () at t3.5.c:10

10 callee(1,2,3,4,5);

1: x/3i $pc

0x400467 <main+4>: mov $0x5,%r8d

0x40046d <main+10>: mov $0x4,%ecx

0x400472 <main+15>: mov $0x3,%edx

(gdb)

接下来,利用ni(nexti)或si(stepi)命令进行汇编指令级的调试,如下所示可以看到参数是如何传递的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

(gdb) display /i $pc

1: x/i $pc

0x400467 <main+4>: mov $0x5,%r8d

(gdb) ni

0x000000000040046d 10 callee(1,2,3,4,5);

1: x/i $pc

0x40046d <main+10>: mov $0x4,%ecx

(gdb) ni

0x0000000000400472 10 callee(1,2,3,4,5);

1: x/i $pc

0x400472 <main+15>: mov $0x3,%edx

(gdb) ni

0x0000000000400477 10 callee(1,2,3,4,5);

1: x/i $pc

0x400477 <main+20>: mov $0x2,%esi

(gdb) ni

0x000000000040047c 10 callee(1,2,3,4,5);

1: x/i $pc

0x40047c <main+25>: mov $0x1,%edi

(gdb)

更简单直接的方法是利用layout显示汇编代码窗口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

(gdb) help layout

Change the layout of windows.

Usage: layout prev | next | <layout_name>

Layout names are:

src : Displays source and command windows.

asm : Displays disassembly and command windows.

split : Displays source, disassembly and command windows.

regs : Displays registerwindow. If existing layout

is source/command or assembly/command, the

registerwindow is displayed. If the

source/assembly/command (split) is displayed,

theregisterwindow is displayed with

the window that has current logical focus.

(gdb) layout asm lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk

x0x400463 <main> push %rbp x

x0x400464 <main+1> mov %rsp,%rbp x

x0x400467 <main+4> mov $0x5,%r8d x

x0x40046d <main+10> mov $0x4,%ecx x

x0x400472 <main+15> mov $0x3,%edx x

x0x400477 <main+20> mov $0x2,%esi x

x0x40047c <main+25> mov $0x1,%edi x

x0x400481 <main+30> callq 0x400448 <callee> x

x0x400486 <main+35> mov $0x2,%eax x

x0x40048b <main+40> leaveq x

x0x40048c <main+41> retq x

x0x40048d nop x

x0x40048e nop x

x0x40048f nop x

x0x400490 <__libc_csu_fini> repz retq x

x0x400492 nopl 0x0(%rax) x

x0x400499 nopl 0x0(%rax) x

x0x4004a0 <__libc_csu_init> mov %r12,-0x20(%rsp) x

x0x4004a5 <__libc_csu_init+5> mov %r13,-0x18(%rsp) x

x0x4004aa <__libc_csu_init+10> lea 0x2001bb(%rip),%r12 # 0x60066c x

x0x4004b1 <__libc_csu_init+17> mov %r14,-0x10(%rsp) x

x0x4004b6 <__libc_csu_init+22> mov %r15,-0x8(%rsp) x

x0x4004bb <__libc_csu_init+27> mov %rsi,%r14 x

x0x4004be <__libc_csu_init+30> mov %rbx,-0x30(%rsp) x

x0x4004c3 <__libc_csu_init+35> mov %rbp,-0x28(%rsp) x

x0x4004c8 <__libc_csu_init+40> sub $0x38,%rsp x

mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

exec No process In: Line: ?? PC: 0x0

(gdb)

如果是7.0版本以上的gdb,那么还有一个方法显示汇编:

另外,7.0版本以上gdb的disas命令可以携带/m参数,让汇编与c源码同时显示:

转载请保留地址:http://lenky.info/2012/05/30/%e5%88%a9%e7%94%a8gdb%e5%9c%a8%e6%b1%87%e7%bc%96%e6%8c%87%e4%bb%a4%e7%ba%a7%e8%b0%83%e8%af%95c%e7%a8%8b%e5%ba%8f/http://lenky.info/?p=1694

备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。

法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以Email或书面等方式告知,本站将及时删除相关内容或链接。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: