Raised This Month: $51 Target: $400
 12% 

Calling static / virtual functions


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
micapat
Veteran Member
Join Date: Feb 2010
Location: Nyuu, nyuu (France).
Old 03-26-2016 , 09:32   Calling static / virtual functions
Reply With Quote #1

Hi everyone,

For information, I'm under Linux.

1.) Static functions

I would like to call a standard function, like for example :

PHP Code:
int UTIL_ClientsInGame(void); // _Z18UTIL_ClientsInGamev 
Is it possible with only "GetMemSig()" (Seems to easy )?

PHP Code:
void *pAddr NULL;
if (
pGameConfig->GetMemSig("UTIL_ClientsInGame", &pAddr) && pAddr)
{
    
int (*pftCall)(void) = (int (*)(void)) pAddr// This cast is ugly.
    
return pftCall();
}

return -
1
2.) Virtual functions

I saw some examples like:

PHP Code:
void VFuncs::CommitSuicide(CBaseEntity *pThisPtr)
{
    
void **this_ptr = *(void ***)&pThisPtr;
    
void **vtable = *(void ***)pThisPtr;
    
void *func vtable[m_Off_CommitSuicide]; 
 
    
union {CBaseEntity *(VfuncEmptyClass::*mfpnew)( void );
    
#ifndef __linux__
            
void *addr;    } u;     u.addr func;
    
#else // GCC's member function pointers all contain a this pointer adjustor. You'd probably set it to 0 
                
struct {void *addrintptr_t adjustor;} s; } uu.s.addr funcu.s.adjustor 0;
    
#endif
 
    
(reinterpret_cast<VfuncEmptyClass*>(this_ptr)->*u.mfpnew)();

Is "vtable" common to all the instances of "CBaseEntity"?
==> If I keep a copy of the union "u" in this example, can I used it later for any "CBaseEntity", or should I retrieve each time the "vtable"?

Thanks!
__________________
micapat is offline
donrevan
AlliedModders Donor
Join Date: Jul 2010
Old 03-26-2016 , 17:38   Re: Calling static / virtual functions
Reply With Quote #2

1) Yes, the example you posted should work fine!

2) Yes and no, each CBaseEntity shares the same vtable instance BUT subclasses have their own.
CBaseEntity vtable instances are shared among other CBaseEntities
CBaseCombatCharacter vtable instances are shared among other CBaseCombatCharacters
CBaseCombatWeapon vtable instances are shared among other CBaseCombatWeapons
.. and so on

you should just do the lookup for every entity

Last edited by donrevan; 03-26-2016 at 17:41.
donrevan is offline
micapat
Veteran Member
Join Date: Feb 2010
Location: Nyuu, nyuu (France).
Old 03-27-2016 , 20:04   Re: Calling static / virtual functions
Reply With Quote #3

Thank you very much !

Just for testing, I tried to call "CreateEntityByName()" (@_Z18CreateEntityByNamePKcib).
I have no error with "pGameConfig->GetMemSig()", but it crashes my server.

I'm calling this function in "SDK_OnLoad", is it the issue? When it's possible to create an entity?

PHP Code:
static CBaseEntity *(*gl_pftCreateEntityByName)(const char *, intbool) = NULL;

void UTIL_Prepare(IGameConfig *pGameConfig)
{
    
void *pAddr NULL

    
// Get CreateEntityByName(const char *, int, bool)
    
if (pGameConfig->GetMemSig("CreateEntityByName", &pAddr) && pAddr
    {
        
gl_pftCreateEntityByName = (CBaseEntity *(*)(const char *, intbool)) pAddr;
    }
    else
    {
        
smutils->LogError(myself"Can't find the function 'CreateEntityByName' !");
    }
}

CBaseEntity *UTIL_CreateEntityByName(const char *szClassname)
{
    if (
gl_pftCreateEntityByName)
    {
        return 
gl_pftCreateEntityByName(szClassname, -1true);
    }

    return 
NULL;

__________________
micapat is offline
WildCard65
Veteran Member
Join Date: Aug 2013
Location: Canada
Old 03-28-2016 , 07:42   Re: Calling static / virtual functions
Reply With Quote #4

Game(Incase of a simpler way to call CreateEntityByName).

And I think the best time to call it is after map load.

Last edited by WildCard65; 03-28-2016 at 07:44.
WildCard65 is offline
donrevan
AlliedModders Donor
Join Date: Jul 2010
Old 03-28-2016 , 14:58   Re: Calling static / virtual functions
Reply With Quote #5

If you just want to test things out you can late load your extension when a map is already loaded via "sm exts load NAME". I'm not sure if it crashes when you call CreateEntityByName too early, could be the case.

If it still crashes attach gdb and look at the address returned by GetMemSig or set a breakpoint on UTIL_CreateEntityByName to see where the problem is. GDB is usefull :)

Last edited by donrevan; 03-28-2016 at 14:58.
donrevan is offline
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 03-28-2016 , 15:19   Re: Calling static / virtual functions
Reply With Quote #6

Quote:
Originally Posted by micapat View Post
Is "vtable" common to all the instances of "CBaseEntity"?
==> If I keep a copy of the union "u" in this example, can I used it later for any "CBaseEntity", or should I retrieve each time the "vtable"?

Thanks!
No, each child class of CBaseEntity will have additional entries.

Having said that, as a general rule, the parent's vtable entries are always first in the child's vtable, unless the child has multiple parents.

TL;DR
Technically no, but yes in practice.
__________________
Not currently working on SourceMod plugin development.
Powerlord is offline
micapat
Veteran Member
Join Date: Feb 2010
Location: Nyuu, nyuu (France).
Old 03-28-2016 , 21:12   Re: Calling static / virtual functions
Reply With Quote #7

Thank you everyone for these information!
Using some printf(), I confirmed that the issue is from "UTIL_CreateEntityByName()" --> I will call this function after the map is loaded!

-----------------------

I stopped for the moment these tests: I'm struggling with a configuration issue...

When I enable the #define "SMEXT_CONF_METAMOD", I got no issue with the compilation, but my extension becomes really big (> 800ko)!
On the server, the extension doesn't load: "undefined symbol: _Z6ConMsgPKcz"...

I used this tutorial to install everything.

-----------------------

Spoiler


==> Why these two libraries aren't linked for my extension?

I can see with ambuild --show-steps:

Spoiler


-----------------------

I use ambuild:

cd build
python ../configure.py --sdks=csgo
ambuild

Am I missing something (LD_LIBRARY_PATH... ?).
__________________
micapat is offline
asherkin
SourceMod Developer
Join Date: Aug 2009
Location: OnGameFrame()
Old 03-29-2016 , 19:32   Re: Calling static / virtual functions
Reply With Quote #8

Use Clang rather than GCC.
__________________
asherkin is offline
micapat
Veteran Member
Join Date: Feb 2010
Location: Nyuu, nyuu (France).
Old 04-02-2016 , 13:26   Re: Calling static / virtual functions
Reply With Quote #9

Perfect, with Clang it works now .
Thank you!
__________________
micapat is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 14:43.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode