I have this… weird problem and I’m desperately looking for a solution.
We have this example: (made for 32-bit systems)
#include <stdio.h>
//unsigned foo(unsigned arg_a, unsigned arg_b) {
unsigned foo(unsigned arg_a, ...) {
unsigned *temp = (unsigned *)((unsigned)&arg_a + 4);
return *temp + arg_a;
}
int main(void) {
int i = foo(0xbe00, 0x00af);
printf("We got a %x\n", i);
return 0;
}
Function foo has 2 arguments. The goal is to “guess” the address of arg_b based on the address of the arg_a. This is based on the assumption that caller (main) will push arg_a and arg_b into the stack (so that (int)&arg_b – (int)&arg_a == 4 ).
Depending on the compiler and the optimization level, the output differs as follows:
gcc -g -Wall -O0 test.c
./a.out
We got a beaf
gcc -g -Wall -O1 test.c
./a.out
We got a beaf
gcc -g -Wall -O2 test.c
./a.out
We got a 80542b0
gcc -g -Wall -O3 test.c
./a.out
We got a 80542b0
clang -g -Wall -O0 test.c
./a.out
We got a 8054281
clang -g -Wall -O1 test.c
./a.out
We got a 805423f
clang -g -Wall -O2 test.c
./a.out
We got a b768d9d6
clang -g -Wall -O3 test.c
./a.out
We got a b76899d6
(The example is quite unstable and for example by putting a printf inside foo, gcc always prints “We got a beaf”. Clang.. not..)
The above example is just my way to try and be clear.
My REAL question (and my goal) is the following:
How can a extract the original address of arg_a, i.e. the address that the caller (main) pushed 0xbe00 in the stack by using CLANG from inside foo function? (gcc is not an option, although it’s still interesting)
Thanx for your time!
edit: made foo variadic in order for the question to make more sense…
I don’t think this is going to work for you.
First off, if gcc is your compiler, why don’t you just pull in the standard C library? If you don’t want to do that, what about pulling in just stdarg.h from the standard implementation?
The version of stdarg.h I’m looking at (came with gcc 4.4.0 on Windows) is basically a bunch of macros that call compiler builtins – if you’ve got the right one for the compiler, then it should be easy, even if you don’t use the rest of the standard library (I can understand a reluctance to pull in that whole mess).
If that doesn’t work for you, then try marking the function you are writing as variadic, and look in the compiler docs for how it builds the stack. You may well have to write some snippets of assembler depending on platform, but by declaring the function as variadic you’ll force the compiler to build the stack in a predictable way.
If your compiler doesn’t support variadic arguments to functions, then you might want to reconsider your other options.