gdb如何转储出结构的数据?

时间:2018-10-15 15:49:09

标签: gdb

使用一个非常简单的示例,该示例使用int指针指向具有long的结构。当然,它不是首选方法,但是可以模仿其他代码。目的是在免费调用之前查看寄存器中的数据。

这是代码。

* def client_id = clientId

使用以下gdb版本逐步执行代码。

使用> gdb GNU gdb(GDB)红帽企业版Linux 7.6.1-94.el7

Gdb用于启动应用程序,然后反汇编以获得free命令的代码行。

#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>

typedef struct
        {
        unsigned long   x;
        unsigned long   y;
        unsigned long   z;
        }
        myStruct;

int main () {
   int  *p_Struct = (int *)0;

   int size = sizeof (myStruct);

   printf("Size of (bytes)...\n");
   printf("     myStruct : %d\n", sizeof (myStruct));

   p_Struct = ( int*) malloc(size);
   memset((int *)p_Struct, 0, size);

   ((myStruct *)p_Struct)->x = 111;
   ((myStruct *)p_Struct)->y = 222;
   ((myStruct *)p_Struct)->z = 333;

   free(p_Struct);
   return(0);
 }

使用特定的代码行,可以自由设置断点。

(gdb) disassemble main
Dump of assembler code for function main:
   0x000000000040064d <+0>:     push   %rbp
   0x000000000040064e <+1>:     mov    %rsp,%rbp
   0x0000000000400651 <+4>:     sub    $0x10,%rsp
=> 0x0000000000400655 <+8>:     movq   $0x0,-0x8(%rbp)
   0x000000000040065d <+16>:    movl   $0x18,-0xc(%rbp)
   0x0000000000400664 <+23>:    mov    $0x400770,%edi
   0x0000000000400669 <+28>:    callq  0x400500 <puts@plt>
   0x000000000040066e <+33>:    mov    $0x18,%esi
   0x0000000000400673 <+38>:    mov    $0x400783,%edi
   0x0000000000400678 <+43>:    mov    $0x0,%eax
   0x000000000040067d <+48>:    callq  0x400510 <printf@plt>
   0x0000000000400682 <+53>:    mov    -0xc(%rbp),%eax
   0x0000000000400685 <+56>:    cltq
   0x0000000000400687 <+58>:    mov    %rax,%rdi
   0x000000000040068a <+61>:    callq  0x400550 <malloc@plt>
   0x000000000040068f <+66>:    mov    %rax,-0x8(%rbp)
   0x0000000000400693 <+70>:    mov    -0xc(%rbp),%eax
   0x0000000000400696 <+73>:    movslq %eax,%rdx
   0x0000000000400699 <+76>:    mov    -0x8(%rbp),%rax
   0x000000000040069d <+80>:    mov    $0x0,%esi
   0x00000000004006a2 <+85>:    mov    %rax,%rdi
   0x00000000004006a5 <+88>:    callq  0x400520 <memset@plt>
   0x00000000004006aa <+93>:    mov    -0x8(%rbp),%rax
   0x00000000004006ae <+97>:    movq   $0x6f,(%rax)
   0x00000000004006b5 <+104>:   mov    -0x8(%rbp),%rax
   0x00000000004006b9 <+108>:   movq   $0xde,0x8(%rax)
   0x00000000004006c1 <+116>:   mov    -0x8(%rbp),%rax
   0x00000000004006c5 <+120>:   movq   $0x14d,0x10(%rax)
   0x00000000004006cd <+128>:   mov    -0x8(%rbp),%rax
   0x00000000004006d1 <+132>:   mov    %rax,%rdi
   0x00000000004006d4 <+135>:   callq  0x4004f0 <free@plt>
   0x00000000004006d9 <+140>:   mov    $0x0,%eax
   0x00000000004006de <+145>:   leaveq
   0x00000000004006df <+146>:   retq
End of assembler dump.

继续,直到代码在free命令上中断。

(gdb) break *0x00000000004006d4

显示可用的寄存器。

(gdb) continue
Continuing.
Size of (bytes)...
     myStruct : 24

Breakpoint 2, 0x00000000004006d4 in main () at freeQuestion.c:28
28         free(p_Struct);

我假设rdi寄存器将容纳正在地址0x602010释放的数据。为了确保所有数据都可见,将执行检查命令以显示80字节的数据(从16字节开始)。

(gdb) info reg
rax            0x602010 6299664
rbx            0x0      0
rcx            0x602010 6299664
rdx            0x18     24
rsi            0x0      0
rdi            0x602010 6299664
rbp            0x7fffffffc160   0x7fffffffc160
rsp            0x7fffffffc150   0x7fffffffc150
r8             0x602000 6299648
r9             0x18     24
r10            0x7fffffffbed0   140737488338640
r11            0x2aaaaad56700   46912498919168
r12            0x400560 4195680
r13            0x7fffffffc240   140737488339520
r14            0x0      0
r15            0x0      0
rip            0x4006d4 0x4006d4 <main+135>
eflags         0x283    [ CF SF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb)

从上面可以看到111,但看不到222或333。

如何在执行free命令之前查看所有数据(111,222,333)?

1 个答案:

答案 0 :(得分:1)

  

从上面可以看到111,但看不到222或333。

您无法在CALL free指令停止之前观察到此输出,这是 no 的方式。我们清楚地看到,值0x6f == 1110xde == 2220x14d == 333在距$RAX的偏移量0、8和16处加载:

0x00000000004006ae <+97>:    movq   $0x6f,(%rax)
0x00000000004006b9 <+108>:   movq   $0xde,0x8(%rax)
0x00000000004006c5 <+120>:   movq   $0x14d,0x10(%rax)

,然后在调用$RAX之前将$RDI复制到free

0x00000000004006d1 <+132>:   mov    %rax,%rdi
0x00000000004006d4 <+135>:   callq  0x4004f0 <free@plt>

这是预期的输出(我在您的程序中观察到):

(gdb) p/x $rdi
$1 = 0x602420

(gdb) x/6d $rdi
0x602420:   111 0   222 0
0x602430:   333 0

但是,如果您执行nexti(以逐步完成对free的调用),则这些值可以被覆盖(您无法期望现在free d存储器的内容尤其是任何东西

nexti之后,我观察到:

(gdb) x/6d 0x602420
0x602420:   0   0   222 0
0x602430:   333 0

但是您观察到的111 0 0 0 0 0也很容易。