Fix/Implement VScript FFI for GCC's virtual member functions

This commit is contained in:
Alexander 'z33ky' Hirsch 2021-03-20 19:21:53 +01:00
parent 761f065d55
commit 28e87ce3d2

View File

@ -137,29 +137,25 @@ inline void *ScriptConvertFuncPtrToVoid( FUNCPTR_TYPE pFunc )
#elif defined( GNUC ) #elif defined( GNUC )
else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) ) else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) )
{ {
AssertMsg( 0, "Note: This path has not been verified yet. See comments below in #else case." );
struct GnuMFP struct GnuMFP
{ {
union union
{ {
void *funcadr; // If vtable_index_2 is even, then this is the function pointer. void *funcadr; // If vtable_index_2 is even, then this is the function pointer.
int vtable_index_2; // If vtable_index_2 is odd, then this = vindex*2+1. int vtable_index_2; // If vtable_index_2 is odd, then (vtable_index_2 - 1) * 2 is the index into the vtable.
}; };
int delta; int delta; // Offset from this-ptr to vtable
}; };
GnuMFP *p = (GnuMFP*)&pFunc; GnuMFP *p = (GnuMFP*)&pFunc;
if ( p->vtable_index_2 & 1 ) if ( p->delta == 0 )
{
char **delta = (char**)p->delta;
char *pCur = *delta + (p->vtable_index_2+1)/2;
return (void*)( pCur + 4 );
}
else
{ {
// No need to check whether this is a direct function pointer or not,
// this gets converted back to a "proper" member-function pointer in
// ScriptConvertFuncPtrFromVoid() to get invoked
return p->funcadr; return p->funcadr;
} }
AssertMsg( 0, "Function pointer must be from primary vtable" );
} }
#else #else
#error "Need to implement code to crack non-offset member function pointer case" #error "Need to implement code to crack non-offset member function pointer case"
@ -257,8 +253,30 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
convert.mfp.m_delta = 0; convert.mfp.m_delta = 0;
return convert.pFunc; return convert.pFunc;
} }
#elif defined( POSIX ) #elif defined( GNUC )
AssertMsg( 0, "Note: This path has not been implemented yet." ); if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) )
{
struct GnuMFP
{
union
{
void *funcadr; // If vtable_index_2 is even, then this is the function pointer.
int vtable_index_2; // If vtable_index_2 is odd, then (vtable_index_2 - 1) * 2 is the index into the vtable.
};
int delta; // Offset from this-ptr to vtable
};
union FuncPtrConvertGnu
{
GnuMFP mfp;
FUNCPTR_TYPE pFunc;
};
FuncPtrConvertGnu convert;
convert.mfp.funcadr = p;
convert.mfp.delta = 0;
return convert.pFunc;
}
#else #else
#error "Need to implement code to crack non-offset member function pointer case" #error "Need to implement code to crack non-offset member function pointer case"
#endif #endif