gdb汇编调试c程序

关于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,那么还有一个方法显示汇编:

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

[root@localhost gdb-7.4.1]# ./gdb/gdb -version | grep "(GDB)"

GNU gdb (GDB) 7.4.1

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

GNU gdb (GDB) 7.4.1

Copyright (C) 2012 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is freesoftware: you are freeto change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.  Type "show copying"

and"show warranty"  for  details.

This GDB was configured as "x86_64-unknown-linux-gnu".

For bug reporting instructions, please see:

<http://www.gnu.org/software/gdb/bugs/>...

Reading symbols from /root/test/a.out...done.

(gdb) set disassemble-next-line on

(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);

=> 0x0000000000400467 <main+4>:    41 b8 05 00 00 00   mov    $0x5,%r8d

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

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

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

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

   0x0000000000400481 <main+30>:  e8 c2 ff ff ff  callq  0x400448 <callee>

(gdb) ni

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

   0x0000000000400467 <main+4>:   41 b8 05 00 00 00   mov    $0x5,%r8d

=> 0x000000000040046d <main+10>:   b9 04 00 00 00  mov    $0x4,%ecx

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

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

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

   0x0000000000400481 <main+30>:  e8 c2 ff ff ff  callq  0x400448 <callee>

(gdb)

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

(gdb) disas /m main

Dump of assembler code forfunction main:

9  intmain(){

   0x0000000000400463 <+0>:   push   %rbp

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

 

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

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

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

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

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

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

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

 

11     return2;

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

 

12  }

   0x000000000040048b <+40>:  leaveq

   0x000000000040048c <+41>:  retq  

 

End of assembler dump.

(gdb)

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值