Unhandled Exception
Unhandled Exception

Reputation: 1513

gdb How to dump out the data of a structure?

Using a very simple sample that uses an int pointer to point to a structure with longs. Granted it isn't the preferred method but it is being done to mimic other code. The objective is to view the data in the register before the free call.

This is the code.

#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);
 }

Using the following gdb version to step through the code.

Using > gdb GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-94.el7

Gdb is used to start the application then disassembled to acquire the line of code for the free command.

(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.

Using the specific line of code, a break point is set on free.

(gdb) break *0x00000000004006d4

Continue until the code breaks on the free command.

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

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

Display the available registers.

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

I assume that rdi register will house the data that is being freed at address 0x602010. To be sure all the data will be visible the examine command is executed to display 80 bytes of data starting 16 bytes prior.

(gdb) x/80d 0x602000
0x602000:       0       0       0       0       0       0       0       0
0x602008:       33      0       0       0       0       0       0       0
0x602010:       111     0       0       0       0       0       0       0
0x602018:       -34     0       0       0       0       0       0       0
0x602020:       77      1       0       0       0       0       0       0
0x602028:       -31     15      2       0       0       0       0       0
0x602030:       0       0       0       0       0       0       0       0
0x602038:       0       0       0       0       0       0       0       0
0x602040:       0       0       0       0       0       0       0       0
0x602048:       0       0       0       0       0       0       0       0
(gdb)

From the above, 111 is visible but not 222, or 333.

How can all the data (111,222,333) be viewed prior to the free command being executed?

Upvotes: 0

Views: 845

Answers (1)

Employed Russian
Employed Russian

Reputation: 213516

From the above, 111 is visible but not 222, or 333.

There is no way that you could have observed this output while stopped before the CALL free instruction. We clearly see that values 0x6f == 111, 0xde == 222 and 0x14d == 333 are loaded at offset 0, 8 and 16 from $RAX:

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

and then $RAX is copied to $RDI just before the call to free:

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

Here is the expected output (that I observe with your program):

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

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

But if you execute nexti (to step over the call to free), then the values can be overwritten (you can't expect the contents of now freed memory to be anything in particular).

After nexti, I observe:

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

but it could just as easily be 111 0 0 0 0 0 that you observed.

Upvotes: 2

Related Questions