The Stack
Stack segment contains a stack, one entry/out, LIFO structure. On the x86 architecture, stacks grow downward, meaning that newer data will be allocated at addresses less than elements pushed onto the stack earlier. This stack normally called a stack frame (or a procedure activation record in java) when there are the boundaries pointed by EBP (Base Pointer) at the bottom and ESP (Stack Pointer) at the top of the stack. Each function call creates a new stack frame and “stacked down” onto the previous stack(s), each one keeps track of the call chain or sequence that is which routine called it and where to return to, once it’s done. Using a very simple C program skeleton, the following tries to figure out function calls and stack frames construction/destruction.
#include <stdio.h>
int a();
int b();
int c();
int a()
{
b();
c();
return 0;
}
int b()
{ return 0; }
int c()
{ return 0; }
int main()
{
a();
return 0;
}
By taking the stack area only, the following is what happen when the above program is run. At the end there should be equilibrium.
Stack frame and function call.
When a program begins execution in the function main(), stack frame is created, space is allocated on the stack for all variables declared within main(). Then, when main() calls a function, a(), new stack frame is created for the variables in a() at the top of the main() stack. Any parameters passed by main() to a() are stored on the stack. If a() were to call any additional functions such as b() and c(), new stack frames would be allocated at the new top of the stack. Notice that the order of the execution happened in the sequence. When c(), b() and a() return, storage for their local variables are de-allocated, the stack frames are destroyed and the top of the stack returns to the previous condition. The order of the execution is in the reverse. As can be seen, the memory allocated in the stack area is used and reused during program execution. It should be clear that memory allocated in this area will contain garbage values left over from previous usage. During the execution the stack frame may shrink and grow and after the function call completed, the return address will be used to return to the caller and program execution continues. Then, the stack frame will be destroyed, releasing the memory to the system for other use. A simple idea is, if the return address can be changed, the program execution flows also can be changed.
A typical stack frame layout for C function call
The functions provided by the tool help library make it easier for you to obtain information about currently executing applications. These functions are designed to streamline the creation of tools, specifically debuggers.