• Binary module help (Unresolved External Symbol)
    5 replies, posted
Hey guys, so im making a module which I have done before but im using source sdk to access engine functions. One thing I wanted to try and do was to call functions on an entity but I seem to have hit a big brick wall. When ever I try to call functions from the CBaseEntity class I get a unresolved external symbol. I'm including every lib that comes with source sdk, and im including all the files I seem to need. I can call functions from IVEngineClient fine and they work and compile, but something like this does not [CODE] CBaseEntity* ent = (CBaseEntity*)GetClientEntityInterface()->GetClientEntity(GetEngineInterface()->GetLocalPlayer()); ent->SetAbsAngles(QAngle(1, 1, 1)); [/CODE] Ugly I know but that wont compile. If I comment/remove the bottom line (ent->) then it works fine. It seems that calling any functions from it results in a unresolved external symbol error. Any help will be appreciated, my includes are below. [CODE]#include "public/tier0/wchartypes.h" #include "public/tier0/basetypes.h" #include "public/cdll_int.h" #include "public/iprediction.h" #include "public/bone_setup.h" #include "public/icliententitylist.h" #include "public/ienginevgui.h" #include "public/IGameUIFuncs.h" #include "public/dlight.h" #include "public/r_efx.h" #include "public/igameevents.h" #include "public/view_shared.h" #include "public/inetchannelinfo.h" #include "public/iachievementmgr.h" #include "public/steam/steam_api.h" #include "public/steam/isteamuserstats.h" #include "game/client/imessagechars.h" #include "game/client/iclientmode.h" #include "game/client/cliententitylist.h" #include "game/client/cdll_client_int.h" #include "game/client/cbase.h" #include "game/client/c_baseanimating.h" #include "game/client/c_basecombatweapon.h" #include "game/client/c_baseplayer.h" #include "game/client/enginesprite.h" #include "game/client/input.h" #include "game/client/c_playerresource.h" #include "game/client/c_baseplayer.h" #include "game/client/iviewrender.h" #include "game/client/viewrender.h" #include "game/client/game_controls/commandmenu.h" #include "game/client/hudelement.h" #include "public/engine/ivmodelrender.h" #include "public/engine/ivdebugoverlay.h" #include "public/engine/ivmodelinfo.h" #include "public/engine/IEngineTrace.h" #include "public/engine/IEngineSound.h" #include "public/materialsystem/imaterialsystemstub.h" #include "public/materialsystem/itexture.h" #include "public/materialsystem/IMaterialVar.h" #include "public/tier1/checksum_md5.h" #include "public/matsys_controls/matsyscontrols.h" #include "public/vgui/IClientPanel.h" #include "public/vgui/IPanel.h" #include "public/vgui/ISurface.h" #include "public/vgui/ILocalize.h" #include "public/collisionutils.h" #include "public/vstdlib/random.h" #include "public/vgui_controls/Panel.h" #include "public/VGuiMatSurface/IMatSystemSurface.h" #include "public/mathlib/vector.h" #include "game/shared/usermessages.h" #include "game/shared/basecombatweapon_shared.h" #include "game/shared/takedamageinfo.h" #include "game/shared/igamemovement.h" [/CODE]
[QUOTE=0V3RR1D3;51865084]Hey guys, so im making a module which I have done before but im using source sdk to access engine functions. One thing I wanted to try and do was to call functions on an entity but I seem to have hit a big brick wall. When ever I try to call functions from the CBaseEntity class I get a unresolved external symbol. I'm including every lib that comes with source sdk, and im including all the files I seem to need. I can call functions from IVEngineClient fine and they work and compile, but something like this does not [CODE] CBaseEntity* ent = (CBaseEntity*)GetClientEntityInterface()->GetClientEntity(GetEngineInterface()->GetLocalPlayer()); ent->SetAbsAngles(QAngle(1, 1, 1)); [/CODE] Ugly I know but that wont compile. If I comment/remove the bottom line (ent->) then it works fine. It seems that calling any functions from it results in a unresolved external symbol error. Any help will be appreciated, my includes are below. [CODE] *header snip* [/CODE][/QUOTE] In order to call a function, your program needs to know what memory address that function begins at. With Valve's interface classes (like IVEngineClient), all of the functions are virtual, which means the class stores a pointer to the functions in its vtable. The compiler will know to look in this vtable for the pointer to the function, and so it doesn't bother trying to find it. With CBaseEntity, many of its functions are not virtual, which means there is no pointer to them stored in the class vtable. This means that the compiler will try to find the function either somewhere in your own code, or in any *.lib files you are linking with. But, the compiler will never find it, as it exists in the client/server dlls (and they don't export it, so you can't force the compiler into making this work). This leaves you with 2 options. 1. Reverse-engineer the client/server binaries, obtain a 'signature' of the function, and use that signature to find the function at run-time instead of at compile-time. 2. Call the Lua binding of this function.
[QUOTE=Jcw87;51866966]In order to call a function, your program needs to know what memory address that function begins at. With Valve's interface classes (like IVEngineClient), all of the functions are virtual, which means the class stores a pointer to the functions in its vtable. The compiler will know to look in this vtable for the pointer to the function, and so it doesn't bother trying to find it. With CBaseEntity, many of its functions are not virtual, which means there is no pointer to them stored in the class vtable. This means that the compiler will try to find the function either somewhere in your own code, or in any *.lib files you are linking with. But, the compiler will never find it, as it exists in the client/server dlls (and they don't export it, so you can't force the compiler into making this work). This leaves you with 2 options. 1. Reverse-engineer the client/server binaries, obtain a 'signature' of the function, and use that signature to find the function at run-time instead of at compile-time. 2. Call the Lua binding of this function.[/QUOTE] Right, can you point me in the direction of some useful information on learning how to do this proccess? Thanks for your response.
[QUOTE=0V3RR1D3;51868116]Right, can you point me in the direction of some useful information on learning how to do this proccess? Thanks for your response.[/QUOTE] Literally exactly what I told you over steam that you must RE the function, and you stated that is not the case and that I was very wrong. Watch my youtube video on how to detour functions. Though like my bud @Jcw87 said sig scannings probably better due to GMod constantly updating. If I were you I'd watch my tutorial on how to detour, then sig scan it afterwards. Funny you ask me for help, say you know how to RE, but now you're asking for sources on how to RE.
it's not worth it; find a virtual function in another class if you can. If you can't then it will take a wildly steep learning curve to start even trying to find the right code.
[QUOTE=0V3RR1D3;51868116]Right, can you point me in the direction of some useful information on learning how to do this proccess? Thanks for your response.[/QUOTE] Well, for the reverse-engineering process, you are going to need a good disassembler/decompiler. The best one I know about is [url=https://www.hex-rays.com/products/ida/]IDA Pro[/url], but it's really expensive. Not only that, but actually being able to find the function can be really difficult. I wouldn't recommend attempting this unless you have a deep understanding of how C++ code is compiled. The much, much easier option is to call the Lua binding of the function. Since you mentioned that you have made modules before, I'll assume you are somewhat familiar with the Lua API. All you need to do is grab the appropriate function from Lua. Class functions are stored on the class metatable, and you can find the metatable by indexing the class name on the Lua registry table. When you call the function, make sure you pass the appropriate userdata as the first argument.
Sorry, you need to Log In to post a reply to this thread.