added new function calling module, wow
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40745
This commit is contained in:
parent
1205de4e67
commit
1592f77fc3
52
extensions/bintools/CallMaker.cpp
Normal file
52
extensions/bintools/CallMaker.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
|
||||||
|
* All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK. This file may only be
|
||||||
|
* used or modified under the Terms and Conditions of its License Agreement,
|
||||||
|
* which is found in public/licenses/LICENSE.txt. As of this notice, derivative
|
||||||
|
* works must be licensed under the GNU General Public License (version 2 or
|
||||||
|
* greater). A copy of the GPL is included under public/licenses/GPL.txt.
|
||||||
|
*
|
||||||
|
* To view the latest information, see: http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CallMaker.h"
|
||||||
|
#include "CallWrapper.h"
|
||||||
|
#include "jit_call.h"
|
||||||
|
|
||||||
|
ICallWrapper *CallMaker::CreateCall(void *address,
|
||||||
|
CallConvention cv,
|
||||||
|
const PassInfo *retInfo,
|
||||||
|
const PassInfo paramInfo[],
|
||||||
|
unsigned int numParams)
|
||||||
|
{
|
||||||
|
CallWrapper *pWrapper = new CallWrapper(cv, paramInfo, retInfo, numParams);
|
||||||
|
pWrapper->m_Addrs[ADDR_CALLEE] = address;
|
||||||
|
|
||||||
|
JIT_Compile(pWrapper, FuncAddr_Direct);
|
||||||
|
|
||||||
|
return pWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
ICallWrapper *CallMaker::CreateVCall(unsigned int vtblIdx,
|
||||||
|
unsigned int vtblOffs,
|
||||||
|
unsigned int thisOffs,
|
||||||
|
const PassInfo *retInfo,
|
||||||
|
const PassInfo paramInfo[],
|
||||||
|
unsigned int numParams)
|
||||||
|
{
|
||||||
|
CallWrapper *pWrapper = new CallWrapper(CallConv_ThisCall, paramInfo, retInfo, numParams);
|
||||||
|
pWrapper->m_VtInfo.thisOffs = thisOffs;
|
||||||
|
pWrapper->m_VtInfo.vtblIdx = vtblIdx;
|
||||||
|
pWrapper->m_VtInfo.vtblOffs = vtblOffs;
|
||||||
|
|
||||||
|
JIT_Compile(pWrapper, FuncAddr_VTable);
|
||||||
|
|
||||||
|
return pWrapper;
|
||||||
|
}
|
48
extensions/bintools/CallMaker.h
Normal file
48
extensions/bintools/CallMaker.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
|
||||||
|
* All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK. This file may only be
|
||||||
|
* used or modified under the Terms and Conditions of its License Agreement,
|
||||||
|
* which is found in public/licenses/LICENSE.txt. As of this notice, derivative
|
||||||
|
* works must be licensed under the GNU General Public License (version 2 or
|
||||||
|
* greater). A copy of the GPL is included under public/licenses/GPL.txt.
|
||||||
|
*
|
||||||
|
* To view the latest information, see: http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_CALLMAKER_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_CALLMAKER_H_
|
||||||
|
|
||||||
|
#include <IBinTools.h>
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
enum FuncAddrMethod
|
||||||
|
{
|
||||||
|
FuncAddr_Direct,
|
||||||
|
FuncAddr_VTable
|
||||||
|
};
|
||||||
|
|
||||||
|
class CallMaker : public IBinTools
|
||||||
|
{
|
||||||
|
public: //IBinTools
|
||||||
|
ICallWrapper *CreateCall(void *address,
|
||||||
|
CallConvention cv,
|
||||||
|
const PassInfo *retInfo,
|
||||||
|
const PassInfo paramInfo[],
|
||||||
|
unsigned int numParams);
|
||||||
|
ICallWrapper *CreateVCall(unsigned int vtblIdx,
|
||||||
|
unsigned int vtblOffs,
|
||||||
|
unsigned int thisOffs,
|
||||||
|
const PassInfo *retInfo,
|
||||||
|
const PassInfo paramInfo[],
|
||||||
|
unsigned int numParams);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_CALLMAKER_H_
|
91
extensions/bintools/CallWrapper.cpp
Normal file
91
extensions/bintools/CallWrapper.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
|
||||||
|
* All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK. This file may only be
|
||||||
|
* used or modified under the Terms and Conditions of its License Agreement,
|
||||||
|
* which is found in public/licenses/LICENSE.txt. As of this notice, derivative
|
||||||
|
* works must be licensed under the GNU General Public License (version 2 or
|
||||||
|
* greater). A copy of the GPL is included under public/licenses/GPL.txt.
|
||||||
|
*
|
||||||
|
* To view the latest information, see: http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "extension.h"
|
||||||
|
#include "CallWrapper.h"
|
||||||
|
|
||||||
|
CallWrapper::CallWrapper(CallConvention cv, const PassInfo *paramInfo, const PassInfo *retInfo, unsigned int numParams)
|
||||||
|
{
|
||||||
|
m_Cv = cv;
|
||||||
|
|
||||||
|
if (numParams)
|
||||||
|
{
|
||||||
|
m_Params = new PassEncode[numParams];
|
||||||
|
for (size_t i=0; i<numParams; i++)
|
||||||
|
{
|
||||||
|
m_Params[i].info = paramInfo[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retInfo)
|
||||||
|
{
|
||||||
|
m_RetParam = new PassInfo;
|
||||||
|
*m_RetParam = *retInfo;
|
||||||
|
} else {
|
||||||
|
m_RetParam = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_NumParams = numParams;
|
||||||
|
|
||||||
|
/* Calculate virtual stack offsets for each parameter */
|
||||||
|
size_t offs = 0;
|
||||||
|
|
||||||
|
if (cv == CallConv_ThisCall)
|
||||||
|
{
|
||||||
|
offs += sizeof(void *);
|
||||||
|
}
|
||||||
|
for (size_t i=0; i<numParams; i++)
|
||||||
|
{
|
||||||
|
m_Params[i].offset = offs;
|
||||||
|
offs += m_Params[i].info.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CallWrapper::~CallWrapper()
|
||||||
|
{
|
||||||
|
delete [] m_Params;
|
||||||
|
delete m_RetParam;
|
||||||
|
g_SPEngine->ExecFree(m_Addrs[ADDR_CODEBASE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
CallConvention CallWrapper::GetCallConvention()
|
||||||
|
{
|
||||||
|
return m_Cv;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PassEncode *CallWrapper::GetParamInfo(unsigned int num)
|
||||||
|
{
|
||||||
|
return (num+1 > m_NumParams) ? NULL : &m_Params[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
const PassInfo *CallWrapper::GetReturnInfo()
|
||||||
|
{
|
||||||
|
return m_RetParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CallWrapper::GetParamCount()
|
||||||
|
{
|
||||||
|
return m_NumParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallWrapper::Execute(void *vParamStack, void *retBuffer)
|
||||||
|
{
|
||||||
|
typedef void (*CALL_EXECUTE)(void *, void *);
|
||||||
|
CALL_EXECUTE fn = (CALL_EXECUTE)m_Addrs[ADDR_CODEBASE];
|
||||||
|
fn(vParamStack, retBuffer);
|
||||||
|
}
|
58
extensions/bintools/CallWrapper.h
Normal file
58
extensions/bintools/CallWrapper.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
|
||||||
|
* All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK. This file may only be
|
||||||
|
* used or modified under the Terms and Conditions of its License Agreement,
|
||||||
|
* which is found in public/licenses/LICENSE.txt. As of this notice, derivative
|
||||||
|
* works must be licensed under the GNU General Public License (version 2 or
|
||||||
|
* greater). A copy of the GPL is included under public/licenses/GPL.txt.
|
||||||
|
*
|
||||||
|
* To view the latest information, see: http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_CCALLWRAPPER_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_CCALLWRAPPER_H_
|
||||||
|
|
||||||
|
#include <IBinTools.h>
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
#define ADDR_CALLEE 0
|
||||||
|
#define ADDR_CODEBASE 1
|
||||||
|
|
||||||
|
struct VtableInfo
|
||||||
|
{
|
||||||
|
unsigned int vtblIdx;
|
||||||
|
unsigned int vtblOffs;
|
||||||
|
unsigned int thisOffs;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CallWrapper : public ICallWrapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CallWrapper(CallConvention cv, const PassInfo *paramInfo, const PassInfo *retInfo, unsigned int numParams);
|
||||||
|
~CallWrapper();
|
||||||
|
public: //ICallWrapper
|
||||||
|
CallConvention GetCallConvention();
|
||||||
|
const PassEncode *GetParamInfo(unsigned int num);
|
||||||
|
const PassInfo *GetReturnInfo();
|
||||||
|
unsigned int GetParamCount();
|
||||||
|
void Execute(void *vParamStack, void *retBuffer);
|
||||||
|
public:
|
||||||
|
inline void deleteThis() { delete this; }
|
||||||
|
void *m_Addrs[4];
|
||||||
|
VtableInfo m_VtInfo;
|
||||||
|
private:
|
||||||
|
CallConvention m_Cv;
|
||||||
|
PassEncode *m_Params;
|
||||||
|
PassInfo *m_RetParam;
|
||||||
|
unsigned int m_NumParams;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_CCALLWRAPPER_H_
|
87
extensions/bintools/Makefile
Normal file
87
extensions/bintools/Makefile
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#(C)2004-2006 SourceMM Development Team
|
||||||
|
# Makefile written by David "BAILOPAN" Anderson
|
||||||
|
|
||||||
|
SMSDK = ../..
|
||||||
|
SRCDS = ~/srcds
|
||||||
|
SOURCEMM = ../../../../sourcemm
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
PROJECT = sample
|
||||||
|
|
||||||
|
#Uncomment for SourceMM-enabled extensions
|
||||||
|
#LINK_HL2 = $(HL2LIB)/tier1_i486.a vstdlib_i486.so tier0_i486.so
|
||||||
|
|
||||||
|
OBJECTS = extension.cpp smsdk_ext.cpp
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
||||||
|
##############################################
|
||||||
|
|
||||||
|
C_OPT_FLAGS = -O3 -funroll-loops -s -pipe -fno-strict-aliasing
|
||||||
|
C_DEBUG_FLAGS = -g -ggdb3
|
||||||
|
CPP_GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden
|
||||||
|
CPP = gcc-4.1
|
||||||
|
|
||||||
|
HL2PUB = $(HL2SDK)/public
|
||||||
|
HL2LIB = $(HL2SDK)/linux_sdk
|
||||||
|
HL2SDK = $(SOURCEMM)/hl2sdk
|
||||||
|
SMM_TRUNK = $(SOURCEMM)/trunk
|
||||||
|
|
||||||
|
LINK = $(LINK_HL2) -static-libgcc
|
||||||
|
|
||||||
|
INCLUDE = -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/dlls -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \
|
||||||
|
-I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I$(SMM_TRUNK) -I$(SMM_TRUNK)/sourcehook -I$(SMM_TRUNK)/sourcemm \
|
||||||
|
-I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SMSDK)/public/extensions \
|
||||||
|
|
||||||
|
CFLAGS = -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror -fPIC -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H
|
||||||
|
CPPFLAGS = -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
################################################
|
||||||
|
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
|
||||||
|
################################################
|
||||||
|
|
||||||
|
ifeq "$(DEBUG)" "true"
|
||||||
|
BIN_DIR = Debug
|
||||||
|
CFLAGS += $(C_DEBUG_FLAGS)
|
||||||
|
else
|
||||||
|
BIN_DIR = Release
|
||||||
|
CFLAGS += $(C_OPT_FLAGS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
||||||
|
ifeq "$(GCC_VERSION)" "4"
|
||||||
|
CPPFLAGS += $(CPP_GCC4_FLAGS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
BINARY = $(PROJECT).ext.so
|
||||||
|
|
||||||
|
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||||
|
|
||||||
|
$(BIN_DIR)/%.o: %.cpp
|
||||||
|
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
all:
|
||||||
|
mkdir -p $(BIN_DIR)
|
||||||
|
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so
|
||||||
|
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so
|
||||||
|
$(MAKE) extension
|
||||||
|
rm -rf $(BINARY)
|
||||||
|
|
||||||
|
extension: $(OBJ_LINUX)
|
||||||
|
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
||||||
|
|
||||||
|
debug:
|
||||||
|
$(MAKE) all DEBUG=true
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf Release/*.o
|
||||||
|
rm -rf Release/$(BINARY)
|
||||||
|
rm -rf Debug/*.o
|
||||||
|
rm -rf Debug/$(BINARY)
|
||||||
|
|
39
extensions/bintools/extension.cpp
Normal file
39
extensions/bintools/extension.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
|
||||||
|
* All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK. This file may only be
|
||||||
|
* used or modified under the Terms and Conditions of its License Agreement,
|
||||||
|
* which is found in public/licenses/LICENSE.txt. As of this notice, derivative
|
||||||
|
* works must be licensed under the GNU General Public License (version 2 or
|
||||||
|
* greater). A copy of the GPL is included under public/licenses/GPL.txt.
|
||||||
|
*
|
||||||
|
* To view the latest information, see: http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "extension.h"
|
||||||
|
#include "CallMaker.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file extension.cpp
|
||||||
|
* @brief Implement extension code here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
BinTools g_BinTools; /**< Global singleton for your extension's main interface */
|
||||||
|
CallMaker g_CallMaker;
|
||||||
|
ISourcePawnEngine *g_SPEngine;
|
||||||
|
|
||||||
|
SMEXT_LINK(&g_BinTools);
|
||||||
|
|
||||||
|
bool BinTools::SDK_OnLoad(char *error, size_t err_max, bool late)
|
||||||
|
{
|
||||||
|
g_SPEngine = g_pSM->GetScriptingEngine();
|
||||||
|
g_pShareSys->AddInterface(myself, &g_CallMaker);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
86
extensions/bintools/extension.h
Normal file
86
extensions/bintools/extension.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
|
||||||
|
* All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK. This file may only be
|
||||||
|
* used or modified under the Terms and Conditions of its License Agreement,
|
||||||
|
* which is found in public/licenses/LICENSE.txt. As of this notice, derivative
|
||||||
|
* works must be licensed under the GNU General Public License (version 2 or
|
||||||
|
* greater). A copy of the GPL is included under public/licenses/GPL.txt.
|
||||||
|
*
|
||||||
|
* To view the latest information, see: http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file extension.h
|
||||||
|
* @brief Sample extension code header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "smsdk_ext.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sample implementation of the SDK Extension.
|
||||||
|
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
|
||||||
|
*/
|
||||||
|
class BinTools : public SDKExtension
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief This is called after the initial loading sequence has been processed.
|
||||||
|
*
|
||||||
|
* @param error Error message buffer.
|
||||||
|
* @param err_max Size of error message buffer.
|
||||||
|
* @param late Whether or not the module was loaded after map load.
|
||||||
|
* @return True to succeed loading, false to fail.
|
||||||
|
*/
|
||||||
|
virtual bool SDK_OnLoad(char *error, size_t err_max, bool late);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This is called right before the extension is unloaded.
|
||||||
|
*/
|
||||||
|
//virtual void SDK_OnUnload();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This is called once all known extensions have been loaded.
|
||||||
|
* Note: It is is a good idea to add natives here, if any are provided.
|
||||||
|
*/
|
||||||
|
//virtual void SDK_OnAllLoaded();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when the pause state is changed.
|
||||||
|
*/
|
||||||
|
//virtual void SDK_OnPauseChange(bool paused);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief this is called when Core wants to know if your extension is working.
|
||||||
|
*
|
||||||
|
* @param error Error message buffer.
|
||||||
|
* @param err_max Size of error message buffer.
|
||||||
|
* @return True if working, false otherwise.
|
||||||
|
*/
|
||||||
|
//virtual void QueryRunning(char *error, size_t maxlength);
|
||||||
|
public:
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
/**
|
||||||
|
* Read smext_base.h for documentation on these.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late);
|
||||||
|
//virtual bool SDK_OnMetamodUnload(char *error, size_t err_max);
|
||||||
|
//virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t err_max);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ISourcePawnEngine *g_SPEngine;
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
609
extensions/bintools/jit_call.cpp
Normal file
609
extensions/bintools/jit_call.cpp
Normal file
@ -0,0 +1,609 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
|
||||||
|
* All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK. This file may only be
|
||||||
|
* used or modified under the Terms and Conditions of its License Agreement,
|
||||||
|
* which is found in public/licenses/LICENSE.txt. As of this notice, derivative
|
||||||
|
* works must be licensed under the GNU General Public License (version 2 or
|
||||||
|
* greater). A copy of the GPL is included under public/licenses/GPL.txt.
|
||||||
|
*
|
||||||
|
* To view the latest information, see: http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sm_platform.h>
|
||||||
|
#include "extension.h"
|
||||||
|
#include <jit_helpers.h>
|
||||||
|
#include <x86_macros.h>
|
||||||
|
#include "jit_call.h"
|
||||||
|
|
||||||
|
jit_uint32_t g_StackUsage = 0;
|
||||||
|
jit_uint32_t g_RegDecoder = 0;
|
||||||
|
|
||||||
|
/********************
|
||||||
|
* Assembly Helpers *
|
||||||
|
********************/
|
||||||
|
|
||||||
|
inline jit_uint8_t _DecodeRegister3(jit_uint32_t val)
|
||||||
|
{
|
||||||
|
switch (val % 3)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
return REG_EAX;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
return REG_EDX;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
return REG_ECX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should never happen */
|
||||||
|
return 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************
|
||||||
|
* Assembly Opcodes *
|
||||||
|
********************/
|
||||||
|
|
||||||
|
inline void Write_Execution_Prologue(JitWriter *jit, bool is_void, bool has_params)
|
||||||
|
{
|
||||||
|
//push ebp
|
||||||
|
//mov ebp, esp
|
||||||
|
//if !is_void
|
||||||
|
// push edi
|
||||||
|
// mov edi, [ebp+12]
|
||||||
|
//if has_params
|
||||||
|
// push ebx
|
||||||
|
// mov ebx, [ebp+8]
|
||||||
|
IA32_Push_Reg(jit, REG_EBP);
|
||||||
|
IA32_Mov_Reg_Rm(jit, REG_EBP, REG_ESP, MOD_REG);
|
||||||
|
if (!is_void)
|
||||||
|
{
|
||||||
|
IA32_Push_Reg(jit, REG_EDI);
|
||||||
|
IA32_Mov_Reg_Rm_Disp8(jit, REG_EDI, REG_EBP, 12);
|
||||||
|
}
|
||||||
|
if (has_params)
|
||||||
|
{
|
||||||
|
IA32_Push_Reg(jit, REG_EBX);
|
||||||
|
IA32_Mov_Reg_Rm_Disp8(jit, REG_EBX, REG_EBP, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Write_Function_Epilogue(JitWriter *jit, bool is_void, bool has_params)
|
||||||
|
{
|
||||||
|
//if has_params
|
||||||
|
// pop ebx
|
||||||
|
//if !is_void
|
||||||
|
// pop edi
|
||||||
|
//mov esp, ebp
|
||||||
|
//pop ebp
|
||||||
|
//ret
|
||||||
|
if (has_params)
|
||||||
|
{
|
||||||
|
IA32_Pop_Reg(jit, REG_EBX);
|
||||||
|
}
|
||||||
|
if (!is_void)
|
||||||
|
{
|
||||||
|
IA32_Pop_Reg(jit, REG_EDI);
|
||||||
|
}
|
||||||
|
IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBP, MOD_REG);
|
||||||
|
IA32_Pop_Reg(jit, REG_EBP);
|
||||||
|
IA32_Return(jit);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Write_PushPOD(JitWriter *jit, const PassEncode *pEnc)
|
||||||
|
{
|
||||||
|
jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++);
|
||||||
|
|
||||||
|
if (pEnc->info.flags & PASSFLAG_BYVAL)
|
||||||
|
{
|
||||||
|
switch (pEnc->info.size)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
//xor reg, reg
|
||||||
|
//mov reg, BYTE PTR [ebx+<offset>]
|
||||||
|
//push reg
|
||||||
|
IA32_Xor_Reg_Rm(jit, reg, reg, MOD_REG);
|
||||||
|
if (pEnc->offset < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Mov_Reg8_Rm8_Disp8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
|
||||||
|
} else if (!pEnc->offset) {
|
||||||
|
IA32_Mov_Reg8_Rm8(jit, reg, REG_EBX, MOD_MEM_REG);
|
||||||
|
} else {
|
||||||
|
IA32_Mov_Reg8_Rm8_Disp32(jit, reg, REG_EBX, pEnc->offset);
|
||||||
|
}
|
||||||
|
IA32_Push_Reg(jit, reg);
|
||||||
|
|
||||||
|
g_StackUsage += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
//xor reg, reg
|
||||||
|
//mov reg, WORD PTR [ebx+<offset>]
|
||||||
|
//push reg
|
||||||
|
IA32_Xor_Reg_Rm(jit, reg, reg, MOD_REG);
|
||||||
|
jit->write_ubyte(IA32_16BIT_PREFIX);
|
||||||
|
if (pEnc->offset < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Mov_Reg_Rm_Disp8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
|
||||||
|
} else if (!pEnc->offset) {
|
||||||
|
IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG);
|
||||||
|
} else {
|
||||||
|
IA32_Mov_Reg_Rm_Disp32(jit, reg, REG_EBX, pEnc->offset);
|
||||||
|
}
|
||||||
|
IA32_Push_Reg(jit, reg);
|
||||||
|
|
||||||
|
g_StackUsage += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
//mov reg, DWORD PTR [ebx+<offset>]
|
||||||
|
//push reg
|
||||||
|
if (pEnc->offset < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Mov_Reg_Rm_Disp8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
|
||||||
|
} else if (!pEnc->offset) {
|
||||||
|
IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG);
|
||||||
|
} else {
|
||||||
|
IA32_Mov_Reg_Rm_Disp32(jit, reg, REG_EBX, pEnc->offset);
|
||||||
|
}
|
||||||
|
IA32_Push_Reg(jit, reg);
|
||||||
|
|
||||||
|
g_StackUsage += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
//mov reg, DWORD PTR [ebx+<offset>+4]
|
||||||
|
//mov reg2, DWORD PTR [ebx+<offset>]
|
||||||
|
//push reg
|
||||||
|
//push reg2
|
||||||
|
jit_uint8_t reg2 = _DecodeRegister3(g_RegDecoder++);
|
||||||
|
|
||||||
|
if (pEnc->offset+4 < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Mov_Reg_Rm_Disp8(jit, reg, REG_EBX, (jit_int8_t)(pEnc->offset+4));
|
||||||
|
} else {
|
||||||
|
IA32_Mov_Reg_Rm_Disp32(jit, reg, REG_EBX, pEnc->offset+4);
|
||||||
|
}
|
||||||
|
if (pEnc->offset < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Mov_Reg_Rm_Disp8(jit, reg2, REG_EBX, (jit_int8_t)pEnc->offset);
|
||||||
|
} else if (!pEnc->offset) {
|
||||||
|
IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG);
|
||||||
|
} else {
|
||||||
|
IA32_Mov_Reg_Rm_Disp32(jit, reg2, REG_EBX, pEnc->offset);
|
||||||
|
}
|
||||||
|
IA32_Push_Reg(jit, reg);
|
||||||
|
IA32_Push_Reg(jit, reg2);
|
||||||
|
|
||||||
|
g_StackUsage += 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (pEnc->info.flags & PASSFLAG_BYREF) {
|
||||||
|
//lea reg, [ebx+<offset>]
|
||||||
|
//push reg
|
||||||
|
if (!pEnc->offset)
|
||||||
|
{
|
||||||
|
IA32_Push_Reg(jit, REG_EBX);
|
||||||
|
g_StackUsage += 4;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pEnc->offset < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Lea_DispRegImm8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
|
||||||
|
} else {
|
||||||
|
IA32_Lea_DispRegImm32(jit, reg, REG_EBX, pEnc->offset);
|
||||||
|
}
|
||||||
|
IA32_Push_Reg(jit, reg);
|
||||||
|
|
||||||
|
g_StackUsage += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Write_PushFloat(JitWriter *jit, const PassEncode *pEnc)
|
||||||
|
{
|
||||||
|
if (pEnc->info.flags & PASSFLAG_BYVAL)
|
||||||
|
{
|
||||||
|
switch (pEnc->info.size)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
//fld DWORD PTR [ebx+<offset>]
|
||||||
|
//push reg
|
||||||
|
//fstp DWORD PTR [esp]
|
||||||
|
if (pEnc->offset < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Fld_Mem32_Disp8(jit, REG_EBX, (jit_int8_t)pEnc->offset);
|
||||||
|
} else {
|
||||||
|
IA32_Fld_Mem32_Disp32(jit, REG_EBX, pEnc->offset);
|
||||||
|
}
|
||||||
|
IA32_Push_Reg(jit, _DecodeRegister3(g_RegDecoder++));
|
||||||
|
IA32_Fstp_Mem32(jit, REG_ESP, REG_NOIDX, NOSCALE);
|
||||||
|
g_StackUsage += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
//fld QWORD PTR [ebx+<offset>]
|
||||||
|
//sub esp, 8
|
||||||
|
//fstp QWORD PTR [esp]
|
||||||
|
if (pEnc->offset < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Fld_Mem64_Disp8(jit, REG_EBX, (jit_int8_t)pEnc->offset);
|
||||||
|
} else {
|
||||||
|
IA32_Fld_Mem64_Disp32(jit, REG_EBX, pEnc->offset);
|
||||||
|
}
|
||||||
|
IA32_Sub_Rm_Imm8(jit, REG_ESP, 8, MOD_REG);
|
||||||
|
IA32_Fstp_Mem64(jit, REG_ESP, REG_NOIDX, NOSCALE);
|
||||||
|
g_StackUsage += 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (pEnc->info.flags & PASSFLAG_BYREF) {
|
||||||
|
//lea reg, [ebx+<offset>]
|
||||||
|
//push reg
|
||||||
|
if (!pEnc->offset)
|
||||||
|
{
|
||||||
|
IA32_Push_Reg(jit, REG_EBX);
|
||||||
|
g_StackUsage += 4;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++);
|
||||||
|
if (pEnc->offset < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Lea_DispRegImm8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
|
||||||
|
} else {
|
||||||
|
IA32_Lea_DispRegImm32(jit, reg, REG_EBX, pEnc->offset);
|
||||||
|
}
|
||||||
|
IA32_Push_Reg(jit, reg);
|
||||||
|
|
||||||
|
g_StackUsage += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Write_PushObject(JitWriter *jit, const PassEncode *pEnc)
|
||||||
|
{
|
||||||
|
if (pEnc->info.flags & PASSFLAG_BYVAL)
|
||||||
|
{
|
||||||
|
#ifdef PLATFORM_POSIX
|
||||||
|
if (pEnc->info.flags & PASSFLAG_ODTOR)
|
||||||
|
{
|
||||||
|
goto push_byref;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
jit_uint32_t dwords = pEnc->info.size >> 2;
|
||||||
|
jit_uint32_t bytes = pEnc->info.size & 0x3;
|
||||||
|
|
||||||
|
//sub esp, <size>
|
||||||
|
//cld
|
||||||
|
//push edi
|
||||||
|
//push esi
|
||||||
|
//lea edi, [esp+8]
|
||||||
|
//lea esi, [ebx+<offs>]
|
||||||
|
//if dwords
|
||||||
|
// mov ecx, <dwords>
|
||||||
|
// rep movsd
|
||||||
|
//if bytes
|
||||||
|
// mov ecx, <bytes>
|
||||||
|
// rep movsb
|
||||||
|
//pop esi
|
||||||
|
//pop edi
|
||||||
|
if (pEnc->info.size < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Sub_Rm_Imm8(jit, REG_ESP, (jit_int8_t)pEnc->info.size, MOD_REG);
|
||||||
|
} else {
|
||||||
|
IA32_Sub_Rm_Imm32(jit, REG_ESP, pEnc->info.size, MOD_REG);
|
||||||
|
}
|
||||||
|
IA32_Cld(jit);
|
||||||
|
IA32_Push_Reg(jit, REG_EDI);
|
||||||
|
IA32_Push_Reg(jit, REG_ESI);
|
||||||
|
IA32_Lea_Reg_DispRegMultImm8(jit, REG_EDI, REG_NOIDX, REG_ESP, NOSCALE, 8);
|
||||||
|
if (pEnc->offset < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Lea_DispRegImm8(jit, REG_ESI, REG_EBX, (jit_int8_t)pEnc->offset);
|
||||||
|
} else if (!pEnc->offset) {
|
||||||
|
IA32_Mov_Reg_Rm(jit, REG_ESI, REG_EBX, MOD_REG);
|
||||||
|
} else {
|
||||||
|
IA32_Lea_DispRegImm32(jit, REG_ESI, REG_EBX, pEnc->offset);
|
||||||
|
}
|
||||||
|
if (dwords)
|
||||||
|
{
|
||||||
|
IA32_Mov_Reg_Imm32(jit, REG_ECX, dwords);
|
||||||
|
IA32_Rep(jit);
|
||||||
|
IA32_Movsd(jit);
|
||||||
|
}
|
||||||
|
if (bytes)
|
||||||
|
{
|
||||||
|
IA32_Mov_Reg_Imm32(jit, REG_ECX, bytes);
|
||||||
|
IA32_Rep(jit);
|
||||||
|
IA32_Movsb(jit);
|
||||||
|
}
|
||||||
|
IA32_Pop_Reg(jit, REG_ESI);
|
||||||
|
IA32_Pop_Reg(jit, REG_EDI);
|
||||||
|
|
||||||
|
g_StackUsage += pEnc->info.size;
|
||||||
|
} else if (pEnc->info.flags & PASSFLAG_BYREF) {
|
||||||
|
#ifdef PLATFORM_POSIX
|
||||||
|
push_byref:
|
||||||
|
#endif
|
||||||
|
if (!pEnc->offset)
|
||||||
|
{
|
||||||
|
IA32_Push_Reg(jit, REG_EBX);
|
||||||
|
g_StackUsage += 4;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//lea reg, [ebx+<offset>]
|
||||||
|
//push reg
|
||||||
|
jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++);
|
||||||
|
if (pEnc->offset < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Lea_DispRegImm8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
|
||||||
|
} else {
|
||||||
|
IA32_Lea_DispRegImm32(jit, reg, REG_EBX, pEnc->offset);
|
||||||
|
}
|
||||||
|
IA32_Push_Reg(jit, reg);
|
||||||
|
|
||||||
|
g_StackUsage += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Write_PushThisPtr(JitWriter *jit)
|
||||||
|
{
|
||||||
|
#ifdef PLATFORM_POSIX
|
||||||
|
//mov reg, [ebx]
|
||||||
|
//push reg
|
||||||
|
jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++);
|
||||||
|
|
||||||
|
IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG);
|
||||||
|
IA32_Push_Reg(jit, reg);
|
||||||
|
|
||||||
|
g_StackUsage += 4;
|
||||||
|
#elif defined PLATFORM_WINDOWS
|
||||||
|
//mov ecx, [ebx]
|
||||||
|
IA32_Mov_Reg_Rm(jit, REG_ECX, REG_EBX, MOD_MEM_REG);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Write_PushRetBuffer(JitWriter *jit)
|
||||||
|
{
|
||||||
|
//push edi
|
||||||
|
IA32_Push_Reg(jit, REG_EDI);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Write_CallFunction(JitWriter *jit, FuncAddrMethod method, CallWrapper *pWrapper)
|
||||||
|
{
|
||||||
|
if (method == FuncAddr_Direct)
|
||||||
|
{
|
||||||
|
//call <addr>
|
||||||
|
jitoffs_t call = IA32_Call_Imm32(jit, 0);
|
||||||
|
IA32_Write_Jump32_Abs(jit, call, pWrapper->m_Addrs[ADDR_CALLEE]);
|
||||||
|
} else if (method == FuncAddr_VTable) {
|
||||||
|
//*(this + thisOffs + vtblOffs)[vtblIdx]
|
||||||
|
//mov edx, [ebx]
|
||||||
|
//mov eax, [edx+<thisOffs>+<vtblOffs>]
|
||||||
|
//mov edx, [eax+<vtblIdx>*4]
|
||||||
|
//call edx
|
||||||
|
jit_uint32_t total_offs = pWrapper->m_VtInfo.thisOffs + pWrapper->m_VtInfo.vtblOffs;
|
||||||
|
jit_uint32_t vfunc_pos = pWrapper->m_VtInfo.vtblIdx * 4;
|
||||||
|
|
||||||
|
IA32_Mov_Reg_Rm(jit, REG_EDX, REG_EBX, MOD_MEM_REG);
|
||||||
|
if (total_offs < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EDX, (jit_int8_t)total_offs);
|
||||||
|
} else if (!total_offs) {
|
||||||
|
IA32_Mov_Reg_Rm(jit, REG_EAX, REG_EDX, MOD_MEM_REG);
|
||||||
|
} else {
|
||||||
|
IA32_Mov_Reg_Rm_Disp32(jit, REG_EAX, REG_EDX, total_offs);
|
||||||
|
}
|
||||||
|
if (vfunc_pos < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, (jit_int8_t)vfunc_pos);
|
||||||
|
} else if (!vfunc_pos) {
|
||||||
|
IA32_Mov_Reg_Rm(jit, REG_EDX, REG_EAX, MOD_MEM_REG);
|
||||||
|
} else {
|
||||||
|
IA32_Mov_Reg_Rm_Disp32(jit, REG_EDX, REG_EAX, vfunc_pos);
|
||||||
|
}
|
||||||
|
IA32_Call_Reg(jit, REG_EDX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Write_RectifyStack(JitWriter *jit, jit_uint32_t value)
|
||||||
|
{
|
||||||
|
//add esp, <value>
|
||||||
|
if (value < SCHAR_MAX)
|
||||||
|
{
|
||||||
|
IA32_Add_Rm_Imm8(jit, REG_ESP, (jit_int8_t)value, MOD_REG);
|
||||||
|
} else {
|
||||||
|
IA32_Add_Rm_Imm32(jit, REG_ESP, value, MOD_REG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Write_MovRet2Buf(JitWriter *jit, const PassInfo *pRet)
|
||||||
|
{
|
||||||
|
if (pRet->type == PassType_Float)
|
||||||
|
{
|
||||||
|
switch (pRet->size)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
//fstp DWORD PTR [edi]
|
||||||
|
IA32_Fstp_Mem32(jit, REG_EDI, REG_NOIDX, NOSCALE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
//fstp QWORD PTR [edi]
|
||||||
|
IA32_Fstp_Mem64(jit, REG_EDI, REG_NOIDX, NOSCALE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (pRet->size)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
//mov BYTE PTR [edi], al
|
||||||
|
IA32_Mov_Rm8_Reg8(jit, REG_EDI, REG_EAX, MOD_MEM_REG);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
//mov WORD PTR [edi], ax
|
||||||
|
jit->write_ubyte(IA32_16BIT_PREFIX);
|
||||||
|
IA32_Mov_Rm_Reg(jit, REG_EDI, REG_EAX, MOD_MEM_REG);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
//mov DWORD PTR [edi], eax
|
||||||
|
IA32_Mov_Rm_Reg(jit, REG_EDI, REG_EAX, MOD_MEM_REG);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
//mov DWORD PTR [edi], eax
|
||||||
|
//mov DWORD PTR [edi+4], edx
|
||||||
|
IA32_Mov_Rm_Reg(jit, REG_EDI, REG_EAX, MOD_MEM_REG);
|
||||||
|
IA32_Mov_Rm_Reg_Disp8(jit, REG_EDI, REG_EDX, 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* Assembly Compiler Function *
|
||||||
|
******************************/
|
||||||
|
|
||||||
|
void JIT_Compile(CallWrapper *pWrapper, FuncAddrMethod method)
|
||||||
|
{
|
||||||
|
JitWriter writer;
|
||||||
|
JitWriter *jit = &writer;
|
||||||
|
|
||||||
|
jit_uint32_t CodeSize = 0;
|
||||||
|
bool Needs_Retbuf = false;
|
||||||
|
CallConvention Convention = pWrapper->GetCallConvention();
|
||||||
|
jit_uint32_t ParamCount = pWrapper->GetParamCount();
|
||||||
|
const PassInfo *pRet = pWrapper->GetReturnInfo();
|
||||||
|
|
||||||
|
writer.outbase = NULL;
|
||||||
|
writer.outptr = NULL;
|
||||||
|
|
||||||
|
jit_rewind:
|
||||||
|
/* Write function prologue */
|
||||||
|
Write_Execution_Prologue(jit, (pRet) ? false : true, (ParamCount) ? true : false);
|
||||||
|
|
||||||
|
/* Write parameter push code */
|
||||||
|
for (jit_int32_t i=ParamCount-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
const PassEncode *pEnc = pWrapper->GetParamInfo(i);
|
||||||
|
switch (pEnc->info.type)
|
||||||
|
{
|
||||||
|
case PassType_Basic:
|
||||||
|
{
|
||||||
|
Write_PushPOD(jit, pEnc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PassType_Float:
|
||||||
|
{
|
||||||
|
Write_PushFloat(jit, pEnc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PassType_Object:
|
||||||
|
{
|
||||||
|
Write_PushObject(jit, pEnc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare the this ptr if applicable */
|
||||||
|
if (Convention == CallConv_ThisCall)
|
||||||
|
{
|
||||||
|
Write_PushThisPtr(jit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip the return buffer stuff if this is a void function */
|
||||||
|
if (!pRet)
|
||||||
|
{
|
||||||
|
goto skip_retbuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pRet->type == PassType_Object) && (pRet->flags & PASSFLAG_BYVAL))
|
||||||
|
{
|
||||||
|
#ifdef PLATFORM_POSIX
|
||||||
|
Needs_Retbuf = true;
|
||||||
|
#elif defined PLATFORM_WINDOWS
|
||||||
|
if ((Convention == CallConv_ThisCall) ||
|
||||||
|
((Convention == CallConv_Cdecl) &&
|
||||||
|
((pRet->size > 8) || (pRet->flags & PASSFLAG_ODTOR|PASSFLAG_OCTOR|PASSFLAG_OASSIGNOP))))
|
||||||
|
{
|
||||||
|
Needs_Retbuf = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare the return buffer in case we are returning objects by value. */
|
||||||
|
if (Needs_Retbuf)
|
||||||
|
{
|
||||||
|
Write_PushRetBuffer(jit);
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_retbuffer:
|
||||||
|
/* Write the calling code */
|
||||||
|
Write_CallFunction(jit, method, pWrapper);
|
||||||
|
|
||||||
|
/* Clean up the calling stack */
|
||||||
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
if ((ParamCount || Needs_Retbuf) && (Convention == CallConv_Cdecl))
|
||||||
|
{
|
||||||
|
/* Pop all parameters from the stack + hidden return pointer */
|
||||||
|
jit_uint32_t total = (Needs_Retbuf) ? g_StackUsage + sizeof(void *) : g_StackUsage;
|
||||||
|
Write_RectifyStack(jit, total);
|
||||||
|
#elif defined PLATFORM_POSIX
|
||||||
|
if (ParamCount)
|
||||||
|
{
|
||||||
|
/* Pop all parameters from the stack */
|
||||||
|
Write_RectifyStack(jit, g_StackUsage);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the return type to the return buffer if the function is not void */
|
||||||
|
if (pRet && !Needs_Retbuf)
|
||||||
|
{
|
||||||
|
Write_MovRet2Buf(jit, pRet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write Function Epilogue */
|
||||||
|
Write_Function_Epilogue(jit, (pRet) ? false : true, (ParamCount) ? true : false);
|
||||||
|
|
||||||
|
if (writer.outbase == NULL)
|
||||||
|
{
|
||||||
|
CodeSize = writer.get_outputpos();
|
||||||
|
writer.outbase = (jitcode_t)g_SPEngine->ExecAlloc(CodeSize);
|
||||||
|
writer.outptr = writer.outbase;
|
||||||
|
pWrapper->m_Addrs[ADDR_CODEBASE] = writer.outbase;
|
||||||
|
g_StackUsage = 0;
|
||||||
|
g_RegDecoder = 0;
|
||||||
|
Needs_Retbuf = false;
|
||||||
|
goto jit_rewind;
|
||||||
|
}
|
||||||
|
}
|
27
extensions/bintools/jit_call.h
Normal file
27
extensions/bintools/jit_call.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
|
||||||
|
* All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK. This file may only be
|
||||||
|
* used or modified under the Terms and Conditions of its License Agreement,
|
||||||
|
* which is found in public/licenses/LICENSE.txt. As of this notice, derivative
|
||||||
|
* works must be licensed under the GNU General Public License (version 2 or
|
||||||
|
* greater). A copy of the GPL is included under public/licenses/GPL.txt.
|
||||||
|
*
|
||||||
|
* To view the latest information, see: http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_JIT_CALL_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_JIT_CALL_H_
|
||||||
|
|
||||||
|
#include "CallMaker.h"
|
||||||
|
#include "CallWrapper.h"
|
||||||
|
|
||||||
|
void JIT_Compile(CallWrapper *pWrapper, FuncAddrMethod method);
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_JIT_CALL_H_
|
20
extensions/bintools/msvc8/bintools.sln
Normal file
20
extensions/bintools/msvc8/bintools.sln
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
|
# Visual Studio 2005
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bintools", "bintools.vcproj", "{B3E797CF-4E77-4C9D-B8A8-7589B6902206}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
253
extensions/bintools/msvc8/bintools.vcproj
Normal file
253
extensions/bintools/msvc8/bintools.vcproj
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8,00"
|
||||||
|
Name="bintools"
|
||||||
|
ProjectGUID="{B3E797CF-4E77-4C9D-B8A8-7589B6902206}"
|
||||||
|
RootNamespace="bintools"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="2"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="..\..\..\public;..\..\..\public\sourcepawn"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;BINTOOLS_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="1"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="false"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
OutputFile="$(OutDir)\bintools.ext.dll"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="2"
|
||||||
|
CharacterSet="2"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalIncludeDirectories="..\..\..\public;..\..\..\public\sourcepawn"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;BINTOOLS_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
|
||||||
|
RuntimeLibrary="0"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="false"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
OutputFile="$(OutDir)\bintools.ext.dll"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="2"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\extension.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\smsdk_ext.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\extension.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\smsdk_config.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\smsdk_ext.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="BinTools"
|
||||||
|
>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\CallMaker.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\CallWrapper.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\jit_call.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\CallMaker.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\CallWrapper.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\jit_call.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
33
extensions/bintools/smsdk_config.h
Normal file
33
extensions/bintools/smsdk_config.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// vim: set ts=4 :
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file smsdk_config.h
|
||||||
|
* @brief Contains macros for configuring basic extension information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Basic information exposed publically */
|
||||||
|
#define SMEXT_CONF_NAME "Sample Extension"
|
||||||
|
#define SMEXT_CONF_DESCRIPTION "Sample extension to help developers"
|
||||||
|
#define SMEXT_CONF_VERSION "0.0.0.0"
|
||||||
|
#define SMEXT_CONF_AUTHOR "AlliedModders"
|
||||||
|
#define SMEXT_CONF_URL "http://www.sourcemod.net/"
|
||||||
|
#define SMEXT_CONF_LOGTAG "SAMPLE"
|
||||||
|
#define SMEXT_CONF_LICENSE "GPL"
|
||||||
|
#define SMEXT_CONF_DATESTRING __DATE__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Exposes plugin's main interface.
|
||||||
|
*/
|
||||||
|
#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets whether or not this plugin required Metamod.
|
||||||
|
* NOTE: Uncomment to enable, comment to disable.
|
||||||
|
* NOTE: This is enabled automatically if a Metamod build is chosen in
|
||||||
|
* the Visual Studio project.
|
||||||
|
*/
|
||||||
|
//#define SMEXT_CONF_METAMOD
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
333
extensions/bintools/smsdk_ext.cpp
Normal file
333
extensions/bintools/smsdk_ext.cpp
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
|
||||||
|
* All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK. This file may only be used
|
||||||
|
* or modified under the Terms and Conditions of its License Agreement, which is found
|
||||||
|
* in LICENSE.txt. The Terms and Conditions for making SourceMod extensions/plugins
|
||||||
|
* may change at any time. To view the latest information, see:
|
||||||
|
* http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include "smsdk_ext.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file smsdk_ext.cpp
|
||||||
|
* @brief Contains wrappers for making Extensions easier to write.
|
||||||
|
*/
|
||||||
|
|
||||||
|
IShareSys *g_pShareSys = NULL; /**< Share system */
|
||||||
|
IExtension *myself = NULL; /**< Ourself */
|
||||||
|
IHandleSys *g_pHandleSys = NULL; /**< Handle system */
|
||||||
|
ISourceMod *g_pSM = NULL; /**< SourceMod helpers */
|
||||||
|
IForwardManager *g_pForwards = NULL; /**< Forward system */
|
||||||
|
|
||||||
|
/** Exports the main interface */
|
||||||
|
PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
|
||||||
|
{
|
||||||
|
return g_pExtensionIface;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDKExtension::SDKExtension()
|
||||||
|
{
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
m_SourceMMLoaded = false;
|
||||||
|
m_WeAreUnloaded = false;
|
||||||
|
m_WeGotPauseChange = false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t err_max, bool late)
|
||||||
|
{
|
||||||
|
g_pShareSys = sys;
|
||||||
|
myself = me;
|
||||||
|
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
m_WeAreUnloaded = true;
|
||||||
|
|
||||||
|
if (!m_SourceMMLoaded)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
snprintf(error, err_max, "Metamod attach failed");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys);
|
||||||
|
SM_GET_IFACE(SOURCEMOD, g_pSM);
|
||||||
|
SM_GET_IFACE(FORWARDMANAGER, g_pForwards);
|
||||||
|
|
||||||
|
if (SDK_OnLoad(error, err_max, late))
|
||||||
|
{
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
m_WeAreUnloaded = true;
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDKExtension::IsMetamodExtension()
|
||||||
|
{
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDKExtension::OnExtensionPauseChange(bool state)
|
||||||
|
{
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
m_WeGotPauseChange = true;
|
||||||
|
#endif
|
||||||
|
SDK_OnPauseChange(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDKExtension::OnExtensionsAllLoaded()
|
||||||
|
{
|
||||||
|
SDK_OnAllLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDKExtension::OnExtensionUnload()
|
||||||
|
{
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
m_WeAreUnloaded = true;
|
||||||
|
#endif
|
||||||
|
SDK_OnUnload();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetExtensionAuthor()
|
||||||
|
{
|
||||||
|
return SMEXT_CONF_AUTHOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetExtensionDateString()
|
||||||
|
{
|
||||||
|
return SMEXT_CONF_DATESTRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetExtensionDescription()
|
||||||
|
{
|
||||||
|
return SMEXT_CONF_DESCRIPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetExtensionVerString()
|
||||||
|
{
|
||||||
|
return SMEXT_CONF_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetExtensionName()
|
||||||
|
{
|
||||||
|
return SMEXT_CONF_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetExtensionTag()
|
||||||
|
{
|
||||||
|
return SMEXT_CONF_LOGTAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetExtensionURL()
|
||||||
|
{
|
||||||
|
return SMEXT_CONF_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDKExtension::SDK_OnLoad(char *error, size_t err_max, bool late)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDKExtension::SDK_OnUnload()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDKExtension::SDK_OnPauseChange(bool paused)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDKExtension::SDK_OnAllLoaded()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
|
||||||
|
PluginId g_PLID = 0; /**< Metamod plugin ID */
|
||||||
|
ISmmPlugin *g_PLAPI = NULL; /**< Metamod plugin API */
|
||||||
|
SourceHook::ISourceHook *g_SHPtr = NULL; /**< SourceHook pointer */
|
||||||
|
ISmmAPI *g_SMAPI = NULL; /**< SourceMM API pointer */
|
||||||
|
|
||||||
|
IVEngineServer *engine = NULL; /**< IVEngineServer pointer */
|
||||||
|
IServerGameDLL *gamedll = NULL; /**< IServerGameDLL pointer */
|
||||||
|
|
||||||
|
/** Exposes the extension to Metamod */
|
||||||
|
SMM_API void *PL_EXPOSURE(const char *name, int *code)
|
||||||
|
{
|
||||||
|
if (name && !strcmp(name, PLAPI_NAME))
|
||||||
|
{
|
||||||
|
if (code)
|
||||||
|
{
|
||||||
|
*code = IFACE_OK;
|
||||||
|
}
|
||||||
|
return static_cast<void *>(g_pExtensionIface);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code)
|
||||||
|
{
|
||||||
|
*code = IFACE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDKExtension::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)
|
||||||
|
{
|
||||||
|
PLUGIN_SAVEVARS();
|
||||||
|
|
||||||
|
GET_V_IFACE_ANY(serverFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL);
|
||||||
|
GET_V_IFACE_CURRENT(engineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
|
||||||
|
|
||||||
|
m_SourceMMLoaded = true;
|
||||||
|
|
||||||
|
return SDK_OnMetamodLoad(ismm, error, maxlen, late);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDKExtension::Unload(char *error, size_t maxlen)
|
||||||
|
{
|
||||||
|
if (!m_WeAreUnloaded)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
snprintf(error, maxlen, "This extension must be unloaded by SourceMod.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDK_OnMetamodUnload(error, maxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDKExtension::Pause(char *error, size_t maxlen)
|
||||||
|
{
|
||||||
|
if (!m_WeGotPauseChange)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
snprintf(error, maxlen, "This extension must be paused by SourceMod.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_WeGotPauseChange = false;
|
||||||
|
|
||||||
|
return SDK_OnMetamodPauseChange(true, error, maxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDKExtension::Unpause(char *error, size_t maxlen)
|
||||||
|
{
|
||||||
|
if (!m_WeGotPauseChange)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
snprintf(error, maxlen, "This extension must be unpaused by SourceMod.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_WeGotPauseChange = false;
|
||||||
|
|
||||||
|
return SDK_OnMetamodPauseChange(false, error, maxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetAuthor()
|
||||||
|
{
|
||||||
|
return GetExtensionAuthor();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetDate()
|
||||||
|
{
|
||||||
|
return GetExtensionDateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetDescription()
|
||||||
|
{
|
||||||
|
return GetExtensionDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetLicense()
|
||||||
|
{
|
||||||
|
return SMEXT_CONF_LICENSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetLogTag()
|
||||||
|
{
|
||||||
|
return GetExtensionTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetName()
|
||||||
|
{
|
||||||
|
return GetExtensionName();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetURL()
|
||||||
|
{
|
||||||
|
return GetExtensionURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SDKExtension::GetVersion()
|
||||||
|
{
|
||||||
|
return GetExtensionVerString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDKExtension::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDKExtension::SDK_OnMetamodUnload(char *error, size_t err_max)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDKExtension::SDK_OnMetamodPauseChange(bool paused, char *error, size_t err_max)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Overload a few things to prevent libstdc++ linking */
|
||||||
|
#if defined __linux__
|
||||||
|
extern "C" void __cxa_pure_virtual(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void *operator new(size_t size)
|
||||||
|
{
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *operator new[](size_t size)
|
||||||
|
{
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void *ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void * ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
196
extensions/bintools/smsdk_ext.h
Normal file
196
extensions/bintools/smsdk_ext.h
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
|
||||||
|
* All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK. This file may only be used
|
||||||
|
* or modified under the Terms and Conditions of its License Agreement, which is found
|
||||||
|
* in LICENSE.txt. The Terms and Conditions for making SourceMod extensions/plugins
|
||||||
|
* may change at any time. To view the latest information, see:
|
||||||
|
* http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file smsdk_ext.h
|
||||||
|
* @brief Contains wrappers for making Extensions easier to write.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "smsdk_config.h"
|
||||||
|
#include <IExtensionSys.h>
|
||||||
|
#include <IHandleSys.h>
|
||||||
|
#include <sp_vm_api.h>
|
||||||
|
#include <sm_platform.h>
|
||||||
|
#include <ISourceMod.h>
|
||||||
|
#include <IForwardSys.h>
|
||||||
|
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
#include <ISmmPlugin.h>
|
||||||
|
#include <eiface.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
using namespace SourcePawn;
|
||||||
|
|
||||||
|
class SDKExtension :
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
public ISmmPlugin,
|
||||||
|
#endif
|
||||||
|
public IExtensionInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Constructor */
|
||||||
|
SDKExtension();
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief This is called after the initial loading sequence has been processed.
|
||||||
|
*
|
||||||
|
* @param error Error message buffer.
|
||||||
|
* @param err_max Size of error message buffer.
|
||||||
|
* @param late Whether or not the module was loaded after map load.
|
||||||
|
* @return True to succeed loading, false to fail.
|
||||||
|
*/
|
||||||
|
virtual bool SDK_OnLoad(char *error, size_t err_max, bool late);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This is called right before the extension is unloaded.
|
||||||
|
*/
|
||||||
|
virtual void SDK_OnUnload();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This is called once all known extensions have been loaded.
|
||||||
|
*/
|
||||||
|
virtual void SDK_OnAllLoaded();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when the pause state is changed.
|
||||||
|
*/
|
||||||
|
virtual void SDK_OnPauseChange(bool paused);
|
||||||
|
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
/**
|
||||||
|
* @brief Called when Metamod is attached, before the extension version is called.
|
||||||
|
*
|
||||||
|
* @param error Error buffer.
|
||||||
|
* @param err_max Maximum size of error buffer.
|
||||||
|
* @param late Whether or not Metamod considers this a late load.
|
||||||
|
* @return True to succeed, false to fail.
|
||||||
|
*/
|
||||||
|
virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when Metamod is detaching, after the extension version is called.
|
||||||
|
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||||
|
*
|
||||||
|
* @param error Error buffer.
|
||||||
|
* @param err_max Maximum size of error buffer.
|
||||||
|
* @return True to succeed, false to fail.
|
||||||
|
*/
|
||||||
|
virtual bool SDK_OnMetamodUnload(char *error, size_t err_max);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when Metamod's pause state is changing.
|
||||||
|
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||||
|
*
|
||||||
|
* @param paused Pause state being set.
|
||||||
|
* @param error Error buffer.
|
||||||
|
* @param err_max Maximum size of error buffer.
|
||||||
|
* @return True to succeed, false to fail.
|
||||||
|
*/
|
||||||
|
virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t err_max);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public: //IExtensionInterface
|
||||||
|
virtual bool OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t err_max, bool late);
|
||||||
|
virtual void OnExtensionUnload();
|
||||||
|
virtual void OnExtensionsAllLoaded();
|
||||||
|
|
||||||
|
/** Returns whether or not this is a Metamod-based extension */
|
||||||
|
virtual bool IsMetamodExtension();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when the pause state changes.
|
||||||
|
*
|
||||||
|
* @param state True if being paused, false if being unpaused.
|
||||||
|
*/
|
||||||
|
virtual void OnExtensionPauseChange(bool state);
|
||||||
|
|
||||||
|
/** Returns name */
|
||||||
|
virtual const char *GetExtensionName();
|
||||||
|
/** Returns URL */
|
||||||
|
virtual const char *GetExtensionURL();
|
||||||
|
/** Returns log tag */
|
||||||
|
virtual const char *GetExtensionTag();
|
||||||
|
/** Returns author */
|
||||||
|
virtual const char *GetExtensionAuthor();
|
||||||
|
/** Returns version string */
|
||||||
|
virtual const char *GetExtensionVerString();
|
||||||
|
/** Returns description string */
|
||||||
|
virtual const char *GetExtensionDescription();
|
||||||
|
/** Returns date string */
|
||||||
|
virtual const char *GetExtensionDateString();
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
public: //ISmmPlugin
|
||||||
|
/** Called when the extension is attached to Metamod. */
|
||||||
|
virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late);
|
||||||
|
/** Returns the author to MM */
|
||||||
|
virtual const char *GetAuthor();
|
||||||
|
/** Returns the name to MM */
|
||||||
|
virtual const char *GetName();
|
||||||
|
/** Returns the description to MM */
|
||||||
|
virtual const char *GetDescription();
|
||||||
|
/** Returns the URL to MM */
|
||||||
|
virtual const char *GetURL();
|
||||||
|
/** Returns the license to MM */
|
||||||
|
virtual const char *GetLicense();
|
||||||
|
/** Returns the version string to MM */
|
||||||
|
virtual const char *GetVersion();
|
||||||
|
/** Returns the date string to MM */
|
||||||
|
virtual const char *GetDate();
|
||||||
|
/** Returns the logtag to MM */
|
||||||
|
virtual const char *GetLogTag();
|
||||||
|
/** Called on unload */
|
||||||
|
virtual bool Unload(char *error, size_t maxlen);
|
||||||
|
/** Called on pause */
|
||||||
|
virtual bool Pause(char *error, size_t maxlen);
|
||||||
|
/** Called on unpause */
|
||||||
|
virtual bool Unpause(char *error, size_t maxlen);
|
||||||
|
private:
|
||||||
|
bool m_SourceMMLoaded;
|
||||||
|
bool m_WeAreUnloaded;
|
||||||
|
bool m_WeGotPauseChange;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
extern SDKExtension *g_pExtensionIface;
|
||||||
|
|
||||||
|
extern IShareSys *g_pShareSys;
|
||||||
|
extern IExtension *myself;
|
||||||
|
extern IHandleSys *g_pHandleSys;
|
||||||
|
extern ISourceMod *g_pSM;
|
||||||
|
extern IForwardManager *g_pForwards;
|
||||||
|
|
||||||
|
#if defined SMEXT_CONF_METAMOD
|
||||||
|
PLUGIN_GLOBALVARS();
|
||||||
|
extern IVEngineServer *engine;
|
||||||
|
extern IServerGameDLL *gamedll;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Creates a SourceMod interface macro pair */
|
||||||
|
#define SM_MKIFACE(name) SMINTERFACE_##name##_NAME, SMINTERFACE_##name##_VERSION
|
||||||
|
/** Automates retrieving SourceMod interfaces */
|
||||||
|
#define SM_GET_IFACE(prefix,addr) \
|
||||||
|
if (!g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr)) { \
|
||||||
|
if (error) { \
|
||||||
|
snprintf(error, err_max, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \
|
||||||
|
} \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
|
178
public/extensions/IBinTools.h
Normal file
178
public/extensions/IBinTools.h
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
|
||||||
|
* All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK. This file may only be
|
||||||
|
* used or modified under the Terms and Conditions of its License Agreement,
|
||||||
|
* which is found in public/licenses/LICENSE.txt. As of this notice, derivative
|
||||||
|
* works must be licensed under the GNU General Public License (version 2 or
|
||||||
|
* greater). A copy of the GPL is included under public/licenses/GPL.txt.
|
||||||
|
*
|
||||||
|
* To view the latest information, see: http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_SMEXT_BINTOOLS_H_
|
||||||
|
#define _INCLUDE_SMEXT_BINTOOLS_H_
|
||||||
|
|
||||||
|
#include <IShareSys.h>
|
||||||
|
|
||||||
|
#define SMINTERFACE_BINTOOLS_NAME "IBinTools"
|
||||||
|
#define SMINTERFACE_BINTOOLS_VERSION 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function calling encoding utilities
|
||||||
|
* @file IBinTools.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace SourceMod
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Supported calling conventions
|
||||||
|
*/
|
||||||
|
enum CallConvention
|
||||||
|
{
|
||||||
|
CallConv_ThisCall, /**< This call (object pointer required) */
|
||||||
|
CallConv_Cdecl, /**< Standard C call */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Describes how a parameter should be passed
|
||||||
|
*/
|
||||||
|
enum PassType
|
||||||
|
{
|
||||||
|
PassType_Basic, /**< Plain old register data (pointers, integers) */
|
||||||
|
PassType_Float, /**< Floating point data */
|
||||||
|
PassType_Object, /**< Object or structure */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PASSFLAG_BYVAL (1<<0) /**< Passing by value */
|
||||||
|
#define PASSFLAG_BYREF (1<<1) /**< Passing by reference */
|
||||||
|
#define PASSFLAG_ODTOR (1<<2) /**< Object has a destructor */
|
||||||
|
#define PASSFLAG_OCTOR (1<<3) /**< Object has a constructor */
|
||||||
|
#define PASSFLAG_OASSIGNOP (1<<4) /**< Object has an assignment operator */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parameter passing information
|
||||||
|
*/
|
||||||
|
struct PassInfo
|
||||||
|
{
|
||||||
|
PassType type; /**< PassType value */
|
||||||
|
unsigned int flags; /**< Pass/return flags */
|
||||||
|
size_t size; /**< Size of the data being passed */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parameter encoding information
|
||||||
|
*/
|
||||||
|
struct PassEncode
|
||||||
|
{
|
||||||
|
PassInfo info; /**< Parameter information */
|
||||||
|
size_t offset; /**< Offset into the virtual stack */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wraps a C/C++ call.
|
||||||
|
*/
|
||||||
|
class ICallWrapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Returns the calling convention.
|
||||||
|
*
|
||||||
|
* @return CallConvention value.
|
||||||
|
*/
|
||||||
|
virtual CallConvention GetCallConvention() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns parameter info.
|
||||||
|
*
|
||||||
|
* @param num Parameter number to get (starting from 0).
|
||||||
|
* @return A PassInfo pointer.
|
||||||
|
*/
|
||||||
|
virtual const PassEncode *GetParamInfo(unsigned int num) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns return type info.
|
||||||
|
*
|
||||||
|
* @return A PassInfo pointer.
|
||||||
|
*/
|
||||||
|
virtual const PassInfo *GetReturnInfo() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the number of parameters.
|
||||||
|
*/
|
||||||
|
virtual unsigned int GetParamCount() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Execute the contained function.
|
||||||
|
*/
|
||||||
|
virtual void Execute(void *vParamStack, void *retBuffer) =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Binary tools interface.
|
||||||
|
*/
|
||||||
|
class IBinTools : public SMInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual const char *GetInterfaceName()
|
||||||
|
{
|
||||||
|
return SMINTERFACE_BINTOOLS_NAME;
|
||||||
|
}
|
||||||
|
virtual unsigned int GetInterfaceVersion()
|
||||||
|
{
|
||||||
|
return SMINTERFACE_BINTOOLS_VERSION;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Creates a call decoder.
|
||||||
|
*
|
||||||
|
* Note: CallConv_ThisCall requires an implicit first parameter
|
||||||
|
* of PassType_Basic / PASSFLAG_BYVAL / sizeof(void *). However,
|
||||||
|
* this should only be given to the Execute() function, and never
|
||||||
|
* listed in the paramInfo array.
|
||||||
|
*
|
||||||
|
* @param address Address to use as a call.
|
||||||
|
* @param cv Calling convention.
|
||||||
|
* @param retInfo Return type information, or NULL for void.
|
||||||
|
* @param paramInfo Array of parameters.
|
||||||
|
* @param numParams Number of parameters in the array.
|
||||||
|
* @return A new ICallWrapper function.
|
||||||
|
*/
|
||||||
|
virtual ICallWrapper *CreateCall(void *address,
|
||||||
|
CallConvention cv,
|
||||||
|
const PassInfo *retInfo,
|
||||||
|
const PassInfo paramInfo[],
|
||||||
|
unsigned int numParams) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a vtable call decoder.
|
||||||
|
*
|
||||||
|
* Note: CallConv_ThisCall requires an implicit first parameter
|
||||||
|
* of PassType_Basic / PASSFLAG_BYVAL / sizeof(void *). However,
|
||||||
|
* this should only be given to the Execute() function, and never
|
||||||
|
* listed in the paramInfo array.
|
||||||
|
*
|
||||||
|
* @param vtblIdx Index into the virtual table.
|
||||||
|
* @param vtblOffs Offset of the virtual table.
|
||||||
|
* @param thisOffs Offset of the this pointer of the virtual table.
|
||||||
|
* @param retInfo Return type information, or NULL for void.
|
||||||
|
* @param paramInfo Array of parameters.
|
||||||
|
* @param numParams Number of parameters in the array.
|
||||||
|
* @return A new ICallWrapper function.
|
||||||
|
*/
|
||||||
|
virtual ICallWrapper *CreateVCall(unsigned int vtblIdx,
|
||||||
|
unsigned int vtblOffs,
|
||||||
|
unsigned int thisOffs,
|
||||||
|
const PassInfo *retInfo,
|
||||||
|
const PassInfo paramInfo[],
|
||||||
|
unsigned int numParams) =0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SMEXT_BINTOOLS_H_
|
@ -92,6 +92,8 @@
|
|||||||
#define IA32_MOV_RM8_REG 0x88 // encoding is /r
|
#define IA32_MOV_RM8_REG 0x88 // encoding is /r
|
||||||
#define IA32_MOV_RM_REG 0x89 // encoding is /r
|
#define IA32_MOV_RM_REG 0x89 // encoding is /r
|
||||||
#define IA32_MOV_REG_MEM 0x8B // encoding is /r
|
#define IA32_MOV_REG_MEM 0x8B // encoding is /r
|
||||||
|
#define IA32_MOV_REG8_RM8 0x8A // encoding is /r
|
||||||
|
#define IA32_MOV_RM8_REG8 0x88 // encoding is /r
|
||||||
#define IA32_MOV_RM_IMM32 0xC7 // encoding is /0
|
#define IA32_MOV_RM_IMM32 0xC7 // encoding is /0
|
||||||
#define IA32_CMP_RM_IMM32 0x81 // encoding is /7 <imm32>
|
#define IA32_CMP_RM_IMM32 0x81 // encoding is /7 <imm32>
|
||||||
#define IA32_CMP_RM_IMM8 0x83 // encoding is /7 <imm8>
|
#define IA32_CMP_RM_IMM8 0x83 // encoding is /7 <imm8>
|
||||||
@ -149,6 +151,10 @@
|
|||||||
#define IA32_POPAD 0x61 // no extra encoding
|
#define IA32_POPAD 0x61 // no extra encoding
|
||||||
#define IA32_NOP 0x90 // no extra encoding
|
#define IA32_NOP 0x90 // no extra encoding
|
||||||
#define IA32_INT3 0xCC // no extra encoding
|
#define IA32_INT3 0xCC // no extra encoding
|
||||||
|
#define IA32_FSTP_MEM32 0xD9 // encoding is /3
|
||||||
|
#define IA32_FSTP_MEM64 0xDD // encoding is /3
|
||||||
|
#define IA32_FLD_MEM32 0xD9 // encoding is /0
|
||||||
|
#define IA32_FLD_MEM64 0xDD // encoding is /0
|
||||||
|
|
||||||
inline jit_uint8_t ia32_modrm(jit_uint8_t mode, jit_uint8_t reg, jit_uint8_t rm)
|
inline jit_uint8_t ia32_modrm(jit_uint8_t mode, jit_uint8_t reg, jit_uint8_t rm)
|
||||||
{
|
{
|
||||||
@ -629,6 +635,19 @@ inline void IA32_Lea_Reg_DispRegMultImm8(JitWriter *jit,
|
|||||||
jit->write_byte(val);
|
jit->write_byte(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void IA32_Lea_Reg_DispRegMultImm32(JitWriter *jit,
|
||||||
|
jit_uint8_t dest,
|
||||||
|
jit_uint8_t src_base,
|
||||||
|
jit_uint8_t src_index,
|
||||||
|
jit_uint8_t scale,
|
||||||
|
jit_int32_t val)
|
||||||
|
{
|
||||||
|
jit->write_ubyte(IA32_LEA_REG_MEM);
|
||||||
|
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, REG_SIB));
|
||||||
|
jit->write_ubyte(ia32_sib(scale, src_index, src_base));
|
||||||
|
jit->write_int32(val);
|
||||||
|
}
|
||||||
|
|
||||||
inline void IA32_Lea_Reg_RegMultImm32(JitWriter *jit,
|
inline void IA32_Lea_Reg_RegMultImm32(JitWriter *jit,
|
||||||
jit_uint8_t dest,
|
jit_uint8_t dest,
|
||||||
jit_uint8_t src_index,
|
jit_uint8_t src_index,
|
||||||
@ -716,6 +735,12 @@ inline void IA32_Mov_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, j
|
|||||||
jit->write_ubyte(ia32_modrm(mode, dest, src));
|
jit->write_ubyte(ia32_modrm(mode, dest, src));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void IA32_Mov_Reg8_Rm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
|
||||||
|
{
|
||||||
|
jit->write_ubyte(IA32_MOV_REG8_RM8);
|
||||||
|
jit->write_ubyte(ia32_modrm(mode, dest, src));
|
||||||
|
}
|
||||||
|
|
||||||
inline void IA32_Mov_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
|
inline void IA32_Mov_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
|
||||||
{
|
{
|
||||||
jit->write_ubyte(IA32_MOV_REG_MEM);
|
jit->write_ubyte(IA32_MOV_REG_MEM);
|
||||||
@ -723,6 +748,13 @@ inline void IA32_Mov_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t
|
|||||||
jit->write_byte(disp);
|
jit->write_byte(disp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void IA32_Mov_Reg8_Rm8_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
|
||||||
|
{
|
||||||
|
jit->write_ubyte(IA32_MOV_REG8_RM8);
|
||||||
|
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src));
|
||||||
|
jit->write_byte(disp);
|
||||||
|
}
|
||||||
|
|
||||||
inline void IA32_Mov_Reg_Esp_Disp8(JitWriter *jit, jit_uint8_t dest, jit_int8_t disp)
|
inline void IA32_Mov_Reg_Esp_Disp8(JitWriter *jit, jit_uint8_t dest, jit_int8_t disp)
|
||||||
{
|
{
|
||||||
jit->write_ubyte(IA32_MOV_REG_MEM);
|
jit->write_ubyte(IA32_MOV_REG_MEM);
|
||||||
@ -738,6 +770,13 @@ inline void IA32_Mov_Reg_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t
|
|||||||
jit->write_int32(disp);
|
jit->write_int32(disp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void IA32_Mov_Reg8_Rm8_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
|
||||||
|
{
|
||||||
|
jit->write_ubyte(IA32_MOV_REG8_RM8);
|
||||||
|
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, src));
|
||||||
|
jit->write_int32(disp);
|
||||||
|
}
|
||||||
|
|
||||||
inline void IA32_Mov_Reg_Rm_Disp_Reg(JitWriter *jit,
|
inline void IA32_Mov_Reg_Rm_Disp_Reg(JitWriter *jit,
|
||||||
jit_uint8_t dest,
|
jit_uint8_t dest,
|
||||||
jit_uint8_t src_base,
|
jit_uint8_t src_base,
|
||||||
@ -784,6 +823,12 @@ inline void IA32_Mov_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, j
|
|||||||
jit->write_ubyte(ia32_modrm(mode, src, dest));
|
jit->write_ubyte(ia32_modrm(mode, src, dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void IA32_Mov_Rm8_Reg8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
|
||||||
|
{
|
||||||
|
jit->write_ubyte(IA32_MOV_RM8_REG8);
|
||||||
|
jit->write_ubyte(ia32_modrm(mode, src, dest));
|
||||||
|
}
|
||||||
|
|
||||||
inline void IA32_Mov_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
|
inline void IA32_Mov_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
|
||||||
{
|
{
|
||||||
jit->write_ubyte(IA32_MOV_RM_REG);
|
jit->write_ubyte(IA32_MOV_RM_REG);
|
||||||
@ -890,6 +935,52 @@ inline void IA32_Mov_RmEBP_Imm32_Disp_Reg(JitWriter *jit,
|
|||||||
jit->write_int32(val);
|
jit->write_int32(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Floating Point Instructions
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline void IA32_Fstp_Mem32(JitWriter *jit, jit_uint8_t dest_base, jit_uint8_t dest_index, jit_uint8_t dest_scale)
|
||||||
|
{
|
||||||
|
jit->write_ubyte(IA32_FSTP_MEM32);
|
||||||
|
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, REG_SIB));
|
||||||
|
jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void IA32_Fstp_Mem64(JitWriter *jit, jit_uint8_t dest_base, jit_uint8_t dest_index, jit_uint8_t dest_scale)
|
||||||
|
{
|
||||||
|
jit->write_ubyte(IA32_FSTP_MEM64);
|
||||||
|
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, REG_SIB));
|
||||||
|
jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void IA32_Fld_Mem32_Disp8(JitWriter *jit, jit_uint8_t dest, jit_int8_t val)
|
||||||
|
{
|
||||||
|
jit->write_ubyte(IA32_FLD_MEM32);
|
||||||
|
jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, dest));
|
||||||
|
jit->write_byte(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void IA32_Fld_Mem64_Disp8(JitWriter *jit, jit_uint8_t dest, jit_int8_t val)
|
||||||
|
{
|
||||||
|
jit->write_ubyte(IA32_FLD_MEM64);
|
||||||
|
jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, dest));
|
||||||
|
jit->write_byte(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void IA32_Fld_Mem32_Disp32(JitWriter *jit, jit_uint8_t dest, jit_int32_t val)
|
||||||
|
{
|
||||||
|
jit->write_ubyte(IA32_FLD_MEM32);
|
||||||
|
jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, dest));
|
||||||
|
jit->write_int32(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void IA32_Fld_Mem64_Disp32(JitWriter *jit, jit_uint8_t dest, jit_int32_t val)
|
||||||
|
{
|
||||||
|
jit->write_ubyte(IA32_FLD_MEM64);
|
||||||
|
jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, dest));
|
||||||
|
jit->write_int32(val);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Branching/Jumping
|
* Branching/Jumping
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user