Thursday, September 3, 2009

Stack Growth - Stackoverflow

Stack Growth

Another question you might get is to try to figure out which way a stack grows. As we know a stack (memory region interpreted as a stack) gets allocated for each process. The stack is used to store local variables and context local to the process. Each function call in a process gets a frame inside the stack where the variables local to the functions get stored; when the function exits the frame gets freed. The stack is also used to store the address of the caller function so that the IP (instruction pointer) can jump back after exiting a function call. i.e:

From the example below (Program:) before main() jumps off into foo(), it first pushes the current address of the IP into the stack so that when foo finishes, the IP can know where to go back to in main();

In some systems the stack is said to grow up and in others it is said to grow down. What the heck does that mean? See bellow:

Memory:
0x00000004 -- -- -- --
0x00000008 -- -- -- --
0x0000000C -- -- -- --
0x00000010 -- -- -- --
...

Program:
int foo();
main();
main()-call->foo();

In a simplistic world (don't hold me to the number it's just an example) if your main()'s frame is at 0x0000000C and foo()'s frame is pushed onto the stack at 0x00000008 then the stack is said to grow down-even though in the diagram it might appear as growing up-because the addresses decrease in that direction. If foo() were to appear at 0x00000010 then the stack would grow up, or in the direction in which the addresses increase.

Code:

#include <stdio.h>

void stackTracer(int *x)
{
int y;
if(&y > x)
printf("The stack grows down\n");
else
printf("The stack grows up\n");
}

int main()
{
int x;
stackTracer(&x);
getchar();
return 0;
}


The code works because when stackTracer is called, the main() frame had already been created in the stack, therefore stackStracker() would be pushed onto the stack after main(). If the address of a variable declared in stackTracer() is greater that the address of a variable declared in main(), that tells you that the stack is growing up as it's growing in the direction that the addresses increase.

StackOverflow

The Stack has a size that is defined even before the process begins to run. The size of the Stack is defined by the linker and can be adjusted by changing the linker flags. But once the program has been linked with the Stack size then that will remain the size of the process' stack throughout its life time. Sometimes if you are not careful, you can grow the stack (recursion anyone?) over its allowed size; and you get a stackoverflow exception.

How can you tell the size of your stack?

This program came out of a couple of minutes of spare time when a co-worker friend of mine and myself decided to overflow the stack just for fun:

Code:


#include <stdio.h>

int counter = 0;
void crasher()
{
double array[10];
array[0]=1;
counter++;
printf("Counter is at %d", counter);
crasher();
}
int main()
{
crasher();
return 0;
}



Then to calculate the size of your stack do => counter (amount of times you allocated that array) * 8 bytes (the size of a double [check your system though]) * 10 (the amount of doubles in the array). Note: this will be roughly the size of your stack, to check the exact size you can always check the default for your linker or the linker flags.

Wednesday, September 2, 2009

Byte swizzling

So, we have all heard about little endian and big endian concepts. We all know that in a little endian system the least significant byte gets stored first, or at the lowest address. In a big endian system the most gets stored in first, or at the lowest address.

So what happens if you are trying to read data that has been stored in a big endian system?

Say you have 0xDEADBEEF stored like so:

Memory:
a => DE
a+1 => AD
a+2 => BE
a+3 => EF

if you have a 32 bit pointer address pointing to a+3 the value read will be 0XEFBEADDE. In order to make sense of the value you will need to swizzle it. In other words; you will need to change the order of bytes.

Here is code which will swizzle a 32 bit value:


#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#define CODETOSWIZZLE 0XEFBEADDE
int main()
{

unsigned int swizzledCode = \
((CODETOSWIZZLE & 0x000000FF)<<24)\
+((CODETOSWIZZLE & 0x0000FF00)<<8)\
+((CODETOSWIZZLE & 0x00FF0000)>>8)\
+((CODETOSWIZZLE & 0xFF000000)>>24);

printf("Swizzled %x", swizzledCode);

getchar();
return 0;
}