following short c program:
void foo(int a, int b) {
printf("a = %p b = %p\n", &a, &b);
}
main() {
foo(1, 2);
}
ok, now I used gdb to view this program. I got as output:
a = 0x7fff5fbff9ac b = 0x7fff5fbff9a8
and stopped execution after the output (in foo()). now I examined 0x7fff5fbff9ac and the content was:
1....correct
then 0x7fff5fbff9a8 and the content:
2...correct
now I wanted to view the return address of the function and examined (a + 4 bytes) with:
x/g 0x7fff5fbff9b1 (8 bytes!! address, therefore "g" (giant word))
and its content was:
(gdb) x/g 0x7fff5fbff9b1
0x7fff5fbff9b1: 0xd700007fff5fbff9
BUT: THIS IS NOT THE RETURN ADR FROM MAIN! where is my fault?
There are a whole bunch of faulty assumptions in your question.
You're assuming that integer arguments are passed on the stack immediately above the return address (as they are in many--not all--x86 ABIs under the default calling conventions). If this were the case, then immediately following the call, your stack would look like this:
// stack frame of main( )
// ...
value of b
value of a
return address <--- stack pointer
However, your assumption is incorrect. You have compiled your code into a 64-bit executable (as evidenced by the size of the pointer you are printing). Per the OS X ABI, in a 64-bit Intel executable, the first few integer arguments are passed in register, not on the stack. Thus, immediately following the call, the stack actually looks like this:
// stack frame of main( )
// ...
return address <--- stack pointer
Since you take the address of a and b, they will be written to the stack at some point before the call to printf( ) (unless the compiler is really clever, and realizes that it doesn't actually need to hand printf( ) valid pointers because it won't use the value pointed to, but that would be pretty evil as optimizations go), but you really don't know where they will be relative to the return address; in fact, because the 64-bit ABI provides a red zone, you don't even know whether they're above or below the stack pointer. Thus, at the time that you print out the address of a and b, your stack looks like this:
// stack frame of main( )
// ...
return address |
// ... |
// a and b are somewhere down here | <-- stack pointer points somewhere in here
// ... |
In general, the C language standard says nothing about stack layouts, or even that there needs to be a stack at all. You cannot get this sort of information in any portable fashion from C code.
Firstly, &a + 4 is 0x7FFF5FBFF9B0, so you are looking one byte offset from where you think you are.
Secondly, the saved frame pointer lies between a and the return address, and this is the value you are seeing.
What you are doing wrong is making a whole bunch of incorrect and random assumptions about the layout of the stack frame on your given platform. Where did you get that weird idea about "a + 4 bytes" location supposedly holding the return address?
If you really want to do this, get the documentation for your platform (or do some reverse engineering) to find out where and how exactly the return address is stored. Making random guesses and then asking other people why your random guesses do not produce results you for some reason expect is not exactly a productive way to do it.
Related
I have the following program:
#include <stdio.h>
void func(char *str) {
int a = 4;
printf("\n str Address: 0x%8X\n", (unsigned int)&str);
printf("\n a Address: 0x%8X\n", (unsigned int)&a);
}
void main()
{
char c = 'y';
func(&c);
}
When I run the program, I get the following result:
str Address: 0x43570EB8
a Address: 0x43570ECC
My understanding is that the stack in Linux grows from high address to low address. Also str as an argument would be pushed first on the stack. If that is the case, why is str address lower than address for variable a ? Am I printing the addresses in an incorrect way ?
Most likely the parameter str is passed in a register. Normally, it would be used from that register and would never exist on the stack. Because your code takes the address of str, the compiler is forced to put it in memory somewhere so it can provide an address. It appears that the compiler created space for a on the stack first (or at least at a higher address), and then created space for str on the stack and copied the value from the register to the stack location.
You should not expect that inspecting the addresses of objects reveals or mirrors other aspects of a platform, such as its Application Binary Interface (which specifies, among other things, how function parameters are passed) or how stack is managed. A C implementation is free to rearrange things as long as the resulting program achieves the same observable behavior as defined by the C standard, and modern C implementations can make large and unexpected transformations while optimizing programs. Observable behavior includes defined outputs of a program but does not include any rules about the ordering of addresses of objects.
Incidentally, regarding your last question, yes, you are printing addresses incorrectly. To print an address, cast it to void * and print it with %p, not %X.
this is the code :
#include <stdio.h>
#include <stdlib.h>
int main() {
int a = 10;
int b = 20;
//printf("\n&a value %p", &a);
int* x = &b;
x = x + 1;
*x = 5;
printf("\nb value %d", b);
printf("\na value %d", a);
}
I want override a with b adress for test the c overflow but when I comment the line 5(printf fuction) I can't write five in a. While if I print the a adress I can write five in a.
Why?
Sorry for my english and thank you.
The reason this occurred is that all normal compilers store objects with automatic storage duration (objects declared inside a block that are not static or extern) on a stack. Your compiler “pushed” a onto the stack, which means it wrote a to the memory location where the stack pointer was pointing and then decremented the pointer. (Decrementing the pointer adds to the stack, because the stack grows in the direction of decreasing memory addresses. Stacks can be oriented in the other direction, but the behavior you observed strongly suggests your system uses the common direction of growing downward.) Then your compiler pushed b onto the stack. So b ended up at a memory address just below a.
When you took the address of b and added one, that produced the memory address where a is. When you used that address to assign 5, that value was written to where a is.
None of this behavior is defined by the C standard. It is a consequence of the particular compiler you used and the switches you compiled with.
You probably compiled with little or no optimization. With optimization turned on, many compilers would simplify the code by removing unnecessary steps (essentially replacing them with shortcuts), so that 20 and 10 are not actually stored on the stack. A possible result with optimization is that “20” and “10” are printed, and your assignment to *x has no effect. However, the C standard does not say what the behavior must be when you use *x in this way, so the results are determined only by the particular compiler you are using, along with the input switches you give it.
After x = x + 1;, x contains an address that you do not own. And by doing *x = 5; you are trying to write to some location that might not be accessible to you. Thus causing UB. Nothing more can be reasoned about.
I was experimenting with pointers. Look at this code:
#include <stdio.h>
int main() {
int numba = 1;
int *otherintptr = &numba;
printf("%d\n", otherintptr);
printf("%d\n", *otherintptr);
*otherintptr++;
printf("%d\n", otherintptr);
printf("%d\n", *otherintptr);
return 0;
}
The output is:
2358852
1
2358856
2358856
Now, I am well aware that (*otherintptr)++ would have incremented my int, but my question is not this.
After the increment, the memory location is correctly increased by 4 bytes, which is the size of an integer.
I'd like to know why the last printf instruction prints the memory location, while I am clearly asking to print the content of memory locations labelled 2358856 (I was expecting some dirty random content).
Note that the second printf statement prints the content of memory cell 2358852, (the integer 1) as expected.
What happens with these two lines
int numba = 1;
int *otherintptr = &numba;
due to the fact the C compiler will generate a sequential memory layout, otherintptr will initially point to the memory address corresponding to the numba variable. And this is relative to the stack frame allocated when main was called.
Now, the next position on the stack (actually the previous if we consider that the stack grows down on x86 based architectures) is occupied by the otherintptr variable. Incrementing otherintptr will make it point to itself, thus you see the same value.
To exemplify, let's assume that the stack for main begins at the 0x20 offset in memory:
0x20: 0x1 #numba variable
0x24: 0x20 #otherintptr variable pointing to numa
After executing the otherintptr++ instruction, the memory layout will look like this:
0x20: 0x1 #numba variable
0x24: 0x24 #otherintptr variable now pointing to itself
This is why the second printf's have the same output.
When you did otherintptr++, you accidentally made otherintptr to point to otherintptr, i.e. to itself. otherintptr just happened to be stored in memory immediately after your numba.
In any case, you got lucky on several occasions here. It is illegal to use an int * pointer to access something that is not an int and not compatible with int. It is illegal to use %d to print pointer values.
I suppose you wanted to increment the integer otherpointer points to (numba). However, you incremented actually the pointer, as ++ binds stronger than *
see here.
So otherpointer pointed past the variable. And as there is no valid variable, dereferencing the pointer is undefined behaviour. Thus, anything can happen and you just were lucky the program did not crash. It just happend by chance otherpointer itself resided at that address.
Like every function is put on a stack frame for its execution and it is flushed after its completion. So, any local variable wont be available to other functions. But then how are we able to return a local variable to the caller?
int pickMin( int x, int y, int z ) {
int min = x ;
if ( y < min )
min = y ;
if ( z < min )
min = z ;
return min ; }
The above code works fine. However the in the below code, compiler does give a warning message- "warning: function returns address of local variable [-Wreturn-local-addr] return a; " but it prints a garbage value at the end, which I think is fine because the variable has already been flushed. But why didn't that happen in the ABOVE program?! I mean, it should also have returned me a garbage value.Moreover, I know that the problem in the below code can be solved using malloc, and then returning that value. :)
int *returnarray(){
int a[10]; int i;
for(i=0;i<10;++i){
a[i] = i;
}return a;}
C passes everything around by value. In your first snippet, return min returns an int variable. Its value is returned. The second snippet consists of return and an array name, which decays into a pointer.
The value that is returned, is the memory address of a local variable. The function where this variable existed has returned, though, and accessing the memory that this function used then invokes undefined behaviour.
The way to handle this kind of situation (ie: needing to return an array) is either by passing the target array to the function as an argument, or by allocating the memory using malloc and returning that pointer.
Heap memory is a tad slower, more error prone, and requires you to look after it though. Still, here's an example of both approaches
create_fill allocates, assigns and returns a pointer to the heap memory, fill_array doesn't return anything, but expects you to pass an array (which decays into a pointer), and a max length to fill. The advantage being: stack memory doesn't require as much care, and will outperform the heap.
The return statement des exactly that: it copies the value of a variable, and leaves it on top of the stack so the calling function can use it. Now, in C this works for simple values, not for arrays because your "array variable" a is actually the address of its first value only.
First, read carefully call stack wikipage. There are nice pictures on it. See also the x86 calling conventions wikipage.
Then, the result (of some C function) often goes thru a register when returned (or, for large struct-s, in a stack space allocated by the caller).
Details are ABI specific. For Linux on x86-64 (in 64 bits), the x86-64 ABI mentions the %rax register to return a result (in common cases, but when the result is a large struct the caller passes an address for it).
BTW, in principle, I believe that nothing in the C99 standard requires a stack, but I know no C implementations without a call stack (generally the processor stack, i.e. thru the stack register).
In first case you return value of a variable.
While, in second case you return address of a local variable which as you correctly said is not available for other functions. In C, the name of an array is the base address of that array. Hence in second case, "base address of array" is copied to any variable/pointer, which is assigned the return value of that function
#include<stdio.h>
#include<conio.h>
void vaibhav()
{
int a;
printf("%u\n",&a);
}
int main()
{
vaibhav();
vaibhav();
vaibhav();
getch();
return 0;
}
Every time I get the same value for the address of variable a.
Is this compiler dependent? I am using dev c++ ide.
Try to call it from within different stack depths, and you'll get different addresses:
void func_which_calls_vaibhav()
{
vaibhav();
}
int main()
{
vaibhav();
func_which_calls_vaibhav();
return 0;
}
The address of a local variable in a function depends on the state of the stack (the value of the SP register) at the point in execution when the function is called.
In your example, the state of the stack is simply identical each time function vaibhav is called.
It is not necessary. You may or may not get the same value of the address. And use %p instead.
printf("%p\n", (void *)&a);
You should use %p format specifier to print address of a variable. %u & %d are used to display integer values. And the address on stack can be same or not every time you call function vaibhav().
"a" in the function vaibhav() is an automatic variable, which means it's auto-created in the stack once this fun is called, and auto-released(invalid to the process) once the fun is returned.
When funA(here is main) calls another funB(here is vaibhav), a stack frame of funB will be allocated for funB. When funB returns, stack frame for funB is released.
In this case, the stack for funB(vaibhav) is called 3 times sequentially, exactly one by one. In each call, the stack frame for funB is allocated and released. Then re-allocated and recycled for times.
The same memory block in stack memory is re-used for 3 times. In that block, the exact memory for "a" is also re-used for 3 times. Thus, the same memory and you get the same address of it.
This is definitely compiler dependent. It depends on the compiler implementation. But I believe almost every C compiler will produce the same result, though I bet there is no specific requirement in C standard to define the expected output for this case.