0
votes

I am working in the GDB debugger with the aim of constructing a model of a call stack for my executable using information from the assembly instructions and the source code, as well as knowledge of the argument input. I know that the location of data on the stack is most typically referenced relative to either the $EBP or $ESP registers for the x86 architecture (i386). For example, from the source code

if argc != 2
{
    //do something
}

Despite being fairly novice in assembly, I can deduce that

<main+9>    cmp    DWORD PTR  [ebp+0x8],0x2

constitutes a portion of the assembly instructions intended to compare the static value 2 to argc, as compiled from the source snippet given above. Furthermore, I understand that argc is located 8 bytes (two 32-bit words -- as this is a 32-bit VM) above the $EBP register value pushed onto the stack and forming the basis of stack. Unfortunately, I am confused as to what the origin/baseline for the relative reference is. Is it relative to the top address or the bottom address of the $EBP "slot" in memory. Asked another way, when I type

print $ebp

in GDB and get

(void *) 0xbaffe020

as a reply, is that hex address located at the top of the 4 byte wide $EBP "slot" or the bottom? This matters, because when I find the distance between two addresses, I need to know whether I need to add an additional 4 bytes.

-- A note on terminology: I often label a 32-bit (4 byte) word as a "slot" in memory because I find it more intuitive with my mental model of flat memory [essentially a large array of fixed width addressable "slots"/bands] --

Also, how can I reconcile this relative addressing scheme with DWARF syntax? Unfortunately typing

info address VARIABLE

into GDB yields relative addressing in the DWARF syntax, like so

DW_OP_breg4 24

I know that breg4 references $EBP and fbreg references $ESP and that positive numbers are offset higher in memory address while negative numbers are offset lower in memory address but that is it. What is the relative basis of DWARF syntax? Can I use another scheme in GDB and avoid DWARF altogether? Thank you so much.

1
A better minimal reproducible example would be a function like void foo(int arg) { int val = arg; } compiled with optimization disabled, so the asm for the entire function (including stack manipulation) would be tiny.Peter Cordes

1 Answers

3
votes

After making a traditional stack-frame with push ebp / mov ebp, esp on function entry, EBP points at the bottom of the saved-caller-EBP value.

Thus EBP points 4 bytes below the return address, and 8 bytes below the first stack arg (which is why you find argc at [ebp+8].

In general, addresses point at the bottom / start of the bytes of an object. A pointer to an object is the same as a pointer to the first byte of an object. (x86 being little-endian, that's the least-significant byte.)