Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

x86_64 calling conventions and stack frames

I am trying to make sense out of the executable code that GCC (4.4.3) is generating for an x86_64 machine running under Ubuntu Linux. In particular, I don't understand how the code keeps track of stack frames. In the old days, in 32-bit code, I was accustomed to seeing this "prologue" in just about every function:

push %ebp
movl %esp, %ebp

Then, at the end of the function, there would come an "epilogue," either

sub $xx, %esp   # Where xx is a number based on GCC's accounting.
pop %ebp
ret

or simply

leave
ret

which accomplishes the same thing:

  • Set the Stack Pointer to the top of the current frame, just below the return address
  • Restore the old Frame Pointer value.

In 64-bit code, as I see it through an objdump disassembly, many functions do not follow this convention--they do not push %rbp and then save %rsp to %rbp, How does a debugger like GDB build a backtrace?

My real goal here to is to try to figure out a reasonable address to consider as the top (highest address) of the user stack when execution reaches the start of an arbitrary function further into the program, where perhaps the Stack Pointer has moved down. For the "top," for instance, the original address of argv would be ideal--but I have no access to it from an arbitrary function that main calls. I had at first thought that I could use the old backtrace method: chasing saved Frame Pointer values until the value saved is 0--then, the next one after that can count as the highest practical value. (This is not the same as getting the address of argv, but it will do--say, to find out the Stack Pointer value at _start or whatever _start calls [e.g., __libc_start_main].) Now, I don't know how to get the equivalent address in 64-bit code.

Thanks.

like image 808
Amittai Aviram Avatar asked Dec 24 '11 15:12

Amittai Aviram


People also ask

What is a stack frame x86?

The idea behind a stack frame is that each subroutine can act independently of its location on the stack, and each subroutine can act as if it is the top of the stack. When a function is called, a new stack frame is created at the current esp location. A stack frame acts like a partition on the stack.

What are different calling conventions?

Microsoft x64 calling convention That means RCX, RDX, R8, R9 for integer, struct or pointer arguments (in that order), and XMM0, XMM1, XMM2, XMM3 for floating point arguments. Additional arguments are pushed onto the stack (right to left). Integer return values (similar to x86) are returned in RAX if 64 bits or less.

When calling a function using the x86 64 C language calling convention the stack pointer RSP must be aligned in what way?

As mentioned above, before executing call the stack pointer must be aligned to a multiple of 16 + 8, so if you are calling a function which has any stack-based arguments, you should add up the total size of these arguments and then, if necessary, adjust the rsp (by subtraction) so that it is aligned.

What is the purpose of calling convention?

A calling convention governs how functions on a particular architecture and operating system interact. This includes rules about includes how function arguments are placed, where return values go, what registers functions may use, how they may allocate local variables, and so forth.


1 Answers

I think the difference is that omitting the frame pointer is simply more encouraged in amd64. A footnote on page 16 of the abi says

The conventional use of %rbp as a frame pointer for the stack frame may be avoided by using %rsp (the stack pointer) to index into the stack frame. This technique saves two instructions in the prologue and epilogue and makes one additional general-purpose register (%rbp) available.

I don't know what GDB does. I assume that when compiled with -g, objects have magic debugging information that allows GDB to reconstruct what it needs. I don't think I've tried GDB on a 64-bit machine without debugging info.

like image 65
Adrian Ratnapala Avatar answered Sep 23 '22 00:09

Adrian Ratnapala