Function Pointer Memory Explanation in C - c

#include <stdio.h>
#include <stdlib.h>
int (*fptr1)(int);
int square(int num){
return num*num;
}
void main(){
fptr1 = &square;
printf("%d\n",fptr1(5));
}
Can someone briefly explain what happens in stack when we call a function pointer? What is the difference between calling a function directly in main() and calling it by function pointer in C language by the means of physical memory and process?
I tried to understand what happens in memory when we call a function with function pointer but it is not enough to me.
When we call a function by pointer, does pointer have this function's location at code space?
When called function is running is it same as normally called function in main()?
What is the difference of calling function directly or using function pointer when code is running in a pipelined branch predictive processor?

The best way to answer this is to look at the disassembly (slightly modified sample):
fptr1 = &square;
int result1 = fptr1(5);
int result2 = square(5);
Results in this x64 asm:
fptr1 = &square;
000000013FA31A61 lea rax,[square (013FA31037h)]
000000013FA31A68 mov qword ptr [fptr1 (013FA40290h)],rax
int result1 = fptr1(5);
000000013FA31A6F mov ecx,5
000000013FA31A74 call qword ptr [fptr1 (013FA40290h)]
000000013FA31A7A mov dword ptr [result1],eax
int result2 = square(5);
000000013FA31A7E mov ecx,5
000000013FA31A83 call square (013FA31037h)
000000013FA31A88 mov dword ptr [result2],eax
As you can see the assembly is virtually identical between calling the function directly and via a pointer. In both cases the CPU needs to have access to the location where the code is located and call it. The direct call has the benefit of not having to dereference the pointer (as the offset will be baked into the assembly).
Yes, you can see in the assignment of the function pointer, that
it stores the code address of the 'square' function.
From a stack
setup/tear down: Yes. From a performance perspective, there is a
slight difference as noted above.
There are no branches, so there is no difference here.
Edit: If we were to interject branches into the above sample, it wouldn't take very long to exhaust the interesting scenarios, so I will address them here:
In the case where we have a branch before loading (or assignment) of the function pointer, for example (in pseudo assembly):
branch zero foobar
lea square
call ptr
Then we could have a difference. Assume that the pipeline chose to load and start processing the instructions at foobar, then when it realized that we weren't actually going to take that branch, it would have to stall in order to load the function pointer, and dereference it. If we were just calling a know address, then there would not be a stall.
Case two:
lea square
branch zero foobar
call ptr
In this case there wouldn't be any difference between direct calls vs through a function pointer, as everything we need is already know if the processor starts executing down the wrong path and then resets to start executing the call.
The third scenario is when the branch follows the call, and that is obviously not very interesting from a pipeline perspective as we've already executed the subroutine.
So to fully re-answer question 3, I would say Yes, there is a difference. But then the real question is whether or not the compiler/optimizer is smart enough to move the branch after the function pointer assignment, so it falls into case 2 and not case 1.

The pointer to function contains the address of the start of the function in the text segment of the program.
Once called, the function runs identically whether it is called directly or by a pointer to function.
I'm not sure. Often, there won't be much difference; the pointer to function doesn't change very often, if at all (e.g. because you loaded a shared library dynamically, so you have to use a pointer to function to call the function).
What is the difference between calling a function directly in main() and calling it by function pointer?
The only difference is possibly an extra memory reference to fetch the function pointer from memory.

Yes
Absolutely
No difference
Calling a function through a function pointer is just a convenience; and makes it possible to pass a function as a parameter to another function. See for example, qsort()

There's no difference between calling a function by its name and calling it through a function pointer. The purpose of function pointers is so that you can call a function that's specified somewhere else. For instance, the qsort() function takes a function pointer as an argument that it calls to determine how to order the elements of the array, rather than having only one comparison method.

Related

Implementing setjmp and longjmp in C without built in functions or assembly (getting incorrect return values)

I'm trying to test 2 of my functions that sort of mimic setjmp and longjmp for a homework - which is pretty difficult since we're not allowed to use built in functions or assembly asm() to implement the longjmp and setjmp functions. (Yes, that's really the assignment.)
Problem: I keep getting wrong return values. So, in short, when main() calls foo() and foo() calls bar(), and bar() calls longjump(), then bar() should not return to foo() but instead setjmp() should return to main with return value of 1 which should print "error" (see main() below).
Instead, my output comes out as:
start foo
start bar
segmentation fault
The segmentation fault, i tried fixing by initializing the pointer *p with malloc, but that didn't seem to do anything. Although, would the segmentation fault, be the reason why im not getting the correct return values?
code:
#include <stdio.h>
#include <stdlib.h>
int setjmp(int v);
int longjmp(int v);
int foo(void);
int bar(void);
int *add;
int main(void) {
int r;
r = setjmp(r);
if(r == 0) {
foo();
return(0);
} else {
printf("error\n");
return(2);
}
}
int _main(void) {
return(0);
}
int setjmp(int v)
{
add = &v;
return(0);
}
int longjmp(int v)
{
int *p;
p = &v;
*(p - 1) = *add;
return(1);
}
int foo(void) {
printf("start foo\n");
bar();
return(0);
}
int bar(void) {
int d;
printf("start bar\n");
longjmp(d);
return(0);
}
Implementing setjmp() and longjmp() requires access to the stack pointer. Unfortunately, the assignment you're working from has explicitly banned you from using every sensible method to do this (i.e, using assembly, or using compiler builtins to access the stack pointer).
What's worse is, they've mangled the definition of setjmp() and longjmp() in their sample code. The argument needs to be a type that resolves to an array (e.g, typedef int jmp_buf[1]), not an int…
Anyways. You need some way to reliably find the old stack pointer from a stack frame in C. Probably the best way of doing this will be to define an array on the stack, then look "behind" it…
void get_sp(void) {
int x[1];
sp = x[-1]; // or -2 or -3, etc…
The exact offset will depend on what compiler you're using, as well as possibly on what arguments your function takes and what other local variables the function has. You will need to experiment a bit to get this right. Run your application in the simulator, and/or look at the generated assembly, to make sure you're picking up the right value.
The same trick will probably work to set the stack pointer when "returning" from longjmp(). However, certain compiler optimizations may make this difficult, especially on architectures with a link register -- such as MIPS. Make sure compiler optimizations are disabled. If all else fails, you may need to call a dummy function in longjmp() to force the compiler to save the link register on the stack, rather than leaving it in a register (where it can't be overwritten).
You are going to need to deal with the link register, the stack pointer, and the frame pointer (you would normally also have to save and restore all of the save registers, but I don't think we need to in order to make this example work).
Take a look at the arg3caller function here. Upon entry, it stores the link register and the frame pointer on the stack, and sets the frame pointer to point to the new stack frame. It then calls args3, sets the return value, and, most importantly, copies the frame pointer back into the stack pointer. It then pops the link register and the original frame pointer from where the stack pointer is now located, and jumps to the link register. If you look at args3, it saves the frame pointer into the stack and then restores it from the stack.
So, arg3caller can be longjmp, but if you want it to return with a different stack pointer than it entered with, you are going to have to change the frame pointer, because the frame pointer gets copied into the stack pointer at then end. The frame pointer can be modified by having args3 (a dummy function called by longjmp) modify the copy of the frame pointer that it saved in the stack.
You will need to make setjmp also call a dummy function in order to get the link register and frame pointer stored on the stack in the same way. You can then copy the link register and frame pointer out of setjmp's stack frame into globals (normally, setjmp would copy stuff into the provided jmpbuf, but here, the arguments to setjmp and longjmp are useless, so you have to use globals), as well as the address of the frame. Then, longjmp must copy the saved link register and frame pointer back into the same address, and have the dummy leaf function change the saved frame pointer to that same address. Thus, the dummy leaf function will copy that address into the frame pointer and return to longjmp, which will copy it into the stack pointer. It will then restore the frame pointer and the link register from that stack frame (that you populated), thus returning with everything in the state that it was when setjmp originally returned (except the return value will be different).
Note that you can access these fields by using the negative indexing of a local array trick described by #duskwuff. You should initially compile with the -S flag so that you can see what asm gcc is generating so that you can see where the important registers are being saved in the stack (and how your code might perturb all of that).
Edit:
I don't have immediate access to a MIPS gcc, but I found this, and put it in MIPS gcc 5.4 mode. Playing around, I found that non-leaf functions store lr and fp immediately below where the argument would be placed on the stack (the argument is actually passed in a0, but gcc leaves room for it on the stack in case the callee needs to store it). By having setjmp call a leaf function, we can ensure that setjmp is a non-leaf so that its lr is saved on the stack. We can then save the address of the arg, and the lr and fp that are stored immediately below it (using negative indexing), and return 0. Then, in longjmp, we can call a leaf function to ensure the lr is saved on the stack, but also have the leaf change its stacked fp to the saved sp. Upon return to longjmp, the fp will be pointing at the original frame, which we can re-populate with the saved lr and fp. Returning from longjmp will copy the fp back into the sp and restore the lr and fp from our re-populated frame, making it appear that we are returning from setjmp. This time however, we return 1 so the caller can differentiate the true return from setjmp to the fake one engineered by longjmp.
Note that I have only eyeballed this code, and have not actually executed it!! Also, it must be compiled with optimization disabled (-O0). If you enable any kind of optimization, the compiler inlines the leaf functions and turns both setjmp and longjmp into empty functions. You should see what your compiler does with this to understand how the stack frames are constructed. Again, we're well and truly in the land of undefined behavior, and even changes in gcc version could upset everything. You should also single step the program (using gdb or spim) to make sure you understand what's going on.
struct jmpbuf {
int lr;
int fp;
int *sp;
};
static struct jmpbuf ctx;
static void setjmp_leaf(void) { }
int setjmp(int arg)
{
// call the leaf so that our lr is saved
setjmp_leaf();
// the address of our arg should be immediately
// above the lr and fp
ctx.sp = &arg;
// lr is immediately below arg
ctx.lr = (&arg)[-1];
// fp is below that
ctx.fp = (&arg)[-2];
return 0;
}
static void longjmp_leaf(int arg)
{
// overwrite the caller's frame pointer
(&arg)[-1] = (int)ctx.sp;
}
int longjmp(int arg)
{
// call the leaf so that our lr is saved
// but also to change our fp to the save sp
longjmp_leaf(arg);
// repopulate the new stack frame with the saved
// lr and fp. &arg is calculated relative to fp,
// which was modified by longjmp_leaf. &arg isn't
// where it used to be!
(&arg)[-1] = ctx.lr;
(&arg)[-2] = ctx.fp;
// this should restore the saved fp and lr
// from the new frame, so it looks like we're
// returning from setjmp
return 1;
}
Good luck!

Is function name an alias for a memory of instructions?

consider the function
int fun(){
int I;
}
Now is fun a pointer to memory or just an alias for memory location.
The compiler will often just inline a simple function, so something like that might be neither. But otherwise, it is actually a series of instructions. for each function call, the compiler will put a series of instructions that save the current registers on the stack, then jump to the memory location corresponding to that function name, then popping any parameters into registers, and including a ret (return) call at the end which will restore the stack and pointer to the next instruction.
it's an alias, like a static array is. It resolves to an address but unlike a pointer it does not store the address.

when the memory is cleared on stack for a local function?

I want to know when exactly the memory is cleared in stack which is allocated for local function calls. I have seen in some video tutorial when the function call is returned to main the memory which is allocated for local function is cleared. I have few questions on below program, please explain.
#include<stdio.h>
void print(){
printf("testing \n");
}
int* sum(int* a, int* b){
int c = *a + *b;
return &c;
}
int main(){
int a=3,b=2;
int *ptr = sum(&a,&b);
print();
printf("sum is: %d",*ptr);
return 0;
}
when I run the above program, it is printing garbage value which is expected. But if I comment "print()" function in main and then run the program it is printing correct value of sum.
Is this mean that even though the execution of local function is completed in stack, until there is another function call to the stack, the previous allocated memory is not cleared ?
If I remove the "printf" statement in "print()" and keep the "print()" call in main, then I could see the result of sum as normal. Why it didn't overwrite the memory in stack?
C has no stack, the word stack is not even mentioned in the standard (C89, C99 or C11). An implementation may use a stack to provide the behavioural aspects of the C abstract machine but it's the abstract machine itself which the standard specifies.
So, as to when the stack is cleared (assuming it even exists), that's something that's totally up to the implementation. What you are doing is basically undefined behaviour, accessing an object after its lifetime has ended, so the results can be anything the implementation chooses.
As to why you can access the items after their lifetime has ended for a specific implementation, most likely it's because entering and exiting a function doesn't clear the stack, it simply adjusts the stack pointer (a lot more efficient than having to clear the memory as well).
So, unless something overwrites what's at that memory location (such as a subsequent call to printf), it'll probably remain at whatever it was last set to.
By way of example, here's a sample prolog code for a function:
push ebp ; Save the frame pointer.
mov ebp, esp ; Set frame pointer to current stack pointer.
sub esp, XX ; Allocate XX space for this frame.
and its equivalent epilog:
mov esp, ebp ; Restore stack pointer.
pop ebp ; Get previous frame pointer.
ret ; Return.
Note that neither the allocation of space (sub in the prolog) nor the deallocation of it (mov in the epilog) actually clears the memory it's using.
However, as stated, it's not something you should rely on.
The answer to your question is operating system specific. In a system that creates process from scratch (VMS/NT) the stack gets cleared only when the process is created. The stack is created from demand-zero pages. When a stack page is accessed for the first time, the operating system creates a new zero pages.
In forking systems the stack gets cleared out whenever a new executable is loaded. Usually the process is the same as above.
After the stack is created, whatever is put there stays there until overwritten.
The stack is managed by the operating system; not the programming languages.

C assembler function casting

I came across this piece of code (for the whole program see this page, see the program named "srop.c").
My question is regarding how func is used in the main method. I have only kept the code which I thought could be related.
It is the line *ret = (int)func +4; that confuses me.
There are three questions I have regarding this:
func(void) is a function, should it not be called with func() (note the brackets)
Accepting that that might be some to me unknown way of calling a function, how can it be casted to an int when it should return void?
I understand that the author doesn't want to save the frame pointer nor update it (the prologue), as his comment indicates. How is this skipping-two-lines ahead achieved with casting the function to an int and adding four?
.
(gdb) disassemble func
Dump of assembler code for function func:
0x000000000040069b <+0>: push %rbp
0x000000000040069c <+1>: mov %rsp,%rbp
0x000000000040069f <+4>: mov $0xf,%rax
0x00000000004006a6 <+11>: retq
0x00000000004006a7 <+12>: pop %rbp
0x00000000004006a8 <+13>: retq
End of assembler dump.
Possibly relevant is that when compiled gcc tells me the following:
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
Please see below for the code.
void func(void)
{
asm("mov $0xf,%rax\n\t");
asm("retq\n\t");
}
int main(void)
{
unsigned long *ret;
/*...*/
/* overflowing */
ret = (unsigned long *)&ret + 2;
*ret = (int)func +4; //skip gadget's function prologue
/*...*/
return 0;
}
[Edit] Following the very helpful advice, here are some further information:
calling func returns a pointer to the start of the function: 0x400530
casting this to an int is dangerous (in hex) 400530
casting this to an int in decimal 4195632
safe cast to unsigned long 4195632
size of void pointer: 8
size of int: 4
size of unsigned long: 8
[Edit 2:] #cmaster: Could you please point me to some more information regarding how to put the assembler function in a separate file and link to it? The original program will not compile because it doesn’t know what the function prog (when put in the assembler file) is, so it must be added either before or during compilation?
Additionally, the gcc -S when ran on a C file only including the assembly commands seem to add a lot of extra information, could not func(void) be represented by the following assembler code?
func:
mov $0xf,%rax
retq
This code assumes a lot more than what is good for it. Anyway, the snippet that you have shown only tries to produce a pointer to the assembler function body, it does not attempt to call it. Here is what it does, and what it assumes:
func by itself produces a pointer to the function.
Assumption 1:
The pointer actually points to the start of the assembler code for func. That assumption is not necessarily right, there are architectures where a function pointer is actually a pointer to a pair of pointers, one of which points to the code, the other of which points to a data segment.
func + 4 increments this pointer to point to the first instruction of the body of the function.
Assumption 2:
Function pointers can be incremented, and their increment is in terms of bytes. I believe that this is not covered by the C standard, but I may be wrong on that one.
Assumption 3:
The prolog that is inserted by the compiler is precisely four bytes long. There is absolutely nothing that dictates what kind of prolog the compiler should emit, there is a multitude of variants allowed, with very different lengths. The code you've given tries to control the length of the prolog by not passing/returning any parameters, but still there can be compilers that produce a different prolog. Worse, the size of the prolog may depend on the optimization level.
The resulting pointer is cast to an int.
Assumption 4:
sizeof(void (*)(void)) == sizeof(int). This is false on most 64 bit systems: on these systems int is usually still four bytes while a pointer occupies eight bytes. On such a system, the pointer value will be truncated. When the int is cast back into a function pointer and called, this will likely crash the program.
My advice:
If you really want to program in assembler, compile a file with only an empty function with gcc -S. This will give you an assembler source file with all the cruft that's needed for the assembler to produce a valid object file and show you where you can add the code for your own function. Modify that file in any way you like, and then compile it together with some calling C code as normal. That way you avoid all these dangerous little assumptions.
The name of a function is a pointer to the start of the function. So the author is not calling the function at that point. Just saving a reference to the start of it.
It's not a void. It's a function pointer. More precisely in this case it is of type: void (*)(void). A pointer is just an address so can be cast to an int (but the address may be truncated if compiled for a 64 bit system as ints are 32 bits in that case).
The first instruction of the function pushes the fp onto the stack. By adding 4, that instruction is skipped. Note that in the snippets you gave the function has not been called. It's probably part of the code that you have not included.

Where does the return statement save its data?

#include<stdio.h>
int add(int,int);
int main()
{
int a;
a=add(5,7);
printf("%d",a);
}
int add(int x,int y)
{
x=x+y;
return(x);
}
Last night I got a doubt on return statement. See x is an auto variable defined inside the add function and as ANSI said an auto variable exists and has its lifetime only inside the function but here the return statement can make the variable a to exist even outside the function. Where does it store the value ? Stack or heap ?
Neither on the stack nor on the heap.
At least in the x86 architecture, the return value of functions is usually copied to the eax register, so it persists outside of the function. This is one of the reasons why you can't return an array but merely a pointer to it.
You can, however, return structs and other larger variables by value, in which case the compiler does some tricks by using the stack and additional registers such as edx.
What return actually does depends on the machine architecture to which the code is compiled. On a machine with registers the value of x is copied to a register. The caller will pick up the value from there and do something with it. Here, that value is copied to a variable named a.
If this code is compiled on a stack machine, the return value might be just left on the stack itself. The object code for calling the add function will look something like this:
push 7
push 5
call add
seti 0x28ccf4
add will pop the values from the stack, add them together and push the result back to the stack. (If the function deals with data structures that will not find into a slot on the stack, their addresses are pushed instead.) seti is an operation that will pop a value from the stack and assign it to the integer variable at a particular address. (Here, 0x28ccf4 is the address of a.). As the top of the stack will now contain the result of adding 5 and 7, the value of a will become 12.
It varies. In a typical case, you can count on anything up to at least the size of an int being returned in some register(s) (e.g., typically eax on x86, $v0-$v1 on MIPS, r0 on ARM).
On many machines, larger return values (e.g., a struct with several members) will result in the caller allocating space on the stack to hold the return value, and either passing a pointer to that space as a hidden argument to the function, or the function having implicit knowledge of the location of that space relative to (for example) the stack pointer when the function was entered.
Though the question is tagged C, I'll also mention that in C++ there are a few special rules about return values. Specifically, there's a return value optimization and a named return value optimization. These allow a compiler to elide code for copying a return value, even if/when (for example) the copy would normally have visible side effects. These are intended to allow optimization where the function constructs a return value where the calling code will need it, rather than constructing it locally in the function, and then making a copy back to where the calling code can use it.
It is stored in a register in most platforms I know about, but this could be changed by compiler implementation.
It is worth noticing that while return x where x is a value and not pointer, such as in you case is legitimate, if x is a pointer, you should make sure that the buffer / data it points to is valid when the function returns, otherwise it will be a valid pointer that points to invalid location.
This is most likely covered in programming language course if you are a CS student. Anyway, you can check out the Wikipedia.
And in fact, it is stored in the call stack, aka stack.
The return value of add function is copied back to 'a' in the main function. The auto variables declared within a function are present in the activation record for that function on the call stack and the activation record is removed at the end of function execution, after copying any return value back to the caller's variable..

Resources