subhook
subhook copied to clipboard
Question: Supports class methods?
The README example illustrated hooks for global functions. Do hooks work for instanced class methods (virtual and non-virtual), and method overloads?
It would probably work if you somehow obtain a pointer to the member function that you wish to hook and declare your function with __thiscall or something similar, but I haven't tried that to be honest.
Short: Yes.
Long: I had to recast the member function pointer, because my gcc refuses converting it directly to a void * (I casted it to a normal function pointer first).
It gets a little bit tricky if the function is a virtual one, because than the member function pointer is an index of the function in the vtable (at least in my gcc version). So you have to get the correct function pointer out of the vtable.
You also have some work to do, if the function is private, and you want to set the hook from outside. (Google for "C++ how to access of private members")
If you have everything up and running, you get the this pointer as first function argument. Of course you can only use the public members/methods, because you are outside in your C-function.
Short: Yes.
Long: I had to recast the member function pointer, because my gcc refuses converting it directly to a void * (I casted it to a normal function pointer first).
Hey there,
Can you go into more detail on how you typecasted a class function to a void* poiner? That is usually considered an invalid conversion or UB, vast majority of compilers straight-up error it out, so I'm curious if there's a "correct" way of accomplishing it.
#include <stdint.h>
#include <iostream>
using namespace std;
class C
{
public:
void foo(int bar)
{
cout << reinterpret_cast<uintptr_t>(this) << " -> " << bar << endl;
}
};
typedef void (C::*cvifptr_t)(int);
typedef void (*vifptr_t)(int, int);
int main(int argc, char **argv)
{
C c;
cvifptr_t zup = &C::foo;
cout << zup << endl;
vifptr_t baz = reinterpret_cast<vifptr_t>(zup);
cout << baz << endl;
(c.*zup)(123);
(*baz)(1234, 321);
return 0;
}
#include <stdint.h> #include <iostream> using namespace std; class C { public: void foo(int bar) { cout << reinterpret_cast<uintptr_t>(this) << " -> " << bar << endl; } }; typedef void (C::*cvifptr_t)(int); typedef void (*vifptr_t)(int, int); int main(int argc, char **argv) { C c; cvifptr_t zup = &C::foo; cout << zup << endl; vifptr_t baz = reinterpret_cast<vifptr_t>(zup); cout << baz << endl; (c.*zup)(123); (*baz)(1234, 321); return 0; }
Thanks for your reply; however the line vifptr_t baz = reinterpret_cast<vifptr_t>(zup); fails to compile with both VS and cl.exe with error C2440: 'reinterpret_cast': cannot convert from 'cvifptr_t' to 'vifptr_t' note: There is no context in which this conversion is possible.
I see that you're converting the class function pointer zup to a standalone function pointer baz, and the calling it with 2 arguments. Is this supposed to represent the behaviour of the __thiscall convention, where the first argument is the this pointer to the class?
Thanks for your reply; however the line
vifptr_t baz = reinterpret_cast<vifptr_t>(zup);fails to compile with both VS andcl.exewitherror C2440: 'reinterpret_cast': cannot convert from 'cvifptr_t' to 'vifptr_t' note: There is no context in which this conversion is possible.
I'm sorry to hear that, it compiles with a warning (which can be suppressed with -Wno-pmf-conversions) using GCC 13.2 on Linux (I recommend experimenting with different compilers on godbolt.org)
I see that you're converting the class function pointer
zupto a standalone function pointerbaz, and the calling it with 2 arguments. Is this supposed to represent the behaviour of the__thiscallconvention, where the first argument is thethispointer to the class?
Exactly.
https://godbolt.org/z/qMqTWGn14