Reputation: 43
How can I retrieve the function pointer that was used to call a function, from within the function itself? Here's an example of what I need to accomplish:
struct vtable {
void (*func)(void);
};
void foobar(void) {
// How can I get the address of t.func from here?
}
int main(void)
{
struct vtable t = { foobar };
t.func();
return 0;
}
In particular I would like to know if this can be done without using additional parameters in the function definition, ie. not this way:
struct vtable {
void (*func)(struct vtable t);
};
void foobar(struct vtable t) {
...
}
int main(void)
{
struct vtable t = { foobar };
t.func(t);
return 0;
}
Upvotes: 1
Views: 992
Reputation: 1
thank you tretorn i found the answer i wanted with your example i had a very similar question.
this is just a quick easy answer maybe something someone overlooked, but if vtable was global then you can do that without adding a parameter, which is singleton-like for it to be global so a parameter may be hidden so:
void foobar(void) ;
static struct vtable interface = {&foobar};
void foobar(void)
{
interface . foobar() ;
}
int main(void)
{
///...
}
this is because my expert opinion is that if it's a virtual table your using then it has to be global even.
another idea is you can have a global stack and before calling foobar you push the address u wanted and then pop it inside the foobar function. when you wrap this function call with another function call a recursive amount of times a stack will solve a certain kind of alignment error you will get when using a single variable/object, not a stack of variables/objects.
Upvotes: 0
Reputation: 12635
First of all, you cannot get the address of t
if you don't pass any reference to it. This is like trying to follow a pointer back to it's pointer. Pointers in general don't work in the reverse, and this is the reason to write data structures like double linked lists, or similar. Simply you can have millions of such pointers, all pointing to this function, so there's nothing in the function address that allow you to know where the function pointer was stored.
Once said that:
In your first paragraph you say:
How can I retrieve the function pointer that was used to call a function, from within the function itself?
Well, that's preciselly what you get when you use the plain name of the function (as in main
) you can then execute that function using a (probably non empty) argument list, as you do in ()
. You don't know where your function has been called from, but what is true, is that if your program control is inside the body of it, it must have been called from the beginning, so using the function name inside the function could be a way to get a function's pointer. But you cannot get it further and get the structure where that pointer was used... this information is not passed in to your function, you have no means to get to it. This is the same problem as when you are forced to pass an array length to a function because there's nothing in the array that allows you to get how large it is.
I have not checked thoroughly your code, as it is just a snippet of code, that needs some adjustments to evolve into fully executable code, but from my point of view it is correct and will do what you are thinking on. Just test, the computer is not going to break if you make a mistake.
Beware in your code you have passed a full struct
record by value, and that will make a full copy of the struct in order to put it in the parameter stack. Probably what you want is something like:
struct vtable {
void (*func)(void); /* correct */
};
void foobar(void) {
// How can I get the address of t.func from here?
/* if you want to get the address of the function, it is
* easy, every function knows its address, is in its
* name */
void (*f)(void) = foobar; /* this pointer is the only one
* that could be used to call
* this function and be now
* executing code here. :) */
/* ... */
f(); /* this will call foobar again, but through the pointer
* f, recursively (the pointer although, is the same) */
}
int main(void)
{
struct vtable t = { foobar };
t.func();
return 0;
}
It is very common to see functions that use callbacks to be executed on behalf of the calling code. Those functions is common also to require pointers to strcutres that represent the context they are called in behalf of. So don't hesitate to pass arguments to your function (try not to pass large structures by value, as you do in your example ---well, I recognize it is not large, it has only a pointer) but anyway, that is very common. OOP implementation rests deeply on these premises.
Upvotes: 0
Reputation: 407
I can give you a working answer, but it won't be a pretty one.
C is a pretty chill language when it comes to accessing memory. In fact you can access the entire program stack from any function, this means that you can access main
variables from foobar
.
Knowing this is as powerfull as it is usually a bad idea.
For your problem, you can search any pointer to your foobar
function in a range. Simply by creating a struct vtable
pointing to ARBITRARY addresses stored at the stack and then checking if the func
field is the same as the address of foobar
.
Usually this will yield a SIGSEGV
, to avoid this you can limit the addresses used to stack valid addresses using pointer arithmetic.
Here you have a working example in "pure" c (simply play with the RANGE
define). But i have to warn you again, dont use this in the real world, unless you want to flex on your hacking skills.
#include <stdio.h>
#define RANGE 100
struct vtable {
void (*func)(void);
};
void foobar(void) {
int a[1]; //We control the stack from this address!
for (int i = 0; i < RANGE; i++) { //We are basically doing a buffer overflow
if (a[i] > a && a[i] < a+RANGE) { //Ignore addresses too far to prevent SEGF
struct vtable *t = (struct vtable*)a[i];
if (t->func == foobar)
printf("[FOOBAR] Address of t is: %x\n", a[i]);
}
}
}
int main(void)
{
struct vtable t = { foobar };
printf("[MAIN] Address of t: %x\n", &t);
t.func();
return 0;
}
Have a nice day!
Upvotes: 0
Reputation: 213276
the problem that I'm trying to solve is how to get the address of the struct without altering the function's list of arguments
The only way to do that, short of doing it the correct way with parameter passing, is to have the caller store the address in a global variable. That's ugly but possible:
#include <stdio.h>
struct vtable {
void (*func)(void);
};
static struct vtable* lastcall;
#define call(x, func) do { lastcall=&(x); (x).func(); } while(0)
void foobar(void) {
printf("foobar caller: %p\n", (void*)lastcall);
}
int main(void)
{
struct vtable t = { foobar };
printf("Address of t: %p\n", &t);
call(t, func);
return 0;
}
I wouldn't recommend the above - it is better if you change the API to include the struct, then hide that part behind a macro if you must.
Discarding everything that's portability, it is of course also possible to dissect the stack and find the caller address there. This is ABI-specific though, and you might have to do it in assembler.
Upvotes: 3
Reputation: 107739
This is impossible in portable C. It's also impossible on typical implementations.
When you have a function call
int main(void) {
…foobar(…)…
}
there is no way for foobar
to know that it was called by main
using C language constructs alone. Many implementations make this information available through debugging features that let you explore the call stack, which the implementation maintains under the hood so as to keep track of where return
goes to. In practice this doesn't always match the calling structure in the source code due to compile-time transformations such as inlining.
When the function is determined through a function pointer variable, typical implementations do not keep track of this information at all. A typical way to compile t.func()
is:
t.func
into a processor register r.There is no information in memory that links steps 1 and 3. Other things may have happened between steps 1 and 3 depending on how the optimizer handled this particular chunk of code.
If you need to know from which “object” a “method” was called, you need to pass a pointer to the object to the function that is the method. This is how object-oriented languages with actual methods work: under the hood, there is an extra “this” or “self” argument, even if the language doesn't make it explicit.
Upvotes: 4
Reputation: 12590
No, it is not possible. How should a function know by which way it is called?
Consider if you call the function without using a structure holding its pointer, like this:
foobar();
You need to invent some way to pass the requested value as a parameter.
Upvotes: 0