Strogenstroff
Strogenstroff

Reputation: 47

How to see variables stored on the stack with GDB

I'm trying to figure out what is stored at a certain place on the stack with GDB. I have a statement:

cmpl $0x176,-0x10(%ebp)

In this function I'm comparing 0x176 to the -0x10(%ebp) and I am wondering if there is a way to see what is stored at -0x10(%ebp).

Upvotes: 1

Views: 1212

Answers (1)

Employed Russian
Employed Russian

Reputation: 213375

I am wondering if there is a way to see what is stored at -0x10(%ebp).

Assuming you have compiled with debug info, info locals will tell you about all the local variables in current frame. After that, print (char*)&a_local - (char*)$ebp will tell you the offset from start of a_local to %ebp, and you can usually find out what local is close to 0x176.

Also, if your locals have initializers, you can do info line NN to figure out which assembly instruction range corresponds to initialization of a given local, then disas ADDR0,ADDR1 to see the disassembly, and again understand which local is located at what offset.

Another alternative is to readelf -w a.out, and look for entries like this:

int foo(int x) { int a = x; int b = x + 1; return b - a; }

<1><25>: Abbrev Number: 2 (DW_TAG_subprogram)
 <26>   DW_AT_external    : 1        
 <27>   DW_AT_name        : foo      
 <2b>   DW_AT_decl_file   : 1        
 <2c>   DW_AT_decl_line   : 1        
 <2d>   DW_AT_prototyped  : 1        
 <2e>   DW_AT_type        : <0x67>   
 <32>   DW_AT_low_pc      : 0x0      
 <36>   DW_AT_high_pc     : 0x23     
 <3a>   DW_AT_frame_base  : 0x0      (location list)
 <3e>   DW_AT_sibling     : <0x67>   
<2><42>: Abbrev Number: 3 (DW_TAG_formal_parameter)
 <43>   DW_AT_name        : x        
 <45>   DW_AT_decl_file   : 1        
 <46>   DW_AT_decl_line   : 1        
 <47>   DW_AT_type        : <0x67>   
 <4b>   DW_AT_location    : 2 byte block: 91 0       (DW_OP_fbreg: 0)
<2><4e>: Abbrev Number: 4 (DW_TAG_variable)
 <4f>   DW_AT_name        : a        
 <51>   DW_AT_decl_file   : 1        
 <52>   DW_AT_decl_line   : 1        
 <53>   DW_AT_type        : <0x67>   
 <57>   DW_AT_location    : 2 byte block: 91 74      (DW_OP_fbreg: -12)
<2><5a>: Abbrev Number: 4 (DW_TAG_variable)
 <5b>   DW_AT_name        : b        
 <5d>   DW_AT_decl_file   : 1        
 <5e>   DW_AT_decl_line   : 1        
 <5f>   DW_AT_type        : <0x67>   
 <63>   DW_AT_location    : 2 byte block: 91 70      (DW_OP_fbreg: -16)

This tells you that x is stored at fbreg+0, a at fbreg-12, and b at fbreg-16. Now you just need to examine location list to figure out how to derive fbreg from %ebp. The list for above code looks like this:

Contents of the .debug_loc section:

Offset   Begin    End      Expression
00000000 00000000 00000001 (DW_OP_breg4: 4)
00000000 00000001 00000003 (DW_OP_breg4: 8)
00000000 00000003 00000023 (DW_OP_breg5: 8)
00000000 <End of list>

So for most of the body, fbreg is %ebp+8, which means that a is at %ebp-4. Disassembly confirms:

00000000 <foo>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 10                sub    $0x10,%esp
   6:   8b 45 08                mov    0x8(%ebp),%eax  # 'x' => %eax
   9:   89 45 fc                mov    %eax,-0x4(%ebp) # '%eax' => 'a'

...

Upvotes: 4

Related Questions