I've been reading through the Riot Vanguard (kernel level anti-cheat driver) source code and have some difficulties understanding what I think is a function call.
((void(*)())(RtlFindExportedRoutineByName(VgkDriverObject->DriverStart, "Egg")))();
RtlFindExportedRoutineByName is a function which returns a PVOID, and what I currently have thought up is: take this function which returns a PVOID, cast it to a pointer to a function which returns nothing and call it.
Would love some insight from someone who is more knowledgeable.
EDIT: Why is this better than just calling the function as it is defined?
RtlFindExportedRoutineByName is a function which returns a PVOID, and what I currently have thought up is: take this function which returns a PVOID, cast it to a pointer to a function which returns nothing and call it.
That is correct.
Why is this better than just calling the function as it is defined?
In order to call a function via a pointer, the pointer must be a function pointer. You cannot call a PVOID (which is a typedef for void *) directly, without casting it beforehand.
The function RtlFindExportedRoutineByName is probably returning a pointer to a function that the program does not have direct access to. Therefore, it can only call it via a function pointer.
Related
I'm trying to run an old MUD driver compiled with added -g flag and removed -O2 flag, so that I can debug it. I have a function with a prototype void try_to_swap(void), but the definition is void try_to_swap(volatile int* interrupted). Inside the function the value of that pointer is checked:
if(*interrupted)
...
The function is called without parameters, like the prototype - try_to_swap();
Everything works OK with the optimization flag. But without it I get a SIGSEGV when the function is called. The problem is that the pointer points to an address which is unreachable for the process (0x3b - every time), thus the segmentation fault.
My question is:
a) Why don't I get any errors during make? Shouldn't the lack of the parameter in the call be somehow noticed by the compiler?
b) During optimization, does the compiler somehow take care of the value of the pointer so the program won't crash?
c) What would be the right way to tackle this? Remove the pointer from definiton, add it to the prototype? The pointer is used only in this function, and only in mentioned if. It doesn't seem to be initialized anywhere. Or maybe it's somehow automatically initialized? I'm not too familiar with volatile pointers. But the pointer value is random garbage from the stack set before the function call, as no parameter value was provided. Is this even legal in C, where default values are not an option?
a) In C, () means "any arguments" and isn't the same as (void) which is no argument. try_to_swap() is valid but not a good documentation for users.
b) Yes, the compiler seems to detect the missing parameter and just passes a null pointer.
c) You could add the pointer argument to the prototype and pass what's required by the internal if or try a trick.
I'm learning C, I was looking at https://github.com/mruby/mruby/blob/master/src/load.c and this line made me very confused:
mrb_irep* read_irep_record_1
On line 40.
I can see that this is a pointer of some sort.
What I'd like to know is the following
What does this do?
How do you use them?
What are these called?
How do they work?
How can I replicate this in a program?
I've only this used in C projects, is it recommended to use these in C++? Can you do this in C++?
I searched a bit on Stackoverflow for pointer functions but couldn't find anything like this.
Thanks in advance!
That line is simply declaring a function that returns a pointer to mrb_irep. For example, what does a function declared as int foo() return? Well it returns an int, as we see in the declaration. Similarly, a function declared as mrb_irep* read_irep_record_1(...) returns a variable of type mreb_irep*, or a pointer to a struct called mreb_irep.
I know the reasons why this is a bad idea and I also know that this is the reason C++ templates were created, but I'm doing it in C for the fun and learning.
I'm embedding Python into my application and I wanted to make it possible to register certain C functions, with any arbitrary type, to be callable at the application run-time. Because of this a pointer to them is stored (as a simple void*).
With some basic macro fun I have gotten all the information I need about these functions and stored that too - the function pointer, the size of the return value (and if it is void), the number of arguments and each of their sizes.
So I'm stuck at the final stage - which is the actual calling of the function pointer with the appropriate data. I'm fairly certain this sort of thing should be possible (I've caused stack errors in my own time), but I was wondering if there was a more...legitimate way to do it.
I guess the ideal would look something like this:
void call_function(void* function, void* return, void* arg_data, int arg_data_size);
Does such a thing exists?
Thanks
You can declare a function pointer void* (*f) (void*); that points to a function that takes a void* argument and returns a void* return value -- you can put this in the first parameter of call_function.
Then call call_function as:
void* function(void*);
ret_type ret;
arg_type arg_data;
call_function(&function, (void*)&ret, (void*)&arg_data, sizeof(arg_data));
where arg_type is the actual argument type you want to use inside function and ret_type is the actual type of the return value of function.
Note: you might want to specify the size of the return value type as well.
Note: this will work with any function of one argument. The solution can be extended to a fixed/known number of arguments in function, but not to handle an unknown number of arguments.
Note: naming the second parameter return is not allowed as return is a keyword.
I am building a C-Interpreter (in C++) which builds an AST. I want to give the user the opportunity to communicate with real DLLs. For example: I call a function from a DLL. This function expects an pointer to an function (to callback). There is the problem: I don't have a real address to a function, because the function which I want to give to the DLL-function only exists as node in my AST. Is there a way to solve the problem? I thought about using a proxy-like function built-in into my interpreter, which delegates to the function in my AST. The problem is, that the proxy-function must have the same signature to be callable from the DLL-function ... and i can't create dynamic functions at runtime.
You don't say specifically which API/dll you're trying to use, but MOST of them provide for a void * (or LPVOID on windows) of 'user data' that is supplied along with the callback function pointer and will be passed to the callback function, along with whatever other arguments are appropriate for the callback.
What you can do is pass in a pointer to your AST as this extra pointer, and write a small wrapper function for the actual callback which converts this void * back into an AST * and then invokes your interpreter on that AST.
So I was wondering how they work. To explain what I mean by a "function caller" a good example of what I mean would be glutTimerFunc, it is able to take in a function as a parameter and call it even with it not knowing it is declared. How is it doing this?
What you're talking about is called a callback and is implemented with function pointers in C and C++.
Since you mentioned glut, let's take a real example directly from the freeglut source code. I'll use glutIdleFunc instead of glutTimerFunc because the code is simpler.
In glut, the idle function callback (what you supply to glutIdleFunc) is a pointer to a function that takes no parameters and returns nothing. A typedef is used to give such a function type a name:
typedef void (* FGCBIdle)( void );
Here, FGCBIdle (short for FreeGlut CallBack Idle) is defined as a pointer to a function that takes no parameters and whose return type is void. This is just a type definition that makes writing expression easier, it doesn't allocate any storage.
Freeglut has a structure called SFG_State that holds various settings. Part of the definition of that structure is:
struct tagSFG_State
{
/* stuff */
FGCBIdle IdleCallback; /* The global idle callback */
/* stuff */
};
The struct holds a variable of type FGCBIdle, which we established is another name for a specific function pointer. You can set the IdleCallback field to point to the address of a function that is supplied by the user using the glutIdleFunc function. The (simplified) definition of that function is:
void glutIdleFunc( void (* callback)( void ) )
{
fgState.IdleCallback = callback;
}
Here, fgState is a SFG_State variable. As you can see, the glutIdleFunc takes one parameter which is a function pointer to a function that takes no parameters and returns nothing, this parameter's name is callback. Inside the function, the IdleCallback inside the global fgState variable is set to the user supplied callback. When you call the glutIdleFunc function, you pass the name of your own function (e.g. glutIdleFunc(myIdle)), but what you're really passing is the address of the function.
Later, inside the big glut event processing loop initiated by glutMainLoop, you'll find this code:
if( fgState.IdleCallback )
{
/* stuff */
fgState.IdleCallback( );
}
If a user supplied idle callback is available, it is called in the loop. If you check the function pointer tutorial at the beginning of my post you will understand the syntax better, but I hope the general concept makes more sense now.
The parameter is a pointer to a function. It is the caller's responsibility to ensure that the function declaration matches the requirements (e.g., number and type of parameters, calling convention).
A function passed as a paramter is passed as a function pointer.
In compiled code, a function is nothing more than an address which the CPU can vector off to to execute. When you are passing a function pointer, the compiler (and later the linker) insert the correct address into the call.
Function parameters must match exactly as the executing code will simply push values on the stack (or registers, depending on the architecture) and expect to pop off (read out) the return value.