landed massive refactoring of the JIT. contexts are actually contexts now, and a higher level structure wraps sp_plugin_t info. on that note, both sp_plugin_t and sp_context_t are entirely opaque, and not even core has access to them. amazingly, i managed to keep binary compatibility here although a large number of functions are deprecated (and core should eventually stop calling them).
NOTE: the JIT is now embeddable out-of-box and usable by other projects which is pretty cool. I will commit a shell app demonstrating this soon --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402400
This commit is contained in:
parent
ea1f5e86c0
commit
1a156deca5
@ -36,11 +36,6 @@
|
|||||||
|
|
||||||
DebugReport g_DbgReporter;
|
DebugReport g_DbgReporter;
|
||||||
|
|
||||||
/* I'm really lazy. This should probably be exported to ISourcePawnEngine someday,
|
|
||||||
* but we need to make sure the JIT will deal with the version bump.
|
|
||||||
*/
|
|
||||||
extern const char *GetSourcePawnErrorMessage(int error);
|
|
||||||
|
|
||||||
void DebugReport::OnSourceModAllInitialized()
|
void DebugReport::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_pSourcePawn->SetDebugListener(this);
|
g_pSourcePawn->SetDebugListener(this);
|
||||||
@ -56,7 +51,7 @@ void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, c
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
|
const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
|
||||||
const char *error = GetSourcePawnErrorMessage(err);
|
const char *error = g_pSourcePawn2->GetErrorString(err);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@ -91,7 +86,7 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
const char *plname = g_PluginSys.FindPluginByContext(pContext->GetContext())->GetFilename();
|
const char *plname = g_PluginSys.FindPluginByContext(pContext->GetContext())->GetFilename();
|
||||||
const char *error = GetSourcePawnErrorMessage(err);
|
const char *error = g_pSourcePawn2->GetErrorString(err);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
|
@ -29,12 +29,8 @@ OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
|
|||||||
smn_adt_trie.cpp smn_hudtext.cpp smn_adt_stack.cpp smn_nextmap.cpp
|
smn_adt_trie.cpp smn_hudtext.cpp smn_adt_stack.cpp smn_nextmap.cpp
|
||||||
OBJECTS += systems/ExtensionSys.cpp systems/ForwardSys.cpp systems/HandleSys.cpp \
|
OBJECTS += systems/ExtensionSys.cpp systems/ForwardSys.cpp systems/HandleSys.cpp \
|
||||||
systems/LibrarySys.cpp systems/PluginInfoDatabase.cpp systems/PluginSys.cpp \
|
systems/LibrarySys.cpp systems/PluginInfoDatabase.cpp systems/PluginSys.cpp \
|
||||||
systems/ShareSys.cpp vm/sp_vm_basecontext.cpp vm/sp_vm_engine.cpp \
|
systems/ShareSys.cpp
|
||||||
vm/sp_vm_function.cpp
|
|
||||||
OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
|
OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
|
||||||
OBJECTS += zlib/adler32.c zlib/compress.c zlib/crc32.c zlib/deflate.c zlib/gzio.c \
|
|
||||||
zlib/infback.c zlib/inffast.c zlib/inflate.c zlib/inftrees.c zlib/trees.c \
|
|
||||||
zlib/uncompr.c zlib/zutil.c
|
|
||||||
|
|
||||||
##############################################
|
##############################################
|
||||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
||||||
@ -103,13 +99,9 @@ ifeq "$(GCC_VERSION)" "4"
|
|||||||
CPPFLAGS += $(CPP_GCC4_FLAGS)
|
CPPFLAGS += $(CPP_GCC4_FLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OBJ_LINUX := $(OBJECTS:%vm_engine.cpp=$(BIN_DIR)/%vm_engine.o)
|
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||||
OBJ_LINUX := $(OBJ_LINUX:%.cpp=$(BIN_DIR)/%.o)
|
|
||||||
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
|
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
|
||||||
|
|
||||||
$(BIN_DIR)/%vm_engine.o: %vm_engine.cpp
|
|
||||||
$(CPP) $(INCLUDE_SM16) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
|
||||||
|
|
||||||
$(BIN_DIR)/%.o: %.cpp
|
$(BIN_DIR)/%.o: %.cpp
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
@ -118,8 +110,6 @@ $(BIN_DIR)/%.o: %.c
|
|||||||
|
|
||||||
all: check
|
all: check
|
||||||
mkdir -p $(BIN_DIR)/systems
|
mkdir -p $(BIN_DIR)/systems
|
||||||
mkdir -p $(BIN_DIR)/vm
|
|
||||||
mkdir -p $(BIN_DIR)/zlib
|
|
||||||
mkdir -p $(BIN_DIR)/thread
|
mkdir -p $(BIN_DIR)/thread
|
||||||
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so;
|
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so;
|
||||||
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so;
|
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so;
|
||||||
@ -142,7 +132,5 @@ default: all
|
|||||||
clean: check
|
clean: check
|
||||||
rm -rf $(BIN_DIR)/*.o
|
rm -rf $(BIN_DIR)/*.o
|
||||||
rm -rf $(BIN_DIR)/systems/*.o
|
rm -rf $(BIN_DIR)/systems/*.o
|
||||||
rm -rf $(BIN_DIR)/zlib/*.o
|
|
||||||
rm -rf $(BIN_DIR)/vm/*.o
|
|
||||||
rm -rf $(BIN_DIR)/thread/*.o
|
rm -rf $(BIN_DIR)/thread/*.o
|
||||||
rm -rf $(BIN_DIR)/$(BINARY)
|
rm -rf $(BIN_DIR)/$(BINARY)
|
||||||
|
@ -1358,204 +1358,26 @@
|
|||||||
Name="SourcePawn"
|
Name="SourcePawn"
|
||||||
UniqueIdentifier="{C3C3DC6E-E392-4916-B893-7ACB92192DE0}"
|
UniqueIdentifier="{C3C3DC6E-E392-4916-B893-7ACB92192DE0}"
|
||||||
>
|
>
|
||||||
<Filter
|
<File
|
||||||
Name="Header Files"
|
RelativePath="..\..\public\sourcepawn\sp_file_headers.h"
|
||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
|
||||||
UniqueIdentifier="{D06F7D18-C940-4200-990B-2D0CF72F91AB}"
|
|
||||||
>
|
>
|
||||||
<File
|
</File>
|
||||||
RelativePath="..\vm\sp_vm_basecontext.h"
|
<File
|
||||||
>
|
RelativePath="..\..\public\sourcepawn\sp_typeutil.h"
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\vm\sp_vm_engine.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\vm\sp_vm_function.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Source Files"
|
|
||||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
|
||||||
UniqueIdentifier="{605A5261-30CD-4cca-BBE2-23BB190DA44E}"
|
|
||||||
>
|
>
|
||||||
<File
|
</File>
|
||||||
RelativePath="..\vm\sp_vm_basecontext.cpp"
|
<File
|
||||||
>
|
RelativePath="..\..\public\sourcepawn\sp_vm_api.h"
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\vm\sp_vm_engine.cpp"
|
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="CrazyDebug - Old Metamod|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories=""$(SOURCEMM16)\sourcehook""
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug - Old Metamod|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories=""$(SOURCEMM16)\sourcehook""
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release - Old Metamod|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories=""$(SOURCEMM16)\sourcehook""
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="CrazyDebug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories=""$(SOURCEMM16)\sourcehook""
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\vm\sp_vm_function.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="SDK"
|
|
||||||
UniqueIdentifier="{A76160D7-4623-42c7-9587-62049792B924}"
|
|
||||||
>
|
>
|
||||||
<File
|
</File>
|
||||||
RelativePath="..\..\public\sourcepawn\sp_file_headers.h"
|
<File
|
||||||
>
|
RelativePath="..\..\public\sourcepawn\sp_vm_base.h"
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\public\sourcepawn\sp_typeutil.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\public\sourcepawn\sp_vm_api.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\public\sourcepawn\sp_vm_base.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\public\sourcepawn\sp_vm_types.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="zlib"
|
|
||||||
UniqueIdentifier="{27E223C9-0208-4c7d-BBAA-DE4BF1745020}"
|
|
||||||
>
|
|
||||||
<Filter
|
|
||||||
Name="Header Files"
|
|
||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
|
||||||
UniqueIdentifier="{65A17C3B-0B6E-450f-96B8-661D47876D4B}"
|
|
||||||
>
|
>
|
||||||
<File
|
</File>
|
||||||
RelativePath="..\zlib\crc32.h"
|
<File
|
||||||
>
|
RelativePath="..\..\public\sourcepawn\sp_vm_types.h"
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\deflate.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\inffast.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\inffixed.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\inflate.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\inftrees.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\trees.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\zconf.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\zlib.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\zutil.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Source Files"
|
|
||||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
|
||||||
UniqueIdentifier="{9279E65A-C154-4296-AE23-949EB8C62BEB}"
|
|
||||||
>
|
>
|
||||||
<File
|
</File>
|
||||||
RelativePath="..\zlib\adler32.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\compress.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\crc32.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\deflate.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\gzio.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\infback.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\inffast.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\inflate.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\inftrees.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\trees.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\uncompr.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\zlib\zutil.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="HL2SDK"
|
Name="HL2SDK"
|
||||||
|
@ -173,7 +173,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern ISourcePawnEngine *g_pSourcePawn;
|
extern ISourcePawnEngine *g_pSourcePawn;
|
||||||
extern IVirtualMachine *g_pVM;
|
extern ISourcePawnEngine2 *g_pSourcePawn2;
|
||||||
extern IdentityToken_t *g_pCoreIdent;
|
extern IdentityToken_t *g_pCoreIdent;
|
||||||
|
|
||||||
#include "sm_autonatives.h"
|
#include "sm_autonatives.h"
|
||||||
|
@ -281,8 +281,8 @@ void RootConsoleMenu::OnRootConsoleCommand(const char *cmdname, const CCommand &
|
|||||||
{
|
{
|
||||||
ConsolePrint(" SourceMod Version Information:");
|
ConsolePrint(" SourceMod Version Information:");
|
||||||
ConsolePrint(" SourceMod Version: %s", SVN_FULL_VERSION);
|
ConsolePrint(" SourceMod Version: %s", SVN_FULL_VERSION);
|
||||||
ConsolePrint(" JIT Version: %s, %s", g_pVM->GetVMName(), g_pVM->GetVersionString());
|
ConsolePrint(" SourcePawn Engine: %s (build %s)", g_pSourcePawn2->GetEngineName(), g_pSourcePawn2->GetVersionString());
|
||||||
ConsolePrint(" JIT Settings: %s", g_pVM->GetCPUOptimizations());
|
ConsolePrint(" SourcePawn API: v1 = %d, v2 = %d", g_pSourcePawn->GetEngineAPIVersion(), g_pSourcePawn2->GetAPIVersion());
|
||||||
ConsolePrint(" Compiled on: %s %s", __DATE__, __TIME__);
|
ConsolePrint(" Compiled on: %s %s", __DATE__, __TIME__);
|
||||||
ConsolePrint(" http://www.sourcemod.net/");
|
ConsolePrint(" http://www.sourcemod.net/");
|
||||||
}
|
}
|
||||||
|
@ -833,7 +833,7 @@ static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
|
|||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
|
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -854,7 +854,7 @@ static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *par
|
|||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
|
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -894,7 +894,7 @@ static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
|
|||||||
char buffer[256];
|
char buffer[256];
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -921,7 +921,7 @@ static cell_t FakeClientCommand(IPluginContext *pContext, const cell_t *params)
|
|||||||
char buffer[256];
|
char buffer[256];
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -948,7 +948,7 @@ static cell_t FakeClientCommandEx(IPluginContext *pContext, const cell_t *params
|
|||||||
char buffer[256];
|
char buffer[256];
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -966,7 +966,7 @@ static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params)
|
|||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 2);
|
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
|
|||||||
|
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err == SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() == SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
|
pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
|
||||||
}
|
}
|
||||||
@ -387,7 +387,7 @@ static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
|
|||||||
char buffer[2048];
|
char buffer[2048];
|
||||||
|
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
pPlugin->SetErrorState(Plugin_Error, "%s", str);
|
pPlugin->SetErrorState(Plugin_Error, "%s", str);
|
||||||
return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "Formatting error (%s)", str);
|
return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "Formatting error (%s)", str);
|
||||||
@ -455,7 +455,7 @@ static cell_t MarkNativeAsOptional(IPluginContext *pContext, const cell_t *param
|
|||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
sp_context_t *ctx = pContext->GetContext();
|
sp_native_t *native;
|
||||||
|
|
||||||
pContext->LocalToString(params[1], &name);
|
pContext->LocalToString(params[1], &name);
|
||||||
if (pContext->FindNativeByName(name, &idx) != SP_ERROR_NONE)
|
if (pContext->FindNativeByName(name, &idx) != SP_ERROR_NONE)
|
||||||
@ -464,7 +464,9 @@ static cell_t MarkNativeAsOptional(IPluginContext *pContext, const cell_t *param
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->natives[idx].flags |= SP_NTVFLAG_OPTIONAL;
|
pContext->GetNativeByIndex(idx, &native);
|
||||||
|
|
||||||
|
native->flags |= SP_NTVFLAG_OPTIONAL;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -505,7 +507,7 @@ static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params)
|
|||||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -535,7 +537,7 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params)
|
|||||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return 0;
|
return 0;
|
||||||
@ -568,7 +570,7 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params)
|
|||||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -54,8 +54,7 @@ cell_t FakeNativeRouter(IPluginContext *pContext, const cell_t *params, void *pD
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the native is paused */
|
/* Check if the native is paused */
|
||||||
sp_context_t *pNativeCtx = native->ctx->GetContext();
|
if (native->ctx->GetRuntime()->IsPaused())
|
||||||
if ((pNativeCtx->flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED)
|
|
||||||
{
|
{
|
||||||
return pContext->ThrowNativeError("Plugin owning this native is currently paused.");
|
return pContext->ThrowNativeError("Plugin owning this native is currently paused.");
|
||||||
}
|
}
|
||||||
@ -90,7 +89,7 @@ cell_t FakeNativeRouter(IPluginContext *pContext, const cell_t *params, void *pD
|
|||||||
int error;
|
int error;
|
||||||
if ((error=native->call->Execute(&result)) != SP_ERROR_NONE)
|
if ((error=native->call->Execute(&result)) != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
if (pContext->GetContext()->n_err == SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() == SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
pContext->ThrowNativeErrorEx(error, "Error encountered while processing a dynamic native");
|
pContext->ThrowNativeErrorEx(error, "Error encountered while processing a dynamic native");
|
||||||
}
|
}
|
||||||
@ -146,7 +145,7 @@ static cell_t ThrowNativeError(IPluginContext *pContext, const cell_t *params)
|
|||||||
|
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
s_curcaller->ThrowNativeError("Error encountered while processing a dynamic native");
|
s_curcaller->ThrowNativeError("Error encountered while processing a dynamic native");
|
||||||
} else {
|
} else {
|
||||||
@ -434,7 +433,7 @@ static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params)
|
|||||||
pContext->LocalToPhysAddr(params[5], &addr);
|
pContext->LocalToPhysAddr(params[5], &addr);
|
||||||
*addr = (cell_t)written;
|
*addr = (cell_t)written;
|
||||||
|
|
||||||
return s_curcaller->GetContext()->n_err;
|
return s_curcaller->GetLastNativeError();
|
||||||
}
|
}
|
||||||
|
|
||||||
//tee hee
|
//tee hee
|
||||||
|
@ -573,7 +573,7 @@ static cell_t sm_LogToGame(IPluginContext *pContext, const cell_t *params)
|
|||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -599,7 +599,7 @@ static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params)
|
|||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -617,7 +617,7 @@ static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params)
|
|||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -670,7 +670,7 @@ static cell_t sm_LogToOpenFile(IPluginContext *pContext, const cell_t *params)
|
|||||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -701,7 +701,7 @@ static cell_t sm_LogToOpenFileEx(IPluginContext *pContext, const cell_t *params)
|
|||||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -289,7 +289,7 @@ static cell_t PrintToChat(IPluginContext *pContext, const cell_t *params)
|
|||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
/* Check for an error before printing to the client */
|
/* Check for an error before printing to the client */
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -323,7 +323,7 @@ static cell_t PrintCenterText(IPluginContext *pContext, const cell_t *params)
|
|||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
/* Check for an error before printing to the client */
|
/* Check for an error before printing to the client */
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -357,7 +357,7 @@ static cell_t PrintHintText(IPluginContext *pContext, const cell_t *params)
|
|||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
/* Check for an error before printing to the client */
|
/* Check for an error before printing to the client */
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -371,7 +371,7 @@ static cell_t ShowSyncHudText(IPluginContext *pContext, const cell_t *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
|
g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -443,7 +443,7 @@ static cell_t ShowHudText(IPluginContext *pContext, const cell_t *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
|
g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1000,7 +1000,7 @@ static cell_t _ShowActivity(IPluginContext *pContext,
|
|||||||
g_SourceMod.SetGlobalTarget(client);
|
g_SourceMod.SetGlobalTarget(client);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1015,7 +1015,7 @@ static cell_t _ShowActivity(IPluginContext *pContext,
|
|||||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1054,7 +1054,7 @@ static cell_t _ShowActivity(IPluginContext *pContext,
|
|||||||
}
|
}
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1078,7 +1078,7 @@ static cell_t _ShowActivity(IPluginContext *pContext,
|
|||||||
}
|
}
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1123,7 +1123,7 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
|
|||||||
g_SourceMod.SetGlobalTarget(client);
|
g_SourceMod.SetGlobalTarget(client);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1152,7 +1152,7 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
|
|||||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1191,7 +1191,7 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
|
|||||||
}
|
}
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1215,7 +1215,7 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
|
|||||||
}
|
}
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1286,7 +1286,7 @@ static cell_t KickClient(IPluginContext *pContext, const cell_t *params)
|
|||||||
char buffer[256];
|
char buffer[256];
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1332,7 +1332,7 @@ static cell_t KickClientEx(IPluginContext *pContext, const cell_t *params)
|
|||||||
char buffer[256];
|
char buffer[256];
|
||||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||||
|
|
||||||
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -233,8 +233,7 @@ static cell_t sm_vformat(IPluginContext *pContext, const cell_t *params)
|
|||||||
int vargPos = static_cast<int>(params[4]);
|
int vargPos = static_cast<int>(params[4]);
|
||||||
|
|
||||||
/* Get the parent parameter array */
|
/* Get the parent parameter array */
|
||||||
sp_context_t *ctx = pContext->GetContext();
|
cell_t *local_params = pContext->GetLocalParams();
|
||||||
cell_t *local_params = (cell_t *)(ctx->memory + ctx->frm + (2 * sizeof(cell_t)));
|
|
||||||
|
|
||||||
cell_t max = local_params[0];
|
cell_t max = local_params[0];
|
||||||
if (vargPos > (int)max + 1)
|
if (vargPos > (int)max + 1)
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include "sourcemod.h"
|
#include "sourcemod.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "systems/LibrarySys.h"
|
#include "systems/LibrarySys.h"
|
||||||
#include "vm/sp_vm_engine.h"
|
|
||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include "PluginSys.h"
|
#include "PluginSys.h"
|
||||||
#include "ShareSys.h"
|
#include "ShareSys.h"
|
||||||
@ -47,27 +46,26 @@
|
|||||||
#include "ForwardSys.h"
|
#include "ForwardSys.h"
|
||||||
#include "TimerSys.h"
|
#include "TimerSys.h"
|
||||||
#include "GameConfigs.h"
|
#include "GameConfigs.h"
|
||||||
|
#include "DebugReporter.h"
|
||||||
|
#include "Profiler.h"
|
||||||
|
|
||||||
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
|
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
|
||||||
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
|
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
|
||||||
SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, false, bool);
|
SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, false, bool);
|
||||||
SH_DECL_HOOK1_void(IVEngineServer, ServerCommand, SH_NOATTRIB, false, const char *);
|
SH_DECL_HOOK1_void(IVEngineServer, ServerCommand, SH_NOATTRIB, false, const char *);
|
||||||
|
|
||||||
SourcePawnEngine g_SourcePawn;
|
|
||||||
SourceModBase g_SourceMod;
|
SourceModBase g_SourceMod;
|
||||||
|
|
||||||
ILibrary *g_pJIT = NULL;
|
ILibrary *g_pJIT = NULL;
|
||||||
SourceHook::String g_BaseDir;
|
SourceHook::String g_BaseDir;
|
||||||
ISourcePawnEngine *g_pSourcePawn = &g_SourcePawn;
|
ISourcePawnEngine *g_pSourcePawn = NULL;
|
||||||
IVirtualMachine *g_pVM;
|
ISourcePawnEngine2 *g_pSourcePawn2 = NULL;
|
||||||
IdentityToken_t *g_pCoreIdent = NULL;
|
IdentityToken_t *g_pCoreIdent = NULL;
|
||||||
IForward *g_pOnMapEnd = NULL;
|
IForward *g_pOnMapEnd = NULL;
|
||||||
bool g_Loaded = false;
|
bool g_Loaded = false;
|
||||||
|
|
||||||
typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *);
|
typedef ISourcePawnEngine *(*GET_SP_V1)();
|
||||||
typedef int (*GIVEENGINEPOINTER2)(ISourcePawnEngine *, unsigned int api_version);
|
typedef ISourcePawnEngine2 *(*GET_SP_V2)();
|
||||||
typedef unsigned int (*GETEXPORTCOUNT)();
|
|
||||||
typedef IVirtualMachine *(*GETEXPORT)(unsigned int);
|
|
||||||
typedef void (*NOTIFYSHUTDOWN)();
|
typedef void (*NOTIFYSHUTDOWN)();
|
||||||
|
|
||||||
void ShutdownJIT()
|
void ShutdownJIT()
|
||||||
@ -165,105 +163,34 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int err;
|
GET_SP_V1 getv1 = (GET_SP_V1)g_pJIT->GetSymbolAddress("GetSourcePawnEngine1");
|
||||||
|
GET_SP_V2 getv2 = (GET_SP_V2)g_pJIT->GetSymbolAddress("GetSourcePawnEngine2");
|
||||||
GIVEENGINEPOINTER2 jit_init2 = (GIVEENGINEPOINTER2)g_pJIT->GetSymbolAddress("GiveEnginePointer2");
|
|
||||||
if (!jit_init2)
|
|
||||||
{
|
|
||||||
GIVEENGINEPOINTER jit_init = (GIVEENGINEPOINTER)g_pJIT->GetSymbolAddress("GiveEnginePointer");
|
|
||||||
if (!jit_init)
|
|
||||||
{
|
|
||||||
ShutdownJIT();
|
|
||||||
if (error && maxlength)
|
|
||||||
{
|
|
||||||
snprintf(error, maxlength, "Failed to find GiveEnginePointer in JIT!");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err=jit_init(g_pSourcePawn)) != 0)
|
if (getv1 == NULL)
|
||||||
{
|
|
||||||
ShutdownJIT();
|
|
||||||
if (error && maxlength)
|
|
||||||
{
|
|
||||||
snprintf(error, maxlength, "GiveEnginePointer returned %d in the JIT", err);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* On version bumps, we should check for older versions as well, if the new version fails.
|
|
||||||
* We can then check the exports to see if any VM versions will be sufficient.
|
|
||||||
*/
|
|
||||||
if ((err=jit_init2(g_pSourcePawn, SOURCEPAWN_ENGINE_API_VERSION)) != SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
ShutdownJIT();
|
|
||||||
if (error && maxlength)
|
|
||||||
{
|
|
||||||
snprintf(error, maxlength, "JIT incompatible with SourceMod version");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GETEXPORTCOUNT jit_getnum = (GETEXPORTCOUNT)g_pJIT->GetSymbolAddress("GetExportCount");
|
|
||||||
GETEXPORT jit_get = (GETEXPORT)g_pJIT->GetSymbolAddress("GetExport");
|
|
||||||
if (!jit_get)
|
|
||||||
{
|
|
||||||
ShutdownJIT();
|
|
||||||
if (error && maxlength)
|
if (error && maxlength)
|
||||||
{
|
{
|
||||||
snprintf(error, maxlength, "JIT is missing a necessary export!");
|
snprintf(error, maxlength, "JIT is too old; upgrade SourceMod");
|
||||||
}
|
}
|
||||||
|
ShutdownJIT();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else if (getv2 == NULL)
|
||||||
unsigned int num = jit_getnum();
|
|
||||||
if (!num)
|
|
||||||
{
|
{
|
||||||
ShutdownJIT();
|
|
||||||
if (error && maxlength)
|
if (error && maxlength)
|
||||||
{
|
{
|
||||||
snprintf(error, maxlength, "JIT did not export any virtual machines!");
|
snprintf(error, maxlength, "JIT is too old; upgrade SourceMod");
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int api_version;
|
|
||||||
for (unsigned int i=0; i<num; i++)
|
|
||||||
{
|
|
||||||
if ((g_pVM=jit_get(i)) == NULL)
|
|
||||||
{
|
|
||||||
if (error && maxlength)
|
|
||||||
{
|
|
||||||
snprintf(error, maxlength, "JIT did not export any virtual machines!");
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Refuse any API that we might not be able to deal with.
|
|
||||||
* <s>Also refuse anything < 3 because we need fake natives.</s>
|
|
||||||
* Also refuse anything < 7 because we need the new sp_native definition.
|
|
||||||
*/
|
|
||||||
api_version = g_pVM->GetAPIVersion();
|
|
||||||
if (api_version < 7 || api_version > SOURCEPAWN_VM_API_VERSION)
|
|
||||||
{
|
|
||||||
if (error && maxlength)
|
|
||||||
{
|
|
||||||
snprintf(error, maxlength, "JIT is not a compatible version");
|
|
||||||
}
|
|
||||||
g_pVM = NULL;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_pVM)
|
|
||||||
{
|
|
||||||
ShutdownJIT();
|
ShutdownJIT();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_pSourcePawn = getv1();
|
||||||
|
g_pSourcePawn2 = getv2();
|
||||||
|
|
||||||
|
g_pSourcePawn2->SetDebugListener(&g_DbgReporter);
|
||||||
|
g_pSourcePawn2->SetProfiler(&g_Profiler);
|
||||||
|
|
||||||
/* Hook this now so we can detect startup without calling StartSourceMod() */
|
/* Hook this now so we can detect startup without calling StartSourceMod() */
|
||||||
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SourceModBase::LevelInit, false);
|
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SourceModBase::LevelInit, false);
|
||||||
|
|
||||||
@ -663,7 +590,7 @@ ISourcePawnEngine *SourceModBase::GetScriptingEngine()
|
|||||||
|
|
||||||
IVirtualMachine *SourceModBase::GetScriptingVM()
|
IVirtualMachine *SourceModBase::GetScriptingVM()
|
||||||
{
|
{
|
||||||
return g_pVM;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceModBase::AllPluginsLoaded()
|
void SourceModBase::AllPluginsLoaded()
|
||||||
|
@ -990,7 +990,7 @@ bool HandleSystem::TryAndFreeSomeHandles()
|
|||||||
g_Logger.LogFatal("[SM] Reloading plugin to free %d handles.", highest_handle_count);
|
g_Logger.LogFatal("[SM] Reloading plugin to free %d handles.", highest_handle_count);
|
||||||
g_Logger.LogFatal("[SM] Contact the author(s) of this plugin to correct this error.", highest_handle_count);
|
g_Logger.LogFatal("[SM] Contact the author(s) of this plugin to correct this error.", highest_handle_count);
|
||||||
|
|
||||||
highest_owner->GetContext()->n_err = SP_ERROR_MEMACCESS;
|
highest_owner->GetBaseContext()->ThrowNativeErrorEx(SP_ERROR_MEMACCESS, "Memory leak");
|
||||||
|
|
||||||
return g_PluginSys.UnloadPlugin(highest_owner);
|
return g_PluginSys.UnloadPlugin(highest_owner);
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ CPlugin::CPlugin(const char *file)
|
|||||||
m_type = PluginType_Private;
|
m_type = PluginType_Private;
|
||||||
m_status = Plugin_Uncompiled;
|
m_status = Plugin_Uncompiled;
|
||||||
m_serial = ++MySerial;
|
m_serial = ++MySerial;
|
||||||
m_plugin = NULL;
|
m_pRuntime = NULL;
|
||||||
m_errormsg[256] = '\0';
|
m_errormsg[256] = '\0';
|
||||||
snprintf(m_filename, sizeof(m_filename), "%s", file);
|
snprintf(m_filename, sizeof(m_filename), "%s", file);
|
||||||
m_handle = 0;
|
m_handle = 0;
|
||||||
@ -82,27 +82,12 @@ CPlugin::~CPlugin()
|
|||||||
g_ShareSys.DestroyIdentity(m_ident);
|
g_ShareSys.DestroyIdentity(m_ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_ctx.base)
|
if (m_pRuntime != NULL)
|
||||||
{
|
{
|
||||||
delete m_ctx.base;
|
delete m_pRuntime;
|
||||||
m_ctx.base = NULL;
|
m_pRuntime = NULL;
|
||||||
}
|
|
||||||
if (m_ctx.ctx)
|
|
||||||
{
|
|
||||||
m_ctx.vm->FreeContext(m_ctx.ctx);
|
|
||||||
m_ctx.ctx = NULL;
|
|
||||||
}
|
|
||||||
if (m_ctx.co)
|
|
||||||
{
|
|
||||||
m_ctx.vm->AbortCompilation(m_ctx.co);
|
|
||||||
m_ctx.co = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_plugin)
|
|
||||||
{
|
|
||||||
g_pSourcePawn->FreeFromMemory(m_plugin);
|
|
||||||
m_plugin = NULL;
|
|
||||||
}
|
|
||||||
if (m_pProps)
|
if (m_pProps)
|
||||||
{
|
{
|
||||||
sm_trie_destroy(m_pProps);
|
sm_trie_destroy(m_pProps);
|
||||||
@ -125,7 +110,8 @@ void CPlugin::InitIdentity()
|
|||||||
{
|
{
|
||||||
m_ident = g_ShareSys.CreateIdentity(g_PluginIdent, this);
|
m_ident = g_ShareSys.CreateIdentity(g_PluginIdent, this);
|
||||||
m_handle = g_HandleSys.CreateHandle(g_PluginType, this, g_PluginSys.GetIdentity(), g_PluginSys.GetIdentity(), NULL);
|
m_handle = g_HandleSys.CreateHandle(g_PluginType, this, g_PluginSys.GetIdentity(), g_PluginSys.GetIdentity(), NULL);
|
||||||
m_ctx.base->SetIdentity(m_ident);
|
m_pRuntime->GetDefaultContext()->SetKey(1, m_ident);
|
||||||
|
m_pRuntime->GetDefaultContext()->SetKey(2, (IPlugin *)this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,37 +143,6 @@ unsigned int CPlugin::CalcMemUsage()
|
|||||||
base_size += (*i).size();
|
base_size += (*i).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_plugin != NULL)
|
|
||||||
{
|
|
||||||
base_size += sizeof(sp_plugin_t);
|
|
||||||
base_size += m_plugin->data_size;
|
|
||||||
base_size += m_plugin->pcode_size;
|
|
||||||
base_size += (m_plugin->info.natives_num * sizeof(sp_file_natives_t));
|
|
||||||
base_size += (m_plugin->info.publics_num * sizeof(sp_file_publics_t));
|
|
||||||
base_size += (m_plugin->info.pubvars_num * sizeof(sp_file_pubvars_t));
|
|
||||||
base_size += (m_plugin->debug.files_num * sizeof(sp_fdbg_file_t));
|
|
||||||
base_size += (m_plugin->debug.lines_num * sizeof(sp_fdbg_line_t));
|
|
||||||
base_size += (m_plugin->debug.syms_num * sizeof(sp_fdbg_symbol_t));
|
|
||||||
/* We can't get strtab size, oh well. */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ctx.base != NULL)
|
|
||||||
{
|
|
||||||
base_size += sizeof(BaseContext);
|
|
||||||
base_size += m_ctx.base->GetPublicsNum() * sizeof(CFunction);
|
|
||||||
}
|
|
||||||
if (m_ctx.ctx != NULL)
|
|
||||||
{
|
|
||||||
base_size += m_ctx.ctx->mem_size;
|
|
||||||
base_size += (m_plugin->debug.files_num * sizeof(sp_debug_file_t));
|
|
||||||
base_size += (m_plugin->debug.lines_num * sizeof(sp_debug_line_t));
|
|
||||||
base_size += (m_plugin->debug.syms_num * sizeof(sp_debug_symbol_t));
|
|
||||||
base_size += (m_plugin->info.pubvars_num * sizeof(sp_pubvar_t));
|
|
||||||
base_size += (m_plugin->info.publics_num * sizeof(sp_public_t));
|
|
||||||
base_size += (m_plugin->info.natives_num * sizeof(sp_native_t));
|
|
||||||
/* We also don't know the JIT code size, oh well. */
|
|
||||||
}
|
|
||||||
|
|
||||||
return base_size;
|
return base_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,23 +169,6 @@ CPlugin *CPlugin::CreatePlugin(const char *file, char *error, size_t maxlength)
|
|||||||
return pPlugin;
|
return pPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
int err;
|
|
||||||
sp_plugin_t *pl = g_pSourcePawn->LoadFromFilePointer(fp, &err);
|
|
||||||
if (pl == NULL)
|
|
||||||
{
|
|
||||||
fclose(fp);
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
snprintf(error, maxlength, "Error %d while parsing plugin", err);
|
|
||||||
}
|
|
||||||
pPlugin->m_status = Plugin_BadLoad;
|
|
||||||
return pPlugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
pPlugin->m_plugin = pl;
|
|
||||||
|
|
||||||
return pPlugin;
|
return pPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,69 +189,9 @@ bool CPlugin::SetProperty(const char *prop, void *ptr)
|
|||||||
return sm_trie_insert(m_pProps, prop, ptr);
|
return sm_trie_insert(m_pProps, prop, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ICompilation *CPlugin::StartMyCompile(IVirtualMachine *vm)
|
IPluginRuntime *CPlugin::GetRuntime()
|
||||||
{
|
{
|
||||||
if (!m_plugin)
|
return m_pRuntime;
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* :NOTICE: We will eventually need to change these natives
|
|
||||||
* for swapping in new contexts
|
|
||||||
*/
|
|
||||||
if (m_ctx.co || m_ctx.ctx)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_status = Plugin_Uncompiled;
|
|
||||||
|
|
||||||
m_ctx.vm = vm;
|
|
||||||
m_ctx.co = vm->StartCompilation(m_plugin);
|
|
||||||
|
|
||||||
return m_ctx.co;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPlugin::CancelMyCompile()
|
|
||||||
{
|
|
||||||
if (!m_ctx.co)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ctx.vm->AbortCompilation(m_ctx.co);
|
|
||||||
m_ctx.co = NULL;
|
|
||||||
m_ctx.vm = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CPlugin::FinishMyCompile(char *error, size_t maxlength)
|
|
||||||
{
|
|
||||||
if (!m_ctx.co)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int err;
|
|
||||||
m_ctx.ctx = m_ctx.vm->CompileToContext(m_ctx.co, &err);
|
|
||||||
if (!m_ctx.ctx)
|
|
||||||
{
|
|
||||||
memset(&m_ctx, 0, sizeof(m_ctx));
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
snprintf(error, maxlength, "JIT failed to compile (error %d)", err);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ctx.base = new BaseContext(m_ctx.ctx);
|
|
||||||
m_ctx.ctx->user[SM_CONTEXTVAR_MYSELF] = (void *)this;
|
|
||||||
|
|
||||||
m_status = Plugin_Created;
|
|
||||||
m_ctx.co = NULL;
|
|
||||||
|
|
||||||
UpdateInfo();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlugin::SetErrorState(PluginStatus status, const char *error_fmt, ...)
|
void CPlugin::SetErrorState(PluginStatus status, const char *error_fmt, ...)
|
||||||
@ -332,9 +210,9 @@ void CPlugin::SetErrorState(PluginStatus status, const char *error_fmt, ...)
|
|||||||
vsnprintf(m_errormsg, sizeof(m_errormsg), error_fmt, ap);
|
vsnprintf(m_errormsg, sizeof(m_errormsg), error_fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (m_ctx.ctx)
|
if (m_pRuntime != NULL)
|
||||||
{
|
{
|
||||||
m_ctx.ctx->flags |= SPFLAG_PLUGIN_PAUSED;
|
m_pRuntime->SetPauseState(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +293,7 @@ void CPlugin::Call_OnPluginStart()
|
|||||||
m_status = Plugin_Running;
|
m_status = Plugin_Running;
|
||||||
|
|
||||||
cell_t result;
|
cell_t result;
|
||||||
IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnPluginStart");
|
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnPluginStart");
|
||||||
if (!pFunction)
|
if (!pFunction)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -436,7 +314,7 @@ void CPlugin::Call_OnPluginEnd()
|
|||||||
}
|
}
|
||||||
|
|
||||||
cell_t result;
|
cell_t result;
|
||||||
IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnPluginEnd");
|
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnPluginEnd");
|
||||||
if (!pFunction)
|
if (!pFunction)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -460,7 +338,7 @@ void CPlugin::Call_OnAllPluginsLoaded()
|
|||||||
m_bGotAllLoaded = true;
|
m_bGotAllLoaded = true;
|
||||||
|
|
||||||
cell_t result;
|
cell_t result;
|
||||||
IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnAllPluginsLoaded");
|
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnAllPluginsLoaded");
|
||||||
if (pFunction != NULL)
|
if (pFunction != NULL)
|
||||||
{
|
{
|
||||||
pFunction->Execute(&result);
|
pFunction->Execute(&result);
|
||||||
@ -468,7 +346,7 @@ void CPlugin::Call_OnAllPluginsLoaded()
|
|||||||
|
|
||||||
if (g_OnMapStarted)
|
if (g_OnMapStarted)
|
||||||
{
|
{
|
||||||
if ((pFunction = m_ctx.base->GetFunctionByName("OnMapStart")) != NULL)
|
if ((pFunction = m_pRuntime->GetFunctionByName("OnMapStart")) != NULL)
|
||||||
{
|
{
|
||||||
pFunction->Execute(NULL);
|
pFunction->Execute(NULL);
|
||||||
}
|
}
|
||||||
@ -491,7 +369,7 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
|
|||||||
|
|
||||||
int err;
|
int err;
|
||||||
cell_t result;
|
cell_t result;
|
||||||
IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("AskPluginLoad");
|
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad");
|
||||||
|
|
||||||
if (!pFunction)
|
if (!pFunction)
|
||||||
{
|
{
|
||||||
@ -515,19 +393,24 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sp_plugin_t *CPlugin::GetPluginStructure()
|
void *CPlugin::GetPluginStructure()
|
||||||
{
|
{
|
||||||
return m_plugin;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPluginContext *CPlugin::GetBaseContext()
|
IPluginContext *CPlugin::GetBaseContext()
|
||||||
{
|
{
|
||||||
return m_ctx.base;
|
if (m_pRuntime == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_pRuntime->GetDefaultContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
sp_context_t *CPlugin::GetContext()
|
sp_context_t *CPlugin::GetContext()
|
||||||
{
|
{
|
||||||
return m_ctx.ctx;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CPlugin::GetFilename()
|
const char *CPlugin::GetFilename()
|
||||||
@ -557,12 +440,12 @@ PluginStatus CPlugin::GetStatus()
|
|||||||
|
|
||||||
bool CPlugin::IsDebugging()
|
bool CPlugin::IsDebugging()
|
||||||
{
|
{
|
||||||
if (!m_ctx.ctx)
|
if (m_pRuntime == NULL)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((m_ctx.ctx->flags & SP_FLAG_DEBUG) == SP_FLAG_DEBUG);
|
return m_pRuntime->IsDebugging();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlugin::LibraryActions(bool dropping)
|
void CPlugin::LibraryActions(bool dropping)
|
||||||
@ -590,7 +473,7 @@ bool CPlugin::SetPauseState(bool paused)
|
|||||||
LibraryActions(true);
|
LibraryActions(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnPluginPauseChange");
|
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnPluginPauseChange");
|
||||||
if (pFunction)
|
if (pFunction)
|
||||||
{
|
{
|
||||||
cell_t result;
|
cell_t result;
|
||||||
@ -601,10 +484,10 @@ bool CPlugin::SetPauseState(bool paused)
|
|||||||
if (paused)
|
if (paused)
|
||||||
{
|
{
|
||||||
m_status = Plugin_Paused;
|
m_status = Plugin_Paused;
|
||||||
m_ctx.ctx->flags |= SPFLAG_PLUGIN_PAUSED;
|
m_pRuntime->SetPauseState(true);
|
||||||
} else {
|
} else {
|
||||||
m_status = Plugin_Running;
|
m_status = Plugin_Running;
|
||||||
m_ctx.ctx->flags &= ~SPFLAG_PLUGIN_PAUSED;
|
m_pRuntime->SetPauseState(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_PluginSys._SetPauseState(this, paused);
|
g_PluginSys._SetPauseState(this, paused);
|
||||||
@ -652,8 +535,9 @@ bool CPlugin::ToggleDebugMode(bool debug, char *error, size_t maxlength)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ICompilation *co = g_pVM->StartCompilation(m_ctx.ctx->plugin);
|
ICompilation *co = g_pSourcePawn2->StartCompilation();
|
||||||
if (!g_pVM->SetCompilationOption(co, "debug", (debug) ? "1" : "0"))
|
|
||||||
|
if (!co->SetOption("debug", (debug) ? "1" : "0"))
|
||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@ -662,32 +546,7 @@ bool CPlugin::ToggleDebugMode(bool debug, char *error, size_t maxlength)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp_context_t *new_ctx = g_pVM->CompileToContext(co, &err);
|
if ((err = m_pRuntime->ApplyCompilationOptions(co)) != SP_ERROR_NONE)
|
||||||
|
|
||||||
if (new_ctx)
|
|
||||||
{
|
|
||||||
memcpy(new_ctx->memory, m_ctx.ctx->memory, m_ctx.ctx->mem_size);
|
|
||||||
new_ctx->hp = m_ctx.ctx->hp;
|
|
||||||
new_ctx->sp = m_ctx.ctx->sp;
|
|
||||||
new_ctx->frm = m_ctx.ctx->frm;
|
|
||||||
new_ctx->dbreak = m_ctx.ctx->dbreak;
|
|
||||||
new_ctx->context = m_ctx.ctx->context;
|
|
||||||
memcpy(new_ctx->user, m_ctx.ctx->user, sizeof(m_ctx.ctx->user));
|
|
||||||
|
|
||||||
uint32_t nativeCount = m_plugin->info.natives_num;
|
|
||||||
for (uint32_t i=0; i<nativeCount; i++)
|
|
||||||
{
|
|
||||||
new_ctx->natives[i].pfn = m_ctx.ctx->natives[i].pfn;
|
|
||||||
new_ctx->natives[i].status = m_ctx.ctx->natives[i].status;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_pVM->FreeContext(m_ctx.ctx);
|
|
||||||
m_ctx.ctx = new_ctx;
|
|
||||||
m_ctx.base->SetContext(new_ctx);
|
|
||||||
|
|
||||||
UpdateInfo();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@ -696,6 +555,8 @@ bool CPlugin::ToggleDebugMode(bool debug, char *error, size_t maxlength)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateInfo();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,7 +602,7 @@ IPhraseCollection *CPlugin::GetPhrases()
|
|||||||
|
|
||||||
void CPlugin::DependencyDropped(CPlugin *pOwner)
|
void CPlugin::DependencyDropped(CPlugin *pOwner)
|
||||||
{
|
{
|
||||||
if (!m_ctx.ctx)
|
if (!m_pRuntime)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -771,12 +632,12 @@ void CPlugin::DependencyDropped(CPlugin *pOwner)
|
|||||||
{
|
{
|
||||||
pNative = (*iter);
|
pNative = (*iter);
|
||||||
/* Find this native! */
|
/* Find this native! */
|
||||||
if (m_ctx.base->FindNativeByName(pNative->name, &idx) != SP_ERROR_NONE)
|
if (m_pRuntime->FindNativeByName(pNative->name, &idx) != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Unbind it */
|
/* Unbind it */
|
||||||
m_ctx.base->GetNativeByIndex(idx, &native);
|
m_pRuntime->GetNativeByIndex(idx, &native);
|
||||||
native->pfn = NULL;
|
native->pfn = NULL;
|
||||||
native->status = SP_NATIVE_UNBOUND;
|
native->status = SP_NATIVE_UNBOUND;
|
||||||
unbound++;
|
unbound++;
|
||||||
@ -1047,6 +908,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
|||||||
return LoadRes_NeverLoad;
|
return LoadRes_NeverLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int err;
|
||||||
bool no_load = false;
|
bool no_load = false;
|
||||||
PluginSettings *pset;
|
PluginSettings *pset;
|
||||||
unsigned int setcount = m_PluginInfo.GetSettingsNum();
|
unsigned int setcount = m_PluginInfo.GetSettingsNum();
|
||||||
@ -1102,7 +964,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
|||||||
|
|
||||||
if (pPlugin->m_status == Plugin_Uncompiled)
|
if (pPlugin->m_status == Plugin_Uncompiled)
|
||||||
{
|
{
|
||||||
co = pPlugin->StartMyCompile(g_pVM);
|
co = g_pSourcePawn2->StartCompilation();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i=0; i<setcount; i++)
|
for (unsigned int i=0; i<setcount; i++)
|
||||||
@ -1122,13 +984,13 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!g_pVM->SetCompilationOption(co, key, val))
|
if ((err = co->SetOption(key, val)) == SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
snprintf(error, maxlength, "Unable to set JIT option (key \"%s\") (value \"%s\")", key, val);
|
snprintf(error, maxlength, "Unable to set JIT option (key \"%s\") (value \"%s\")", key, val);
|
||||||
}
|
}
|
||||||
pPlugin->CancelMyCompile();
|
co->Abort();
|
||||||
co = NULL;
|
co = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1137,10 +999,25 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do the actual compiling */
|
/* Do the actual compiling */
|
||||||
if (co)
|
if (co != NULL)
|
||||||
{
|
{
|
||||||
pPlugin->FinishMyCompile(error, maxlength);
|
char fullpath[PLATFORM_MAX_PATH];
|
||||||
co = NULL;
|
g_SourceMod.BuildPath(Path_SM, fullpath, sizeof(fullpath), "plugins/%s", pPlugin->m_filename);
|
||||||
|
|
||||||
|
pPlugin->m_pRuntime = g_pSourcePawn2->LoadPlugin(co, fullpath, &err);
|
||||||
|
if (pPlugin->m_pRuntime == NULL)
|
||||||
|
{
|
||||||
|
snprintf(error,
|
||||||
|
maxlength,
|
||||||
|
"Unable to load plugin (error %d: %s)",
|
||||||
|
err,
|
||||||
|
g_pSourcePawn2->GetErrorString(err));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pPlugin->UpdateInfo();
|
||||||
|
pPlugin->m_status = Plugin_Created;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the status */
|
/* Get the status */
|
||||||
@ -1321,7 +1198,7 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size
|
|||||||
{
|
{
|
||||||
cell_t res;
|
cell_t res;
|
||||||
pFunc->Execute(&res);
|
pFunc->Execute(&res);
|
||||||
if (pPlugin->GetContext()->n_err != SP_ERROR_NONE)
|
if (pPlugin->GetBaseContext()->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@ -1448,7 +1325,7 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass
|
|||||||
{
|
{
|
||||||
cell_t res;
|
cell_t res;
|
||||||
pFunc->Execute(&res);
|
pFunc->Execute(&res);
|
||||||
if (pPlugin->GetContext()->n_err != SP_ERROR_NONE)
|
if (pPlugin->GetBaseContext()->GetLastNativeError() != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@ -1615,9 +1492,9 @@ void CPluginManager::TryRefreshDependencies(CPlugin *pPlugin)
|
|||||||
{
|
{
|
||||||
/* If we got here, all natives are okay again! */
|
/* If we got here, all natives are okay again! */
|
||||||
pPlugin->m_status = Plugin_Running;
|
pPlugin->m_status = Plugin_Running;
|
||||||
if ((pPlugin->m_ctx.ctx->flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED)
|
if (pPlugin->m_pRuntime->IsPaused())
|
||||||
{
|
{
|
||||||
pPlugin->m_ctx.ctx->flags &= ~SPFLAG_PLUGIN_PAUSED;
|
pPlugin->m_pRuntime->SetPauseState(false);
|
||||||
_SetPauseState(pPlugin, false);
|
_SetPauseState(pPlugin, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1687,8 +1564,22 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin)
|
|||||||
|
|
||||||
IPlugin *CPluginManager::FindPluginByContext(const sp_context_t *ctx)
|
IPlugin *CPluginManager::FindPluginByContext(const sp_context_t *ctx)
|
||||||
{
|
{
|
||||||
IPlugin *pl = (IPlugin *)ctx->user[SM_CONTEXTVAR_MYSELF];
|
IPlugin *pPlugin;
|
||||||
return pl;
|
IPluginContext *pContext;
|
||||||
|
|
||||||
|
pContext = reinterpret_cast<IPluginContext *>(const_cast<sp_context_t *>(ctx));
|
||||||
|
|
||||||
|
if (pContext->GetKey(2, (void **)&pPlugin))
|
||||||
|
{
|
||||||
|
return pPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPlugin *CPluginManager::GetPluginByCtx(const sp_context_t *ctx)
|
||||||
|
{
|
||||||
|
return (CPlugin *)FindPluginByContext(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CPluginManager::GetPluginCount()
|
unsigned int CPluginManager::GetPluginCount()
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
#include <sh_vector.h>
|
#include <sh_vector.h>
|
||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include "vm/sp_vm_basecontext.h"
|
|
||||||
#include "PluginInfoDatabase.h"
|
#include "PluginInfoDatabase.h"
|
||||||
#include "sm_trie.h"
|
#include "sm_trie.h"
|
||||||
#include "sourcemod.h"
|
#include "sourcemod.h"
|
||||||
@ -109,19 +108,6 @@ using namespace SourceHook;
|
|||||||
* 7. Once all plugins are deemed to be loaded, OnPluginStart() is called
|
* 7. Once all plugins are deemed to be loaded, OnPluginStart() is called
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SM_CONTEXTVAR_MYSELF 0
|
|
||||||
|
|
||||||
struct ContextPair
|
|
||||||
{
|
|
||||||
ContextPair() : base(NULL), ctx(NULL), co(NULL)
|
|
||||||
{
|
|
||||||
};
|
|
||||||
BaseContext *base;
|
|
||||||
sp_context_t *ctx;
|
|
||||||
ICompilation *co;
|
|
||||||
IVirtualMachine *vm;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum LoadRes
|
enum LoadRes
|
||||||
{
|
{
|
||||||
LoadRes_Successful,
|
LoadRes_Successful,
|
||||||
@ -152,18 +138,19 @@ public:
|
|||||||
PluginType GetType();
|
PluginType GetType();
|
||||||
SourcePawn::IPluginContext *GetBaseContext();
|
SourcePawn::IPluginContext *GetBaseContext();
|
||||||
sp_context_t *GetContext();
|
sp_context_t *GetContext();
|
||||||
const sm_plugininfo_t *GetPublicInfo();
|
void *GetPluginStructure();
|
||||||
const char *GetFilename();
|
const char *GetFilename();
|
||||||
bool IsDebugging();
|
bool IsDebugging();
|
||||||
PluginStatus GetStatus();
|
PluginStatus GetStatus();
|
||||||
|
const sm_plugininfo_t *GetPublicInfo();
|
||||||
bool SetPauseState(bool paused);
|
bool SetPauseState(bool paused);
|
||||||
unsigned int GetSerial();
|
unsigned int GetSerial();
|
||||||
const sp_plugin_t *GetPluginStructure();
|
|
||||||
IdentityToken_t *GetIdentity();
|
IdentityToken_t *GetIdentity();
|
||||||
unsigned int CalcMemUsage();
|
unsigned int CalcMemUsage();
|
||||||
bool SetProperty(const char *prop, void *ptr);
|
bool SetProperty(const char *prop, void *ptr);
|
||||||
bool GetProperty(const char *prop, void **ptr, bool remove=false);
|
bool GetProperty(const char *prop, void **ptr, bool remove=false);
|
||||||
void DropEverything();
|
void DropEverything();
|
||||||
|
SourcePawn::IPluginRuntime *GetRuntime();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Creates a plugin object with default values.
|
* Creates a plugin object with default values.
|
||||||
@ -174,16 +161,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
static CPlugin *CreatePlugin(const char *file, char *error, size_t maxlength);
|
static CPlugin *CreatePlugin(const char *file, char *error, size_t maxlength);
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* Starts the initial compilation of a plugin.
|
|
||||||
* Returns false if another compilation exists or there is a current context set.
|
|
||||||
*/
|
|
||||||
ICompilation *StartMyCompile(IVirtualMachine *vm);
|
|
||||||
/**
|
|
||||||
* Finalizes a compilation. If error buffer is NULL, the error is saved locally.
|
|
||||||
*/
|
|
||||||
bool FinishMyCompile(char *error, size_t maxlength);
|
|
||||||
void CancelMyCompile();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets an error state on the plugin
|
* Sets an error state on the plugin
|
||||||
@ -267,13 +244,11 @@ protected:
|
|||||||
void SetTimeStamp(time_t t);
|
void SetTimeStamp(time_t t);
|
||||||
void DependencyDropped(CPlugin *pOwner);
|
void DependencyDropped(CPlugin *pOwner);
|
||||||
private:
|
private:
|
||||||
ContextPair m_ctx;
|
|
||||||
PluginType m_type;
|
PluginType m_type;
|
||||||
char m_filename[PLATFORM_MAX_PATH];
|
char m_filename[PLATFORM_MAX_PATH];
|
||||||
PluginStatus m_status;
|
PluginStatus m_status;
|
||||||
unsigned int m_serial;
|
unsigned int m_serial;
|
||||||
sm_plugininfo_t m_info;
|
sm_plugininfo_t m_info;
|
||||||
sp_plugin_t *m_plugin;
|
|
||||||
char m_errormsg[256];
|
char m_errormsg[256];
|
||||||
time_t m_LastAccess;
|
time_t m_LastAccess;
|
||||||
IdentityToken_t *m_ident;
|
IdentityToken_t *m_ident;
|
||||||
@ -289,6 +264,8 @@ private:
|
|||||||
bool m_bGotAllLoaded;
|
bool m_bGotAllLoaded;
|
||||||
int m_FileVersion;
|
int m_FileVersion;
|
||||||
char m_DateTime[256];
|
char m_DateTime[256];
|
||||||
|
IPluginRuntime *m_pRuntime;
|
||||||
|
IPluginContext *m_pContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CPluginManager :
|
class CPluginManager :
|
||||||
@ -382,10 +359,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Internal version of FindPluginByContext()
|
* Internal version of FindPluginByContext()
|
||||||
*/
|
*/
|
||||||
inline CPlugin *GetPluginByCtx(const sp_context_t *ctx)
|
CPlugin *GetPluginByCtx(const sp_context_t *ctx);
|
||||||
{
|
|
||||||
return reinterpret_cast<CPlugin *>(ctx->user[SM_CONTEXTVAR_MYSELF]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets status text for a status code
|
* Gets status text for a status code
|
||||||
|
@ -488,7 +488,7 @@ NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name
|
|||||||
|
|
||||||
pFake = new FakeNative;
|
pFake = new FakeNative;
|
||||||
|
|
||||||
if ((gate = g_pVM->CreateFakeNative(func, pFake)) == NULL)
|
if ((gate = g_pSourcePawn2->CreateFakeNative(func, pFake)) == NULL)
|
||||||
{
|
{
|
||||||
delete pFake;
|
delete pFake;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,124 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourcePawn
|
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
|
|
||||||
#define _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
|
|
||||||
|
|
||||||
#include "sp_vm_api.h"
|
|
||||||
#include "sp_vm_function.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* :TODO: Make functions allocate as a lump instead of individual allocations!
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern IProfiler *sm_profiler;
|
|
||||||
|
|
||||||
namespace SourcePawn
|
|
||||||
{
|
|
||||||
class BaseContext :
|
|
||||||
public IPluginContext,
|
|
||||||
public IPluginDebugInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BaseContext(sp_context_t *ctx);
|
|
||||||
~BaseContext();
|
|
||||||
public: //IPluginContext
|
|
||||||
IVirtualMachine *GetVirtualMachine();
|
|
||||||
sp_context_t *GetContext();
|
|
||||||
bool IsDebugging();
|
|
||||||
int SetDebugBreak(SPVM_DEBUGBREAK newpfn, SPVM_DEBUGBREAK *oldpfn);
|
|
||||||
IPluginDebugInfo *GetDebugInfo();
|
|
||||||
int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr);
|
|
||||||
int HeapPop(cell_t local_addr);
|
|
||||||
int HeapRelease(cell_t local_addr);
|
|
||||||
int FindNativeByName(const char *name, uint32_t *index);
|
|
||||||
int GetNativeByIndex(uint32_t index, sp_native_t **native);
|
|
||||||
uint32_t GetNativesNum();
|
|
||||||
int FindPublicByName(const char *name, uint32_t *index);
|
|
||||||
int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
|
|
||||||
uint32_t GetPublicsNum();
|
|
||||||
int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
|
|
||||||
int FindPubvarByName(const char *name, uint32_t *index);
|
|
||||||
int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
|
|
||||||
uint32_t GetPubVarsNum();
|
|
||||||
int LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr);
|
|
||||||
int LocalToString(cell_t local_addr, char **addr);
|
|
||||||
int StringToLocal(cell_t local_addr, size_t chars, const char *source);
|
|
||||||
int StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes);
|
|
||||||
int PushCell(cell_t value);
|
|
||||||
int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells);
|
|
||||||
int PushString(cell_t *local_addr, char **phys_addr, const char *string);
|
|
||||||
int PushCellsFromArray(cell_t array[], unsigned int numcells);
|
|
||||||
int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite);
|
|
||||||
int BindNative(const sp_nativeinfo_t *native);
|
|
||||||
int BindNativeToAny(SPVM_NATIVE_FUNC native);
|
|
||||||
int Execute(uint32_t code_addr, cell_t *result);
|
|
||||||
cell_t ThrowNativeErrorEx(int error, const char *msg, ...);
|
|
||||||
cell_t ThrowNativeError(const char *msg, ...);
|
|
||||||
IPluginFunction *GetFunctionByName(const char *public_name);
|
|
||||||
IPluginFunction *GetFunctionById(funcid_t func_id);
|
|
||||||
#if defined SOURCEMOD_BUILD
|
|
||||||
SourceMod::IdentityToken_t *GetIdentity();
|
|
||||||
void SetIdentity(SourceMod::IdentityToken_t *token);
|
|
||||||
cell_t *GetNullRef(SP_NULL_TYPE type);
|
|
||||||
int LocalToStringNULL(cell_t local_addr, char **addr);
|
|
||||||
#endif
|
|
||||||
int BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC native);
|
|
||||||
public: //IPluginDebugInfo
|
|
||||||
int LookupFile(ucell_t addr, const char **filename);
|
|
||||||
int LookupFunction(ucell_t addr, const char **name);
|
|
||||||
int LookupLine(ucell_t addr, uint32_t *line);
|
|
||||||
public:
|
|
||||||
void SetContext(sp_context_t *_ctx);
|
|
||||||
bool IsInExec();
|
|
||||||
private:
|
|
||||||
void SetErrorMessage(const char *msg, va_list ap);
|
|
||||||
void FlushFunctionCache();
|
|
||||||
void RefreshFunctionCache();
|
|
||||||
private:
|
|
||||||
sp_context_t *ctx;
|
|
||||||
#if defined SOURCEMOD_BUILD
|
|
||||||
SourceMod::IdentityToken_t *m_pToken;
|
|
||||||
cell_t *m_pNullVec;
|
|
||||||
cell_t *m_pNullString;
|
|
||||||
#endif
|
|
||||||
char m_MsgCache[1024];
|
|
||||||
bool m_CustomMsg;
|
|
||||||
bool m_InExec;
|
|
||||||
unsigned int m_funcsnum;
|
|
||||||
#if 0
|
|
||||||
CFunction **m_priv_funcs;
|
|
||||||
#endif
|
|
||||||
CFunction **m_pub_funcs;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_
|
|
@ -109,25 +109,25 @@ namespace SourceMod
|
|||||||
virtual PluginType GetType() =0;
|
virtual PluginType GetType() =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the current API context being used in the plugin.
|
* @brief Returns the IPluginRuntime::GetDefaultContext() value.
|
||||||
*
|
*
|
||||||
* @return Pointer to an IPluginContext, or NULL if not loaded.
|
* @return Pointer to an IPluginContext, or NULL if not loaded.
|
||||||
*/
|
*/
|
||||||
virtual SourcePawn::IPluginContext *GetBaseContext() =0;
|
virtual SourcePawn::IPluginContext *GetBaseContext() =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the context structure being used in the plugin.
|
* @brief Deprecated, returns NULL.
|
||||||
*
|
*
|
||||||
* @return Pointer to an sp_context_t, or NULL if not loaded.
|
* @return NULL.
|
||||||
*/
|
*/
|
||||||
virtual sp_context_t *GetContext() =0;
|
virtual sp_context_t *GetContext() =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the plugin file structure.
|
* @brief Deprecated, returns NULL.
|
||||||
*
|
*
|
||||||
* @return Pointer to an sp_plugin_t, or NULL if not loaded.
|
* @return NULL.
|
||||||
*/
|
*/
|
||||||
virtual const sp_plugin_t *GetPluginStructure() =0;
|
virtual void *GetPluginStructure() =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns information about the plugin by reference.
|
* @brief Returns information about the plugin by reference.
|
||||||
@ -189,6 +189,13 @@ namespace SourceMod
|
|||||||
* @return True if the property existed, false otherwise.
|
* @return True if the property existed, false otherwise.
|
||||||
*/
|
*/
|
||||||
virtual bool GetProperty(const char *prop, void **ptr, bool remove=false) =0;
|
virtual bool GetProperty(const char *prop, void **ptr, bool remove=false) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the runtime representing this plugin.
|
||||||
|
*
|
||||||
|
* @return IPluginRuntime pointer, or NULL if not loaded.
|
||||||
|
*/
|
||||||
|
virtual SourcePawn::IPluginRuntime *GetRuntime() =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -203,9 +203,9 @@ namespace SourceMod
|
|||||||
virtual SourcePawn::ISourcePawnEngine *GetScriptingEngine() =0;
|
virtual SourcePawn::ISourcePawnEngine *GetScriptingEngine() =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the JIT interface.
|
* @brief Deprecated, do not use.
|
||||||
*
|
*
|
||||||
* @return A pointer to the JIT interface.
|
* @return NULL.
|
||||||
*/
|
*/
|
||||||
virtual SourcePawn::IVirtualMachine *GetScriptingVM() =0;
|
virtual SourcePawn::IVirtualMachine *GetScriptingVM() =0;
|
||||||
|
|
||||||
|
@ -41,10 +41,8 @@
|
|||||||
#include "sp_vm_types.h"
|
#include "sp_vm_types.h"
|
||||||
|
|
||||||
/** SourcePawn Engine API Version */
|
/** SourcePawn Engine API Version */
|
||||||
#define SOURCEPAWN_ENGINE_API_VERSION 3
|
#define SOURCEPAWN_ENGINE_API_VERSION 4
|
||||||
|
#define SOURCEPAWN_ENGINE2_API_VERSION 1
|
||||||
/** SourcePawn VM API Version */
|
|
||||||
#define SOURCEPAWN_VM_API_VERSION 7
|
|
||||||
|
|
||||||
#if !defined SOURCEMOD_BUILD
|
#if !defined SOURCEMOD_BUILD
|
||||||
#define SOURCEMOD_BUILD
|
#define SOURCEMOD_BUILD
|
||||||
@ -57,6 +55,9 @@ namespace SourceMod
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct sp_context_s;
|
||||||
|
typedef struct sp_context_s sp_context_t;
|
||||||
|
|
||||||
namespace SourcePawn
|
namespace SourcePawn
|
||||||
{
|
{
|
||||||
class IVirtualMachine;
|
class IVirtualMachine;
|
||||||
@ -185,7 +186,8 @@ namespace SourcePawn
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Executes the forward, resets the pushed parameter list, and performs any copybacks.
|
* @brief Executes the function, resets the pushed parameter list, and
|
||||||
|
* performs any copybacks.
|
||||||
*
|
*
|
||||||
* @param result Pointer to store return value in.
|
* @param result Pointer to store return value in.
|
||||||
* @return Error code, if any.
|
* @return Error code, if any.
|
||||||
@ -206,9 +208,9 @@ namespace SourcePawn
|
|||||||
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) =0;
|
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns which plugin this function belongs to.
|
* @brief Deprecated, do not use.
|
||||||
*
|
*
|
||||||
* @return IPluginContext pointer to parent plugin.
|
* @return GetDefaultContext() of parent runtime.
|
||||||
*/
|
*/
|
||||||
virtual IPluginContext *GetParentContext() =0;
|
virtual IPluginContext *GetParentContext() =0;
|
||||||
|
|
||||||
@ -227,6 +229,37 @@ namespace SourcePawn
|
|||||||
* @return Function id.
|
* @return Function id.
|
||||||
*/
|
*/
|
||||||
virtual funcid_t GetFunctionID() =0;
|
virtual funcid_t GetFunctionID() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Executes the forward, resets the pushed parameter list, and
|
||||||
|
* performs any copybacks.
|
||||||
|
*
|
||||||
|
* Note: A function can only be executed given a runtime it was created in.
|
||||||
|
*
|
||||||
|
* @param ctx Context to execute the function in.
|
||||||
|
* @param result Pointer to store return value in.
|
||||||
|
* @return Error code, if any.
|
||||||
|
*/
|
||||||
|
virtual int Execute2(IPluginContext *ctx, cell_t *result) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Executes the function with the given parameter array.
|
||||||
|
* Parameters are read in forward order (i.e. index 0 is parameter #1)
|
||||||
|
* NOTE: You will get an error if you attempt to use CallFunction() with
|
||||||
|
* previously pushed parameters.
|
||||||
|
*
|
||||||
|
* Note: A function can only be executed given a runtime it was created in.
|
||||||
|
*
|
||||||
|
* @param ctx Context to execute the function in.
|
||||||
|
* @param params Array of cell parameters.
|
||||||
|
* @param num_params Number of parameters to push.
|
||||||
|
* @param result Pointer to store result of function on return.
|
||||||
|
* @return SourcePawn error code (if any).
|
||||||
|
*/
|
||||||
|
virtual int CallFunction2(IPluginContext *ctx,
|
||||||
|
const cell_t *params,
|
||||||
|
unsigned int num_params,
|
||||||
|
cell_t *result) =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -262,43 +295,38 @@ namespace SourcePawn
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Interface to managing a context at runtime.
|
* @brief Represents a JIT compilation or plugin loading options.
|
||||||
*/
|
*/
|
||||||
class IPluginContext
|
class ICompilation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/** Virtual destructor */
|
/**
|
||||||
virtual ~IPluginContext() { };
|
* @brief Sets a compilation option.
|
||||||
|
*
|
||||||
|
* @param key Option name.
|
||||||
|
* @param val Option value.
|
||||||
|
* @return True on success, false on failure.
|
||||||
|
*/
|
||||||
|
virtual bool SetOption(const char *key, const char *val) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Aborts the compilation and destroys this object.
|
||||||
|
*/
|
||||||
|
virtual void Abort() =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface to managing a runtime plugin.
|
||||||
|
*/
|
||||||
|
class IPluginRuntime
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* @brief Returns the parent IVirtualMachine.
|
|
||||||
*
|
|
||||||
* @return Parent virtual machine pointer.
|
|
||||||
*/
|
|
||||||
virtual IVirtualMachine *GetVirtualMachine() =0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the child sp_context_t structure.
|
* @brief Virtual destructor (you may call delete).
|
||||||
*
|
|
||||||
* @return Child sp_context_t structure.
|
|
||||||
*/
|
*/
|
||||||
virtual sp_context_t *GetContext() =0;
|
virtual ~IPluginRuntime()
|
||||||
|
{
|
||||||
/**
|
}
|
||||||
* @brief Returns true if the plugin is in debug mode.
|
|
||||||
*
|
|
||||||
* @return True if in debug mode, false otherwise.
|
|
||||||
*/
|
|
||||||
virtual bool IsDebugging() =0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Installs a debug break and returns the old one, if any.
|
|
||||||
* This will fail if the plugin is not debugging.
|
|
||||||
*
|
|
||||||
* @param newpfn New function pointer.
|
|
||||||
* @param oldpfn Pointer to retrieve old function pointer.
|
|
||||||
*/
|
|
||||||
virtual int SetDebugBreak(SPVM_DEBUGBREAK newpfn, SPVM_DEBUGBREAK *oldpfn) =0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns debug info.
|
* @brief Returns debug info.
|
||||||
@ -307,39 +335,6 @@ namespace SourcePawn
|
|||||||
*/
|
*/
|
||||||
virtual IPluginDebugInfo *GetDebugInfo() =0;
|
virtual IPluginDebugInfo *GetDebugInfo() =0;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Allocates memory on the secondary stack of a plugin.
|
|
||||||
* Note that although called a heap, it is in fact a stack.
|
|
||||||
*
|
|
||||||
* @param cells Number of cells to allocate.
|
|
||||||
* @param local_addr Will be filled with data offset to heap.
|
|
||||||
* @param phys_addr Physical address to heap memory.
|
|
||||||
*/
|
|
||||||
virtual int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr) =0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Pops a heap address off the heap stack. Use this to free memory allocated with
|
|
||||||
* SP_HeapAlloc().
|
|
||||||
* Note that in SourcePawn, the heap is in fact a bottom-up stack. Deallocations
|
|
||||||
* with this native should be performed in precisely the REVERSE order.
|
|
||||||
*
|
|
||||||
* @param local_addr Local address to free.
|
|
||||||
*/
|
|
||||||
virtual int HeapPop(cell_t local_addr) =0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Releases a heap address using a different method than SP_HeapPop().
|
|
||||||
* This allows you to release in any order. However, if you allocate N
|
|
||||||
* objects, release only some of them, then begin allocating again,
|
|
||||||
* you cannot go back and starting freeing the originals.
|
|
||||||
* In other words, for each chain of allocations, if you start deallocating,
|
|
||||||
* then allocating more in a chain, you must only deallocate from the current
|
|
||||||
* allocation chain. This is basically HeapPop() except on a larger scale.
|
|
||||||
*
|
|
||||||
* @param local_addr Local address to free.
|
|
||||||
*/
|
|
||||||
virtual int HeapRelease(cell_t local_addr) =0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Finds a native by name.
|
* @brief Finds a native by name.
|
||||||
*
|
*
|
||||||
@ -419,7 +414,227 @@ namespace SourcePawn
|
|||||||
virtual uint32_t GetPubVarsNum() =0;
|
virtual uint32_t GetPubVarsNum() =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Round-about method of converting a plugin reference to a physical address
|
* @brief Returns a function by name.
|
||||||
|
*
|
||||||
|
* @param public_name Name of the function.
|
||||||
|
* @return A new IPluginFunction pointer, NULL if not found.
|
||||||
|
*/
|
||||||
|
virtual IPluginFunction *GetFunctionByName(const char *public_name) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a function by its id.
|
||||||
|
*
|
||||||
|
* @param func_id Function ID.
|
||||||
|
* @return A new IPluginFunction pointer, NULL if not found.
|
||||||
|
*/
|
||||||
|
virtual IPluginFunction *GetFunctionById(funcid_t func_id) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the default context. The default context
|
||||||
|
* should not be destroyed.
|
||||||
|
*
|
||||||
|
* @return Default context pointer.
|
||||||
|
*/
|
||||||
|
virtual IPluginContext *GetDefaultContext() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if the plugin is in debug mode.
|
||||||
|
*
|
||||||
|
* @return True if in debug mode, false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool IsDebugging() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Applies new compilation/runtime settings to the runtime code.
|
||||||
|
*
|
||||||
|
* The compilation object is destroyed once this function completes.
|
||||||
|
*
|
||||||
|
* @return Error code (SP_ERROR_NONE on success).
|
||||||
|
*/
|
||||||
|
virtual int ApplyCompilationOptions(ICompilation *co) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets whether or not the plugin is paused (cannot be run).
|
||||||
|
*
|
||||||
|
* @param pause Pause state.
|
||||||
|
*/
|
||||||
|
virtual void SetPauseState(bool paused) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns whether or not the plugin is paused (runnable).
|
||||||
|
*
|
||||||
|
* @return Pause state (true = paused, false = not).
|
||||||
|
*/
|
||||||
|
virtual bool IsPaused() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the estimated memory usage of this plugin.
|
||||||
|
*
|
||||||
|
* @return Memory usage, in bytes.
|
||||||
|
*/
|
||||||
|
virtual size_t GetMemUsage() =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface to managing a context at runtime.
|
||||||
|
*/
|
||||||
|
class IPluginContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Virtual destructor */
|
||||||
|
virtual ~IPluginContext() { };
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, does nothing.
|
||||||
|
*
|
||||||
|
* @return NULL.
|
||||||
|
*/
|
||||||
|
virtual IVirtualMachine *GetVirtualMachine() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, do not use.
|
||||||
|
*
|
||||||
|
* Returns the pointer of this object, casted to an opaque structure.
|
||||||
|
*
|
||||||
|
* @return Returns this.
|
||||||
|
*/
|
||||||
|
virtual sp_context_t *GetContext() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if the plugin is in debug mode.
|
||||||
|
*
|
||||||
|
* @return True if in debug mode, false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool IsDebugging() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, does nothing.
|
||||||
|
*
|
||||||
|
* @param newpfn Unused.
|
||||||
|
* @param oldpfn Unused.
|
||||||
|
*/
|
||||||
|
virtual int SetDebugBreak(void *newpfn, void *oldpfn) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, do not use.
|
||||||
|
*
|
||||||
|
* @return NULL.
|
||||||
|
*/
|
||||||
|
virtual IPluginDebugInfo *GetDebugInfo() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocates memory on the secondary stack of a plugin.
|
||||||
|
* Note that although called a heap, it is in fact a stack.
|
||||||
|
*
|
||||||
|
* @param cells Number of cells to allocate.
|
||||||
|
* @param local_addr Will be filled with data offset to heap.
|
||||||
|
* @param phys_addr Physical address to heap memory.
|
||||||
|
*/
|
||||||
|
virtual int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pops a heap address off the heap stack. Use this to free memory allocated with
|
||||||
|
* SP_HeapAlloc().
|
||||||
|
* Note that in SourcePawn, the heap is in fact a bottom-up stack. Deallocations
|
||||||
|
* with this native should be performed in precisely the REVERSE order.
|
||||||
|
*
|
||||||
|
* @param local_addr Local address to free.
|
||||||
|
*/
|
||||||
|
virtual int HeapPop(cell_t local_addr) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Releases a heap address using a different method than SP_HeapPop().
|
||||||
|
* This allows you to release in any order. However, if you allocate N
|
||||||
|
* objects, release only some of them, then begin allocating again,
|
||||||
|
* you cannot go back and starting freeing the originals.
|
||||||
|
* In other words, for each chain of allocations, if you start deallocating,
|
||||||
|
* then allocating more in a chain, you must only deallocate from the current
|
||||||
|
* allocation chain. This is basically HeapPop() except on a larger scale.
|
||||||
|
*
|
||||||
|
* @param local_addr Local address to free.
|
||||||
|
*/
|
||||||
|
virtual int HeapRelease(cell_t local_addr) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, use IPluginRuntime instead.
|
||||||
|
*
|
||||||
|
* @param name Name of native.
|
||||||
|
* @param index Optionally filled with native index number.
|
||||||
|
*/
|
||||||
|
virtual int FindNativeByName(const char *name, uint32_t *index) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, use IPluginRuntime instead.
|
||||||
|
*
|
||||||
|
* @param index Index number of native.
|
||||||
|
* @param native Optionally filled with pointer to native structure.
|
||||||
|
*/
|
||||||
|
virtual int GetNativeByIndex(uint32_t index, sp_native_t **native) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, use IPluginRuntime instead.
|
||||||
|
*
|
||||||
|
* @return Filled with the number of natives.
|
||||||
|
*/
|
||||||
|
virtual uint32_t GetNativesNum() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, use IPluginRuntime instead.
|
||||||
|
*
|
||||||
|
* @param name Name of public
|
||||||
|
* @param index Optionally filled with public index number.
|
||||||
|
*/
|
||||||
|
virtual int FindPublicByName(const char *name, uint32_t *index) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, use IPluginRuntime instead.
|
||||||
|
*
|
||||||
|
* @param index Public function index number.
|
||||||
|
* @param publicptr Optionally filled with pointer to public structure.
|
||||||
|
*/
|
||||||
|
virtual int GetPublicByIndex(uint32_t index, sp_public_t **publicptr) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, use IPluginRuntime instead.
|
||||||
|
*
|
||||||
|
* @return Filled with the number of public functions.
|
||||||
|
*/
|
||||||
|
virtual uint32_t GetPublicsNum() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, use IPluginRuntime instead.
|
||||||
|
*
|
||||||
|
* @param index Public variable index number.
|
||||||
|
* @param pubvar Optionally filled with pointer to pubvar structure.
|
||||||
|
*/
|
||||||
|
virtual int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, use IPluginRuntime instead.
|
||||||
|
*
|
||||||
|
* @param name Name of pubvar
|
||||||
|
* @param index Optionally filled with pubvar index number.
|
||||||
|
*/
|
||||||
|
virtual int FindPubvarByName(const char *name, uint32_t *index) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, use IPluginRuntime instead.
|
||||||
|
*
|
||||||
|
* @param index Index of public variable.
|
||||||
|
* @param local_addr Address to store local address in.
|
||||||
|
* @param phys_addr Address to store physically relocated in.
|
||||||
|
*/
|
||||||
|
virtual int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deprecated, use IPluginRuntime instead.
|
||||||
|
*
|
||||||
|
* @return Number of public variables.
|
||||||
|
*/
|
||||||
|
virtual uint32_t GetPubVarsNum() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts a plugin reference to a physical address
|
||||||
*
|
*
|
||||||
* @param local_addr Local address in plugin.
|
* @param local_addr Local address in plugin.
|
||||||
* @param phys_addr Optionally filled with relocated physical address.
|
* @param phys_addr Optionally filled with relocated physical address.
|
||||||
@ -445,8 +660,8 @@ namespace SourcePawn
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Converts a physical UTF-8 string to a local address.
|
* @brief Converts a physical UTF-8 string to a local address.
|
||||||
* This function is the same as the ANSI version, except it will copy the maximum number of characters possible
|
* This function is the same as the ANSI version, except it will copy the maximum number
|
||||||
* without accidentally chopping a multi-byte character.
|
* of characters possible without accidentally chopping a multi-byte character.
|
||||||
*
|
*
|
||||||
* @param local_addr Local address in plugin.
|
* @param local_addr Local address in plugin.
|
||||||
* @param maxbytes Number of bytes to write, including NULL terminator.
|
* @param maxbytes Number of bytes to write, including NULL terminator.
|
||||||
@ -459,48 +674,41 @@ namespace SourcePawn
|
|||||||
size_t *wrtnbytes) =0;
|
size_t *wrtnbytes) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pushes a cell onto the stack. Increases the parameter count by one.
|
* @brief Deprecated, does nothing.
|
||||||
*
|
*
|
||||||
* @param value Cell value.
|
* @param value Unused.
|
||||||
*/
|
*/
|
||||||
virtual int PushCell(cell_t value) =0;
|
virtual int PushCell(cell_t value) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pushes an array of cells onto the stack. Increases the parameter count by one.
|
* @brief Deprecated, does nothing.
|
||||||
* If the function returns an error it will fail entirely, releasing anything allocated in the process.
|
|
||||||
* Note that this does not release the heap, so you should release it after
|
|
||||||
* calling Execute().
|
|
||||||
*
|
*
|
||||||
* @param local_addr Filled with local address to release.
|
* @param local_addr Unused.
|
||||||
* @param phys_addr Optionally filled with physical address of new array.
|
* @param phys_addr Unused.
|
||||||
* @param array Cell array to copy.
|
* @param array Unused.
|
||||||
* @param numcells Number of cells in the array to copy.
|
* @param numcells Unused.
|
||||||
*/
|
*/
|
||||||
virtual int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells) =0;
|
virtual int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pushes a string onto the stack (by reference) and increases the parameter count by one.
|
* @brief Deprecated, does nothing.
|
||||||
* Note that this does not release the heap, so you should release it after
|
|
||||||
* calling Execute().
|
|
||||||
*
|
*
|
||||||
* @param local_addr Filled with local address to release.
|
* @param local_addr Unused.
|
||||||
* @param phys_addr Optionally filled with physical address of new array.
|
* @param phys_addr Unused.
|
||||||
* @param string Source string to push.
|
* @param string Unused.
|
||||||
*/
|
*/
|
||||||
virtual int PushString(cell_t *local_addr, char **phys_addr, const char *string) =0;
|
virtual int PushString(cell_t *local_addr, char **phys_addr, const char *string) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Individually pushes each cell of an array of cells onto the stack. Increases the
|
* @brief Deprecated, does nothing.
|
||||||
* parameter count by the number of cells pushed.
|
|
||||||
* If the function returns an error it will fail entirely, releasing anything allocated in the process.
|
|
||||||
*
|
*
|
||||||
* @param array Array of cells to read from.
|
* @param array Unused.
|
||||||
* @param numcells Number of cells to read.
|
* @param numcells Unused.
|
||||||
*/
|
*/
|
||||||
virtual int PushCellsFromArray(cell_t array[], unsigned int numcells) =0;
|
virtual int PushCellsFromArray(cell_t array[], unsigned int numcells) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deprecated; do not use.
|
* @brief Deprecated, does nothing.
|
||||||
*
|
*
|
||||||
* @param natives Deprecated; do not use.
|
* @param natives Deprecated; do not use.
|
||||||
* @param num Deprecated; do not use.
|
* @param num Deprecated; do not use.
|
||||||
@ -509,25 +717,25 @@ namespace SourcePawn
|
|||||||
virtual int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite) =0;
|
virtual int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deprecated; do not use.
|
* @brief Deprecated, does nothing.
|
||||||
*
|
*
|
||||||
* @param native Deprecated; do not use.
|
* @param native Deprecated; do not use.
|
||||||
*/
|
*/
|
||||||
virtual int BindNative(const sp_nativeinfo_t *native) =0;
|
virtual int BindNative(const sp_nativeinfo_t *native) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Binds a single native to any non-registered native.
|
* @brief Deprecated, does nothing.
|
||||||
*
|
*
|
||||||
* @param native Native to bind.
|
* @param native Unused.
|
||||||
*/
|
*/
|
||||||
virtual int BindNativeToAny(SPVM_NATIVE_FUNC native) =0;
|
virtual int BindNativeToAny(SPVM_NATIVE_FUNC native) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Executes a function ID located in this context.
|
* @brief Deprecated, does nothing.
|
||||||
*
|
*
|
||||||
* @param code_addr Address to execute at.
|
* @param code_addr Unused.
|
||||||
* @param result Pointer to store the return value (required).
|
* @param result Unused.
|
||||||
* @return Error code (if any) from the VM.
|
* @return SP_ERROR_ABORTED.
|
||||||
*/
|
*/
|
||||||
virtual int Execute(uint32_t code_addr, cell_t *result) =0;
|
virtual int Execute(uint32_t code_addr, cell_t *result) =0;
|
||||||
|
|
||||||
@ -566,10 +774,10 @@ namespace SourcePawn
|
|||||||
*/
|
*/
|
||||||
virtual IPluginFunction *GetFunctionById(funcid_t func_id) =0;
|
virtual IPluginFunction *GetFunctionById(funcid_t func_id) =0;
|
||||||
|
|
||||||
#if defined SOURCEMOD_BUILD
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the identity token for this context.
|
* @brief Returns the identity token for this context.
|
||||||
* Note: This is a helper function for native calls and the Handle System.
|
*
|
||||||
|
* Note: This is a compatibility shim and is the same as GetKey(1).
|
||||||
*
|
*
|
||||||
* @return Identity token.
|
* @return Identity token.
|
||||||
*/
|
*/
|
||||||
@ -592,7 +800,6 @@ namespace SourcePawn
|
|||||||
* @param addr Destination output pointer.
|
* @param addr Destination output pointer.
|
||||||
*/
|
*/
|
||||||
virtual int LocalToStringNULL(cell_t local_addr, char **addr) =0;
|
virtual int LocalToStringNULL(cell_t local_addr, char **addr) =0;
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deprecated; do not use.
|
* @brief Deprecated; do not use.
|
||||||
@ -608,6 +815,67 @@ namespace SourcePawn
|
|||||||
* @return True if in exec, false otherwise.
|
* @return True if in exec, false otherwise.
|
||||||
*/
|
*/
|
||||||
virtual bool IsInExec() =0;
|
virtual bool IsInExec() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the parent runtime of a context.
|
||||||
|
*
|
||||||
|
* @return Parent runtime.
|
||||||
|
*/
|
||||||
|
virtual IPluginRuntime *GetRuntime() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Executes a function in the context. The function must be
|
||||||
|
* a member of the context's parent runtime.
|
||||||
|
*
|
||||||
|
* @param function Function.
|
||||||
|
* @param params Parameters.
|
||||||
|
* @param num_params Number of parameters in the parameter array.
|
||||||
|
* @param result Optional pointer to store the result on success.
|
||||||
|
* @return Error code.
|
||||||
|
*/
|
||||||
|
virtual int Execute2(IPluginFunction *function,
|
||||||
|
const cell_t *params,
|
||||||
|
unsigned int num_params,
|
||||||
|
cell_t *result) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns whether a context is in an error state.
|
||||||
|
*
|
||||||
|
* This should only be used inside natives to determine whether
|
||||||
|
* a prior call failed.
|
||||||
|
*/
|
||||||
|
virtual int GetLastNativeError() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the local parameter stack, starting from the
|
||||||
|
* cell that contains the number of parameters passed.
|
||||||
|
*
|
||||||
|
* Local parameters are the parameters passed to the function
|
||||||
|
* from which a native was called (and thus this can only be
|
||||||
|
* called inside a native).
|
||||||
|
*
|
||||||
|
* @return Parameter stack.
|
||||||
|
*/
|
||||||
|
virtual cell_t *GetLocalParams() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets a local "key" that can be used for fast lookup.
|
||||||
|
*
|
||||||
|
* Only the "owner" of the context should be setting this.
|
||||||
|
*
|
||||||
|
* @param key Key number (values allowed: 1 through 4).
|
||||||
|
* @param value Pointer value.
|
||||||
|
*/
|
||||||
|
virtual void SetKey(int k, void *value) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves a previously set "key."
|
||||||
|
*
|
||||||
|
* @param key Key number (values allowed: 1 through 4).
|
||||||
|
* @param value Pointer to store value.
|
||||||
|
* @return True on success, false on failure.
|
||||||
|
*/
|
||||||
|
virtual bool GetKey(int k, void **value) =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -748,6 +1016,9 @@ namespace SourcePawn
|
|||||||
virtual void OnCallbackEnd(int serial) =0;
|
virtual void OnCallbackEnd(int serial) =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sp_plugin_s;
|
||||||
|
typedef struct sp_plugin_s sp_plugin_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Contains helper functions used by VMs and the host app
|
* @brief Contains helper functions used by VMs and the host app
|
||||||
*/
|
*/
|
||||||
@ -755,30 +1026,29 @@ namespace SourcePawn
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Loads a named file from a file pointer.
|
* @brief Deprecated, do not use.
|
||||||
* Note: Using this means the memory will be allocated by the VM.
|
|
||||||
*
|
*
|
||||||
* @param fp File pointer. May be at any offset. Not closed on return.
|
* @param fp Unused.
|
||||||
* @param err Optional error code pointer.
|
* @param err Unused.
|
||||||
* @return A new plugin structure.
|
* @return NULL.
|
||||||
*/
|
*/
|
||||||
virtual sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err) =0;
|
virtual sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Loads a file from a base memory address.
|
* @brief Deprecated, do not use,
|
||||||
*
|
*
|
||||||
* @param base Base address of the plugin's memory region.
|
* @param base Unused.
|
||||||
* @param plugin If NULL, a new plugin pointer is returned.
|
* @param plugin Unused.
|
||||||
* Otherwise, the passed pointer is used.
|
* @param err Unused.
|
||||||
* @param err Optional error code pointer.
|
* @return NULL.
|
||||||
* @return The resulting plugin pointer.
|
|
||||||
*/
|
*/
|
||||||
virtual sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err) =0;
|
virtual sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees all of the memory associated with a plugin file.
|
* @brief Deprecated, do not use.
|
||||||
* If allocated using SP_LoadFromMemory, the base and plugin pointer
|
*
|
||||||
* itself are not freed (so this may end up doing nothing).
|
* @param plugin Unused.
|
||||||
|
* @return SP_ERROR_ABORTED.
|
||||||
*/
|
*/
|
||||||
virtual int FreeFromMemory(sp_plugin_t *plugin) =0;
|
virtual int FreeFromMemory(sp_plugin_t *plugin) =0;
|
||||||
|
|
||||||
@ -826,9 +1096,9 @@ namespace SourcePawn
|
|||||||
virtual IDebugListener *SetDebugListener(IDebugListener *listener) =0;
|
virtual IDebugListener *SetDebugListener(IDebugListener *listener) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the number of plugins on the call stack.
|
* @brief Deprecated, do not use.
|
||||||
*
|
*
|
||||||
* @return Number of contexts in the call stack.
|
* @return 0.
|
||||||
*/
|
*/
|
||||||
virtual unsigned int GetContextCallCount() =0;
|
virtual unsigned int GetContextCallCount() =0;
|
||||||
|
|
||||||
@ -869,103 +1139,23 @@ namespace SourcePawn
|
|||||||
virtual void FreePageMemory(void *ptr) =0;
|
virtual void FreePageMemory(void *ptr) =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Dummy class for encapsulating private compilation data.
|
|
||||||
*/
|
|
||||||
class ICompilation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/** Virtual destructor */
|
|
||||||
virtual ~ICompilation() { };
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Outlines the interface a Virtual Machine (JIT) must expose
|
* @brief Outlines the interface a Virtual Machine (JIT) must expose
|
||||||
*/
|
*/
|
||||||
class IVirtualMachine
|
class ISourcePawnEngine2
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Returns the current API version.
|
* @brief Returns the second engine API version.
|
||||||
|
*
|
||||||
|
* @return API version.
|
||||||
*/
|
*/
|
||||||
virtual unsigned int GetAPIVersion() =0;
|
virtual unsigned int GetAPIVersion() =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the string name of a VM implementation.
|
* @brief Returns the string name of a VM implementation.
|
||||||
*/
|
*/
|
||||||
virtual const char *GetVMName() =0;
|
virtual const char *GetEngineName() =0;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Begins a new compilation
|
|
||||||
*
|
|
||||||
* @param plugin Pointer to a plugin structure.
|
|
||||||
* @return New compilation pointer.
|
|
||||||
*/
|
|
||||||
virtual ICompilation *StartCompilation(sp_plugin_t *plugin) =0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets a compilation option.
|
|
||||||
*
|
|
||||||
* @param co Pointer to a compilation.
|
|
||||||
* @param key Option key name.
|
|
||||||
* @param val Option value string.
|
|
||||||
* @return True if option could be set, false otherwise.
|
|
||||||
*/
|
|
||||||
virtual bool SetCompilationOption(ICompilation *co, const char *key, const char *val) =0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Finalizes a compilation into a new sp_context_t.
|
|
||||||
* Note: This will free the ICompilation pointer.
|
|
||||||
*
|
|
||||||
* @param co Compilation pointer.
|
|
||||||
* @param err Filled with error code on exit.
|
|
||||||
* @return New plugin context.
|
|
||||||
*/
|
|
||||||
virtual sp_context_t *CompileToContext(ICompilation *co, int *err) =0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Aborts a compilation and frees the ICompilation pointer.
|
|
||||||
*
|
|
||||||
* @param co Compilation pointer.
|
|
||||||
*/
|
|
||||||
virtual void AbortCompilation(ICompilation *co) =0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Frees any internal variable usage on a context.
|
|
||||||
*
|
|
||||||
* @param ctx Context structure pointer.
|
|
||||||
*/
|
|
||||||
virtual void FreeContext(sp_context_t *ctx) =0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calls the "execute" function on a context.
|
|
||||||
*
|
|
||||||
* @param ctx Executes a function in a context.
|
|
||||||
* @param code_addr Index into the code section.
|
|
||||||
* @param result Pointer to store result into.
|
|
||||||
* @return Error code (if any).
|
|
||||||
*/
|
|
||||||
virtual int ContextExecute(sp_context_t *ctx, uint32_t code_addr, cell_t *result) =0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Given a context and a code address, returns the index of the function.
|
|
||||||
*
|
|
||||||
* @param ctx Context to search.
|
|
||||||
* @param code_addr Index into the code section.
|
|
||||||
* @param result Pointer to store result into.
|
|
||||||
* @return True if code index is valid, false otherwise.
|
|
||||||
*/
|
|
||||||
virtual bool FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result) =0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the number of functions defined in the context.
|
|
||||||
*
|
|
||||||
* @param ctx Context to search.
|
|
||||||
* @return Number of functions.
|
|
||||||
*/
|
|
||||||
virtual unsigned int FunctionCount(const sp_context_t *ctx) =0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a version string.
|
* @brief Returns a version string.
|
||||||
@ -975,21 +1165,24 @@ namespace SourcePawn
|
|||||||
virtual const char *GetVersionString() =0;
|
virtual const char *GetVersionString() =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a string describing optimizations.
|
* @brief Creates a new compilation options object.
|
||||||
*
|
*
|
||||||
* @return String describing CPU specific optimizations.
|
* @return Compilation options object.
|
||||||
*/
|
*/
|
||||||
virtual const char *GetCPUOptimizations() =0;
|
virtual ICompilation *StartCompilation() =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Given a context and a p-code address, returns the index of the function.
|
* @brief Loads a plugin from disk.
|
||||||
|
*
|
||||||
|
* If a compilation object is supplied, it is destroyed upon
|
||||||
|
* the function's return.
|
||||||
*
|
*
|
||||||
* @param ctx Context to search.
|
* @param co Compilation options, or NULL for defaults.
|
||||||
* @param code_addr Index into the p-code section.
|
* @param file Path to the file to compile.
|
||||||
* @param result Pointer to store result into.
|
* @param err Error code (filled on failure); required.
|
||||||
* @return True if code index is valid, false otherwise.
|
* @return New runtime pointer, or NULL on failure.
|
||||||
*/
|
*/
|
||||||
virtual bool FunctionPLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result) =0;
|
virtual IPluginRuntime *LoadPlugin(ICompilation *co, const char *file, int *err) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a fake native and binds it to a general callback function.
|
* @brief Creates a fake native and binds it to a general callback function.
|
||||||
@ -1006,6 +1199,32 @@ namespace SourcePawn
|
|||||||
* @param func Pointer to the fake native created by CreateFakeNative.
|
* @param func Pointer to the fake native created by CreateFakeNative.
|
||||||
*/
|
*/
|
||||||
virtual void DestroyFakeNative(SPVM_NATIVE_FUNC func) =0;
|
virtual void DestroyFakeNative(SPVM_NATIVE_FUNC func) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the debug listener. This should only be called once.
|
||||||
|
* If called successively (using manual chaining), only the last function should
|
||||||
|
* attempt to call back into the same plugin. Otherwise, globally cached states
|
||||||
|
* can be accidentally overwritten.
|
||||||
|
*
|
||||||
|
* @param listener Pointer to an IDebugListener.
|
||||||
|
* @return Old IDebugListener, or NULL if none.
|
||||||
|
*/
|
||||||
|
virtual IDebugListener *SetDebugListener(IDebugListener *listener) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the global profiler.
|
||||||
|
*
|
||||||
|
* @param profiler Profiler pointer.
|
||||||
|
*/
|
||||||
|
virtual void SetProfiler(IProfiler *profiler) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the string representation of an error message.
|
||||||
|
*
|
||||||
|
* @param err Error code.
|
||||||
|
* @return Error string, or NULL if not found.
|
||||||
|
*/
|
||||||
|
virtual const char *GetErrorString(int err) =0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,8 +47,5 @@
|
|||||||
#define EXPORT_LINK extern "C" __attribute__((visibility("default")))
|
#define EXPORT_LINK extern "C" __attribute__((visibility("default")))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** No longer used */
|
|
||||||
typedef SourcePawn::IVirtualMachine *(*SP_GETVM_FUNC)(SourcePawn::ISourcePawnEngine *);
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEPAWN_VM_BASE_H_
|
#endif //_INCLUDE_SOURCEPAWN_VM_BASE_H_
|
||||||
|
|
||||||
|
@ -92,56 +92,6 @@ typedef uint32_t funcid_t; /**< Function index code */
|
|||||||
*** binary.
|
*** binary.
|
||||||
**********************************************/
|
**********************************************/
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Information about the core plugin tables. These may or may not be present!
|
|
||||||
*/
|
|
||||||
typedef struct sp_plugin_infotab_s
|
|
||||||
{
|
|
||||||
const char *stringbase; /**< base of string table */
|
|
||||||
uint32_t publics_num; /**< number of publics */
|
|
||||||
sp_file_publics_t *publics; /**< public table */
|
|
||||||
uint32_t natives_num; /**< number of natives */
|
|
||||||
sp_file_natives_t *natives; /**< native table */
|
|
||||||
uint32_t pubvars_num; /**< number of pubvars */
|
|
||||||
sp_file_pubvars_t *pubvars; /**< pubvars table */
|
|
||||||
} sp_plugin_infotab_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Information about the plugin's debug tables. These are all present if one is present.
|
|
||||||
*/
|
|
||||||
typedef struct sp_plugin_debug_s
|
|
||||||
{
|
|
||||||
const char *stringbase; /**< base of string table */
|
|
||||||
uint32_t files_num; /**< number of files */
|
|
||||||
sp_fdbg_file_t *files; /**< files table */
|
|
||||||
uint32_t lines_num; /**< number of lines */
|
|
||||||
sp_fdbg_line_t *lines; /**< lines table */
|
|
||||||
uint32_t syms_num; /**< number of symbols */
|
|
||||||
sp_fdbg_symbol_t *symbols; /**< symbol table */
|
|
||||||
} sp_plugin_debug_t;
|
|
||||||
|
|
||||||
#define SP_FA_SELF_EXTERNAL (1<<0) /**< Allocation of structure is external */
|
|
||||||
#define SP_FA_BASE_EXTERNAL (1<<1) /**< Allocation of base is external */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The rebased memory format of a plugin. This differs from the on-disk structure
|
|
||||||
* to ensure that the format is properly read.
|
|
||||||
*/
|
|
||||||
typedef struct sp_plugin_s
|
|
||||||
{
|
|
||||||
uint8_t *base; /**< Base of memory for this plugin. */
|
|
||||||
uint8_t *pcode; /**< P-Code of plugin */
|
|
||||||
uint32_t pcode_size; /**< Size of p-code */
|
|
||||||
uint8_t *data; /**< Data/memory layout */
|
|
||||||
uint32_t data_size; /**< Size of data */
|
|
||||||
uint32_t memory; /**< Required memory space */
|
|
||||||
uint16_t flags; /**< Code flags */
|
|
||||||
uint32_t allocflags; /**< Allocation flags */
|
|
||||||
sp_plugin_infotab_t info; /**< Base info table */
|
|
||||||
sp_plugin_debug_t debug; /**< Debug info table */
|
|
||||||
} sp_plugin_t;
|
|
||||||
|
|
||||||
|
|
||||||
namespace SourcePawn
|
namespace SourcePawn
|
||||||
{
|
{
|
||||||
class IPluginContext;
|
class IPluginContext;
|
||||||
@ -251,51 +201,7 @@ typedef struct sp_debug_symbol_s
|
|||||||
sp_fdbg_symbol_t *sym; /**< Pointer to original symbol */
|
sp_fdbg_symbol_t *sym; /**< Pointer to original symbol */
|
||||||
} sp_debug_symbol_t;
|
} sp_debug_symbol_t;
|
||||||
|
|
||||||
/**
|
//#define SPFLAG_PLUGIN_DEBUG (1<<0) /**< plugin is in debug mode */
|
||||||
* Breaks into a debugger
|
//#define SPFLAG_PLUGIN_PAUSED (1<<1) /**< plugin is "paused" (blocked from executing) */
|
||||||
* Params:
|
|
||||||
* [0] - plugin context
|
|
||||||
* [1] - frm
|
|
||||||
* [2] - cip
|
|
||||||
*/
|
|
||||||
typedef int (*SPVM_DEBUGBREAK)(struct sp_context_s *, uint32_t, uint32_t);
|
|
||||||
|
|
||||||
#define SPFLAG_PLUGIN_DEBUG (1<<0) /**< plugin is in debug mode */
|
|
||||||
#define SPFLAG_PLUGIN_PAUSED (1<<1) /**< plugin is "paused" (blocked from executing) */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This is the heart of the VM. It contains all of the runtime
|
|
||||||
* information about a plugin context. Note that user[0..3] can be used for any user based pointers.
|
|
||||||
* However, vm[0..3] should not be touched, as it is reserved for the VM.
|
|
||||||
*/
|
|
||||||
typedef struct sp_context_s
|
|
||||||
{
|
|
||||||
void *codebase; /**< Base of generated code and memory */
|
|
||||||
sp_plugin_t *plugin; /**< Pointer back to parent information */
|
|
||||||
SourcePawn::IPluginContext *context; /**< Pointer to IPluginContext */
|
|
||||||
SourcePawn::IVirtualMachine *vmbase; /**< Pointer to IVirtualMachine */
|
|
||||||
void *user[4]; /**< User specific pointers */
|
|
||||||
void *vm[4]; /**< VM specific pointers */
|
|
||||||
uint32_t flags; /**< Compilation flags */
|
|
||||||
SPVM_DEBUGBREAK dbreak; /**< Debug break function */
|
|
||||||
uint8_t *memory; /**< Data chunk */
|
|
||||||
ucell_t mem_size; /**< Total memory size; */
|
|
||||||
cell_t data_size; /**< Data chunk size, always starts at 0 */
|
|
||||||
cell_t heap_base; /**< Where the heap starts */
|
|
||||||
cell_t hp; /**< Heap pointer */
|
|
||||||
cell_t sp; /**< Stack pointer */
|
|
||||||
cell_t frm; /**< Frame pointer */
|
|
||||||
uint32_t pushcount; /**< Push count */
|
|
||||||
int32_t n_err; /**< Error code set by a native */
|
|
||||||
uint32_t n_idx; /**< Current native index being executed */
|
|
||||||
sp_public_t *publics; /**< Public functions table */
|
|
||||||
sp_pubvar_t *pubvars; /**< Public variables table */
|
|
||||||
sp_native_t *natives; /**< Natives table */
|
|
||||||
sp_debug_file_t *files; /**< Files */
|
|
||||||
sp_debug_line_t *lines; /**< Lines */
|
|
||||||
sp_debug_symbol_t *symbols; /**< Symbols */
|
|
||||||
SourcePawn::IProfiler *profiler; /**< Pointer to IProfiler */
|
|
||||||
uint32_t prof_flags; /**< Profiling flags */
|
|
||||||
} sp_context_t;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEPAWN_VM_TYPES_H
|
#endif //_INCLUDE_SOURCEPAWN_VM_TYPES_H
|
||||||
|
357
sourcepawn/jit/BaseRuntime.cpp
Normal file
357
sourcepawn/jit/BaseRuntime.cpp
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "BaseRuntime.h"
|
||||||
|
#include "sp_vm_engine.h"
|
||||||
|
#include "x86/jit_x86.h"
|
||||||
|
#include "sp_vm_basecontext.h"
|
||||||
|
#include "engine2.h"
|
||||||
|
|
||||||
|
using namespace SourcePawn;
|
||||||
|
|
||||||
|
int GlobalDebugBreak(BaseContext *ctx, uint32_t frm, uint32_t cip)
|
||||||
|
{
|
||||||
|
g_engine1.RunTracer(ctx, frm, cip);
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseRuntime::BaseRuntime(sp_plugin_t *pl) : m_Debug(pl), m_pPlugin(pl)
|
||||||
|
{
|
||||||
|
m_pCtx = new BaseContext(this);
|
||||||
|
|
||||||
|
if (m_pPlugin->info.publics_num > 0)
|
||||||
|
{
|
||||||
|
m_PubFuncs = new CFunction *[m_pPlugin->info.publics_num];
|
||||||
|
memset(m_PubFuncs, 0, sizeof(CFunction *) * m_pPlugin->info.publics_num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_PubFuncs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pPlugin->dbreak = GlobalDebugBreak;
|
||||||
|
m_pPlugin->profiler = g_engine2.GetProfiler();
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseRuntime::~BaseRuntime()
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++)
|
||||||
|
{
|
||||||
|
delete m_PubFuncs[i];
|
||||||
|
m_PubFuncs[i] = NULL;
|
||||||
|
}
|
||||||
|
delete [] m_PubFuncs;
|
||||||
|
|
||||||
|
ClearCompile();
|
||||||
|
|
||||||
|
free(m_pPlugin->base);
|
||||||
|
delete [] m_pPlugin->memory;
|
||||||
|
delete m_pPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseRuntime::ClearCompile()
|
||||||
|
{
|
||||||
|
g_Jit1.FreeContextVars(m_pCtx->GetCtx());
|
||||||
|
g_Jit1.FreePluginVars(m_pPlugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
|
||||||
|
{
|
||||||
|
int high;
|
||||||
|
|
||||||
|
high = m_pPlugin->info.natives_num - 1;
|
||||||
|
|
||||||
|
for (uint32_t i=0; i<m_pPlugin->info.natives_num; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(m_pPlugin->natives[i].name, name) == 0)
|
||||||
|
{
|
||||||
|
if (index)
|
||||||
|
{
|
||||||
|
*index = i;
|
||||||
|
}
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SP_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
|
||||||
|
{
|
||||||
|
if (index >= m_pPlugin->info.natives_num)
|
||||||
|
{
|
||||||
|
return SP_ERROR_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (native)
|
||||||
|
{
|
||||||
|
*native = &(m_pPlugin->natives[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t BaseRuntime::GetNativesNum()
|
||||||
|
{
|
||||||
|
return m_pPlugin->info.natives_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
|
||||||
|
{
|
||||||
|
int diff, high, low;
|
||||||
|
uint32_t mid;
|
||||||
|
|
||||||
|
high = m_pPlugin->info.publics_num - 1;
|
||||||
|
low = 0;
|
||||||
|
|
||||||
|
while (low <= high)
|
||||||
|
{
|
||||||
|
mid = (low + high) / 2;
|
||||||
|
diff = strcmp(m_pPlugin->publics[mid].name, name);
|
||||||
|
if (diff == 0)
|
||||||
|
{
|
||||||
|
if (index)
|
||||||
|
{
|
||||||
|
*index = mid;
|
||||||
|
}
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
} else if (diff < 0) {
|
||||||
|
low = mid + 1;
|
||||||
|
} else {
|
||||||
|
high = mid - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SP_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
|
||||||
|
{
|
||||||
|
if (index >= m_pPlugin->info.publics_num)
|
||||||
|
{
|
||||||
|
return SP_ERROR_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pblic)
|
||||||
|
{
|
||||||
|
*pblic = &(m_pPlugin->publics[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t BaseRuntime::GetPublicsNum()
|
||||||
|
{
|
||||||
|
return m_pPlugin->info.publics_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
|
||||||
|
{
|
||||||
|
if (index >= m_pPlugin->info.pubvars_num)
|
||||||
|
{
|
||||||
|
return SP_ERROR_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pubvar)
|
||||||
|
{
|
||||||
|
*pubvar = &(m_pPlugin->pubvars[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
|
||||||
|
{
|
||||||
|
int diff, high, low;
|
||||||
|
uint32_t mid;
|
||||||
|
|
||||||
|
high = m_pPlugin->info.pubvars_num - 1;
|
||||||
|
low = 0;
|
||||||
|
|
||||||
|
while (low <= high)
|
||||||
|
{
|
||||||
|
mid = (low + high) / 2;
|
||||||
|
diff = strcmp(m_pPlugin->pubvars[mid].name, name);
|
||||||
|
if (diff == 0)
|
||||||
|
{
|
||||||
|
if (index)
|
||||||
|
{
|
||||||
|
*index = mid;
|
||||||
|
}
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
} else if (diff < 0) {
|
||||||
|
low = mid + 1;
|
||||||
|
} else {
|
||||||
|
high = mid - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SP_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
|
||||||
|
{
|
||||||
|
if (index >= m_pPlugin->info.pubvars_num)
|
||||||
|
{
|
||||||
|
return SP_ERROR_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
*local_addr = m_pPlugin->info.pubvars[index].address;
|
||||||
|
*phys_addr = m_pPlugin->pubvars[index].offs;
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t BaseRuntime::GetPubVarsNum()
|
||||||
|
{
|
||||||
|
return m_pPlugin->info.pubvars_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPluginContext *BaseRuntime::GetDefaultContext()
|
||||||
|
{
|
||||||
|
return m_pCtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPluginDebugInfo *BaseRuntime::GetDebugInfo()
|
||||||
|
{
|
||||||
|
if (!IsDebugging())
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &m_Debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseRuntime::RefreshFunctionCache()
|
||||||
|
{
|
||||||
|
if (m_PubFuncs != NULL)
|
||||||
|
{
|
||||||
|
sp_public_t *pub;
|
||||||
|
for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++)
|
||||||
|
{
|
||||||
|
if (m_PubFuncs[i] == NULL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (GetPublicByIndex(i, &pub) != SP_ERROR_NONE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
m_PubFuncs[i]->Set(pub->code_offs, this, (i << 1) | 1, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id)
|
||||||
|
{
|
||||||
|
CFunction *pFunc = NULL;
|
||||||
|
|
||||||
|
if (func_id & 1)
|
||||||
|
{
|
||||||
|
func_id >>= 1;
|
||||||
|
if (func_id >= m_pPlugin->info.publics_num)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pFunc = m_PubFuncs[func_id];
|
||||||
|
if (!pFunc)
|
||||||
|
{
|
||||||
|
m_PubFuncs[func_id] = new CFunction(m_pPlugin->publics[func_id].code_offs,
|
||||||
|
this,
|
||||||
|
(func_id << 1) | 1,
|
||||||
|
func_id);
|
||||||
|
pFunc = m_PubFuncs[func_id];
|
||||||
|
}
|
||||||
|
else if (pFunc->IsInvalidated())
|
||||||
|
{
|
||||||
|
pFunc->Set(m_pPlugin->publics[func_id].code_offs,
|
||||||
|
this,
|
||||||
|
(func_id << 1) | 1,
|
||||||
|
func_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPluginFunction *BaseRuntime::GetFunctionByName(const char *public_name)
|
||||||
|
{
|
||||||
|
uint32_t index;
|
||||||
|
|
||||||
|
if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFunction *pFunc = m_PubFuncs[index];
|
||||||
|
if (!pFunc)
|
||||||
|
{
|
||||||
|
sp_public_t *pub = NULL;
|
||||||
|
GetPublicByIndex(index, &pub);
|
||||||
|
if (pub)
|
||||||
|
{
|
||||||
|
m_PubFuncs[index] = new CFunction(pub->code_offs, this, (index << 1) | 1, index);
|
||||||
|
}
|
||||||
|
pFunc = m_PubFuncs[index];
|
||||||
|
}
|
||||||
|
else if (pFunc->IsInvalidated())
|
||||||
|
{
|
||||||
|
sp_public_t *pub = NULL;
|
||||||
|
GetPublicByIndex(index, &pub);
|
||||||
|
if (pub)
|
||||||
|
{
|
||||||
|
pFunc->Set(pub->code_offs, this, (index << 1) | 1, index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pFunc = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseRuntime::IsDebugging()
|
||||||
|
{
|
||||||
|
return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_DEBUG) == SPFLAG_PLUGIN_DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseRuntime::SetPauseState(bool paused)
|
||||||
|
{
|
||||||
|
if (paused)
|
||||||
|
{
|
||||||
|
m_pPlugin->run_flags |= SPFLAG_PLUGIN_PAUSED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pPlugin->run_flags &= ~SPFLAG_PLUGIN_PAUSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseRuntime::IsPaused()
|
||||||
|
{
|
||||||
|
return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t BaseRuntime::GetMemUsage()
|
||||||
|
{
|
||||||
|
size_t mem = 0;
|
||||||
|
|
||||||
|
mem += sizeof(this);
|
||||||
|
mem += sizeof(sp_plugin_t);
|
||||||
|
mem += sizeof(BaseContext);
|
||||||
|
mem += m_pPlugin->base_size;
|
||||||
|
mem += m_pPlugin->jit_codesize;
|
||||||
|
mem += m_pPlugin->jit_memsize;
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseContext *BaseRuntime::GetBaseContext()
|
||||||
|
{
|
||||||
|
return m_pCtx;
|
||||||
|
}
|
||||||
|
|
60
sourcepawn/jit/BaseRuntime.h
Normal file
60
sourcepawn/jit/BaseRuntime.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
|
||||||
|
#define _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
|
||||||
|
|
||||||
|
#include <sp_vm_api.h>
|
||||||
|
#include "jit_shared.h"
|
||||||
|
#include "sp_vm_function.h"
|
||||||
|
|
||||||
|
class BaseContext;
|
||||||
|
|
||||||
|
class DebugInfo : public IPluginDebugInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DebugInfo(sp_plugin_t *plugin);
|
||||||
|
public:
|
||||||
|
int LookupFile(ucell_t addr, const char **filename);
|
||||||
|
int LookupFunction(ucell_t addr, const char **name);
|
||||||
|
int LookupLine(ucell_t addr, uint32_t *line);
|
||||||
|
private:
|
||||||
|
sp_plugin_t *m_pPlugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Jit wants fast access to this so we expose things as public */
|
||||||
|
class BaseRuntime : public SourcePawn::IPluginRuntime
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BaseRuntime(sp_plugin_t *pl);
|
||||||
|
~BaseRuntime();
|
||||||
|
public:
|
||||||
|
virtual bool IsDebugging();
|
||||||
|
virtual IPluginDebugInfo *GetDebugInfo();
|
||||||
|
virtual int FindNativeByName(const char *name, uint32_t *index);
|
||||||
|
virtual int GetNativeByIndex(uint32_t index, sp_native_t **native);
|
||||||
|
virtual uint32_t GetNativesNum();
|
||||||
|
virtual int FindPublicByName(const char *name, uint32_t *index);
|
||||||
|
virtual int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
|
||||||
|
virtual uint32_t GetPublicsNum();
|
||||||
|
virtual int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
|
||||||
|
virtual int FindPubvarByName(const char *name, uint32_t *index);
|
||||||
|
virtual int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
|
||||||
|
virtual uint32_t GetPubVarsNum();
|
||||||
|
virtual IPluginFunction *GetFunctionByName(const char *public_name);
|
||||||
|
virtual IPluginFunction *GetFunctionById(funcid_t func_id);
|
||||||
|
virtual IPluginContext *GetDefaultContext();
|
||||||
|
virtual int ApplyCompilationOptions(ICompilation *co);
|
||||||
|
virtual void SetPauseState(bool paused);
|
||||||
|
virtual bool IsPaused();
|
||||||
|
virtual size_t GetMemUsage();
|
||||||
|
public:
|
||||||
|
BaseContext *GetBaseContext();
|
||||||
|
private:
|
||||||
|
void ClearCompile();
|
||||||
|
void RefreshFunctionCache();
|
||||||
|
public:
|
||||||
|
DebugInfo m_Debug;
|
||||||
|
sp_plugin_t *m_pPlugin;
|
||||||
|
BaseContext *m_pCtx;
|
||||||
|
CFunction **m_PubFuncs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
|
@ -1,7 +1,8 @@
|
|||||||
# (C)2004-2008 SourceMod Development Team
|
# (C)2004-2008 SourceMod Development Team
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
# Makefile written by David "BAILOPAN" Anderson
|
||||||
|
|
||||||
SMSDK = ../../..
|
SMSDK = ../..
|
||||||
|
SOURCEHOOK = ../../../sourcemm-1.6/sourcehook
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||||
@ -9,7 +10,26 @@ SMSDK = ../../..
|
|||||||
|
|
||||||
PROJECT = sourcepawn.jit.x86
|
PROJECT = sourcepawn.jit.x86
|
||||||
|
|
||||||
OBJECTS = dll_exports.cpp jit_x86.cpp opcode_helpers.cpp
|
OBJECTS = dll_exports.cpp \
|
||||||
|
x86/jit_x86.cpp \
|
||||||
|
x86/opcode_helpers.cpp \
|
||||||
|
sp_vm_basecontext.cpp \
|
||||||
|
sp_vm_engine.cpp \
|
||||||
|
sp_vm_function.cpp \
|
||||||
|
engine2.cpp \
|
||||||
|
BaseRuntime.cpp \
|
||||||
|
zlib/adler32.c \
|
||||||
|
zlib/compress.c \
|
||||||
|
zlib/crc32.c \
|
||||||
|
zlib/deflate.c \
|
||||||
|
zlib/gzio.c \
|
||||||
|
zlib/infback.c \
|
||||||
|
zlib/inffast.c \
|
||||||
|
zlib/inflate.c \
|
||||||
|
zlib/inftrees.c \
|
||||||
|
zlib/trees.c \
|
||||||
|
zlib/uncompr.c \
|
||||||
|
zlib/zutil.c
|
||||||
|
|
||||||
##############################################
|
##############################################
|
||||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
||||||
@ -24,7 +44,7 @@ CPP = gcc-4.1
|
|||||||
LINK = -static-libgcc
|
LINK = -static-libgcc
|
||||||
|
|
||||||
INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86 \
|
INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86 \
|
||||||
-I$(SMSDK)/public/sourcepawn
|
-I$(SMSDK)/public/sourcepawn -I$(SOURCEHOOK)
|
||||||
|
|
||||||
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
|
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
|
||||||
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -DHAVE_STDINT_H \
|
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -DHAVE_STDINT_H \
|
||||||
@ -52,12 +72,17 @@ endif
|
|||||||
BINARY = $(PROJECT).so
|
BINARY = $(PROJECT).so
|
||||||
|
|
||||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||||
|
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
|
||||||
|
|
||||||
|
$(BIN_DIR)/%.o: %.c
|
||||||
|
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
$(BIN_DIR)/%.o: %.cpp
|
$(BIN_DIR)/%.o: %.cpp
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
all:
|
all:
|
||||||
mkdir -p $(BIN_DIR)
|
mkdir -p $(BIN_DIR)/x86
|
||||||
|
mkdir -p $(BIN_DIR)/zlib
|
||||||
$(MAKE) -f Makefile jit
|
$(MAKE) -f Makefile jit
|
||||||
|
|
||||||
jit: $(OBJ_LINUX)
|
jit: $(OBJ_LINUX)
|
@ -31,44 +31,21 @@
|
|||||||
|
|
||||||
#include <sp_vm_api.h>
|
#include <sp_vm_api.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include "jit_x86.h"
|
#include "x86/jit_x86.h"
|
||||||
#include "dll_exports.h"
|
#include "dll_exports.h"
|
||||||
|
#include "sp_vm_engine.h"
|
||||||
|
#include "engine2.h"
|
||||||
|
|
||||||
SourcePawn::ISourcePawnEngine *engine = NULL;
|
SourcePawnEngine2 g_engine2;
|
||||||
JITX86 g_jit;
|
|
||||||
|
|
||||||
EXPORTFUNC int GiveEnginePointer2(SourcePawn::ISourcePawnEngine *engine_p, unsigned int api_version)
|
EXPORTFUNC ISourcePawnEngine *GetSourcePawnEngine1()
|
||||||
{
|
{
|
||||||
engine = engine_p;
|
return &g_engine1;
|
||||||
|
|
||||||
if (api_version > SOURCEPAWN_ENGINE_API_VERSION || api_version < 2)
|
|
||||||
{
|
|
||||||
return SP_ERROR_PARAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SP_ERROR_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORTFUNC unsigned int GetExportCount()
|
EXPORTFUNC ISourcePawnEngine2 *GetSourcePawnEngine2()
|
||||||
{
|
{
|
||||||
return 1;
|
return &g_engine2;
|
||||||
}
|
|
||||||
|
|
||||||
EXPORTFUNC SourcePawn::IVirtualMachine *GetExport(unsigned int exportnum)
|
|
||||||
{
|
|
||||||
/* Don't return anything if we're not initialized yet */
|
|
||||||
if (!engine)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We only have one export - 0 */
|
|
||||||
if (exportnum)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &g_jit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined __linux__
|
#if defined __linux__
|
278
sourcepawn/jit/engine2.cpp
Normal file
278
sourcepawn/jit/engine2.cpp
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "engine2.h"
|
||||||
|
#include "x86/jit_x86.h"
|
||||||
|
#include "jit_version.h"
|
||||||
|
#include "zlib/zlib.h"
|
||||||
|
#include "BaseRuntime.h"
|
||||||
|
#include "sp_vm_engine.h"
|
||||||
|
|
||||||
|
using namespace SourcePawn;
|
||||||
|
|
||||||
|
SourcePawnEngine2::SourcePawnEngine2()
|
||||||
|
{
|
||||||
|
m_Profiler = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp_plugin_t *_ReadPlugin(sp_file_hdr_t *hdr, uint8_t *base, sp_plugin_t *plugin, int *err)
|
||||||
|
{
|
||||||
|
char *nameptr;
|
||||||
|
uint8_t sectnum = 0;
|
||||||
|
sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
|
||||||
|
|
||||||
|
memset(plugin, 0, sizeof(sp_plugin_t));
|
||||||
|
|
||||||
|
plugin->base = base;
|
||||||
|
|
||||||
|
while (sectnum < hdr->sections)
|
||||||
|
{
|
||||||
|
nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
|
||||||
|
|
||||||
|
if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
|
||||||
|
{
|
||||||
|
sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
|
||||||
|
plugin->pcode = base + secptr->dataoffs + cod->code;
|
||||||
|
plugin->pcode_size = cod->codesize;
|
||||||
|
plugin->flags = cod->flags;
|
||||||
|
}
|
||||||
|
else if (!(plugin->data) && !strcmp(nameptr, ".data"))
|
||||||
|
{
|
||||||
|
sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
|
||||||
|
plugin->data = base + secptr->dataoffs + dat->data;
|
||||||
|
plugin->data_size = dat->datasize;
|
||||||
|
plugin->mem_size = dat->memsize;
|
||||||
|
plugin->memory = new uint8_t[plugin->mem_size];
|
||||||
|
memcpy(plugin->memory, plugin->data, plugin->data_size);
|
||||||
|
}
|
||||||
|
else if (!(plugin->info.publics) && !strcmp(nameptr, ".publics"))
|
||||||
|
{
|
||||||
|
plugin->info.publics_num = secptr->size / sizeof(sp_file_publics_t);
|
||||||
|
plugin->info.publics = (sp_file_publics_t *)(base + secptr->dataoffs);
|
||||||
|
}
|
||||||
|
else if (!(plugin->info.pubvars) && !strcmp(nameptr, ".pubvars"))
|
||||||
|
{
|
||||||
|
plugin->info.pubvars_num = secptr->size / sizeof(sp_file_pubvars_t);
|
||||||
|
plugin->info.pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
|
||||||
|
}
|
||||||
|
else if (!(plugin->info.natives) && !strcmp(nameptr, ".natives"))
|
||||||
|
{
|
||||||
|
plugin->info.natives_num = secptr->size / sizeof(sp_file_natives_t);
|
||||||
|
plugin->info.natives = (sp_file_natives_t *)(base + secptr->dataoffs);
|
||||||
|
}
|
||||||
|
else if (!(plugin->info.stringbase) && !strcmp(nameptr, ".names"))
|
||||||
|
{
|
||||||
|
plugin->info.stringbase = (const char *)(base + secptr->dataoffs);
|
||||||
|
}
|
||||||
|
else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
|
||||||
|
{
|
||||||
|
plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
|
||||||
|
}
|
||||||
|
else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
|
||||||
|
{
|
||||||
|
plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
|
||||||
|
}
|
||||||
|
else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
|
||||||
|
{
|
||||||
|
plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
|
||||||
|
}
|
||||||
|
else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
|
||||||
|
{
|
||||||
|
sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
|
||||||
|
plugin->debug.files_num = inf->num_files;
|
||||||
|
plugin->debug.lines_num = inf->num_lines;
|
||||||
|
plugin->debug.syms_num = inf->num_syms;
|
||||||
|
}
|
||||||
|
else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
|
||||||
|
{
|
||||||
|
plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
|
||||||
|
}
|
||||||
|
|
||||||
|
secptr++;
|
||||||
|
sectnum++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(plugin->pcode) || !(plugin->data) || !(plugin->info.stringbase))
|
||||||
|
{
|
||||||
|
goto return_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
|
||||||
|
{
|
||||||
|
goto return_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
*err = SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
|
||||||
|
return_error:
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
*err = SP_ERROR_FILE_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file, int *err)
|
||||||
|
{
|
||||||
|
sp_file_hdr_t hdr;
|
||||||
|
sp_plugin_t *plugin;
|
||||||
|
uint8_t *base;
|
||||||
|
int z_result;
|
||||||
|
int error;
|
||||||
|
BaseRuntime *pRuntime;
|
||||||
|
|
||||||
|
FILE *fp = fopen(file, "rb");
|
||||||
|
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
error = SP_ERROR_NOT_FOUND;
|
||||||
|
goto return_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rewind for safety */
|
||||||
|
fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
|
||||||
|
|
||||||
|
if (hdr.magic != SPFILE_MAGIC)
|
||||||
|
{
|
||||||
|
error = SP_ERROR_FILE_FORMAT;
|
||||||
|
goto return_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (hdr.compression)
|
||||||
|
{
|
||||||
|
case SPFILE_COMPRESSION_GZ:
|
||||||
|
{
|
||||||
|
uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
|
||||||
|
uint32_t compsize = hdr.disksize - hdr.dataoffs;
|
||||||
|
uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
|
||||||
|
uLongf destlen = uncompsize;
|
||||||
|
|
||||||
|
char *tempbuf = (char *)malloc(compsize);
|
||||||
|
void *uncompdata = malloc(uncompsize);
|
||||||
|
void *sectheader = malloc(sectsize);
|
||||||
|
|
||||||
|
fread(sectheader, sectsize, 1, fp);
|
||||||
|
fread(tempbuf, compsize, 1, fp);
|
||||||
|
|
||||||
|
z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
|
||||||
|
free(tempbuf);
|
||||||
|
if (z_result != Z_OK)
|
||||||
|
{
|
||||||
|
free(sectheader);
|
||||||
|
free(uncompdata);
|
||||||
|
error = SP_ERROR_DECOMPRESSOR;
|
||||||
|
goto return_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = (uint8_t *)malloc(hdr.imagesize);
|
||||||
|
memcpy(base, &hdr, sizeof(sp_file_hdr_t));
|
||||||
|
memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
|
||||||
|
free(sectheader);
|
||||||
|
memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
|
||||||
|
free(uncompdata);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SPFILE_COMPRESSION_NONE:
|
||||||
|
{
|
||||||
|
base = (uint8_t *)malloc(hdr.imagesize);
|
||||||
|
rewind(fp);
|
||||||
|
fread(base, hdr.imagesize, 1, fp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
error = SP_ERROR_DECOMPRESSOR;
|
||||||
|
goto return_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin = new sp_plugin_t;
|
||||||
|
|
||||||
|
memset(plugin, 0, sizeof(sp_plugin_t));
|
||||||
|
|
||||||
|
plugin->base_size = hdr.imagesize;
|
||||||
|
if (!_ReadPlugin(&hdr, base, plugin, err))
|
||||||
|
{
|
||||||
|
delete plugin;
|
||||||
|
free(base);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pRuntime = new BaseRuntime(plugin);
|
||||||
|
|
||||||
|
if (co == NULL)
|
||||||
|
{
|
||||||
|
co = g_Jit1.StartCompilation(pRuntime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
*err = pRuntime->ApplyCompilationOptions(co);
|
||||||
|
if (*err != SP_ERROR_NONE)
|
||||||
|
{
|
||||||
|
delete pRuntime;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pRuntime;
|
||||||
|
|
||||||
|
return_error:
|
||||||
|
*err = error;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPVM_NATIVE_FUNC SourcePawnEngine2::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
|
||||||
|
{
|
||||||
|
return g_Jit1.CreateFakeNative(callback, pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourcePawnEngine2::DestroyFakeNative(SPVM_NATIVE_FUNC func)
|
||||||
|
{
|
||||||
|
g_Jit1.DestroyFakeNative(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SourcePawnEngine2::GetEngineName()
|
||||||
|
{
|
||||||
|
return "SourcePawn 1.1, jit-x86";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SourcePawnEngine2::GetVersionString()
|
||||||
|
{
|
||||||
|
return SVN_FULL_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
IProfiler *SourcePawnEngine2::GetProfiler()
|
||||||
|
{
|
||||||
|
return m_Profiler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourcePawnEngine2::SetProfiler(IProfiler *profiler)
|
||||||
|
{
|
||||||
|
m_Profiler = profiler;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDebugListener *SourcePawnEngine2::SetDebugListener(IDebugListener *listener)
|
||||||
|
{
|
||||||
|
return g_engine1.SetDebugListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int SourcePawnEngine2::GetAPIVersion()
|
||||||
|
{
|
||||||
|
return SOURCEPAWN_ENGINE2_API_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
ICompilation *SourcePawnEngine2::StartCompilation()
|
||||||
|
{
|
||||||
|
return g_Jit1.StartCompilation();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SourcePawnEngine2::GetErrorString(int err)
|
||||||
|
{
|
||||||
|
return g_engine1.GetErrorString(err);
|
||||||
|
}
|
35
sourcepawn/jit/engine2.h
Normal file
35
sourcepawn/jit/engine2.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEPAWN_ENGINE_2_H_
|
||||||
|
#define _INCLUDE_SOURCEPAWN_ENGINE_2_H_
|
||||||
|
|
||||||
|
#include <sp_vm_api.h>
|
||||||
|
|
||||||
|
namespace SourcePawn
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Outlines the interface a Virtual Machine (JIT) must expose
|
||||||
|
*/
|
||||||
|
class SourcePawnEngine2 : public ISourcePawnEngine2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SourcePawnEngine2();
|
||||||
|
public:
|
||||||
|
unsigned int GetAPIVersion();
|
||||||
|
const char *GetEngineName();
|
||||||
|
const char *GetVersionString();
|
||||||
|
IPluginRuntime *LoadPlugin(ICompilation *co, const char *file, int *err);
|
||||||
|
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
|
||||||
|
void DestroyFakeNative(SPVM_NATIVE_FUNC func);
|
||||||
|
IDebugListener *SetDebugListener(IDebugListener *listener);
|
||||||
|
void SetProfiler(IProfiler *profiler);
|
||||||
|
ICompilation *StartCompilation();
|
||||||
|
const char *GetErrorString(int err);
|
||||||
|
public:
|
||||||
|
IProfiler *GetProfiler();
|
||||||
|
private:
|
||||||
|
IProfiler *m_Profiler;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extern SourcePawn::SourcePawnEngine2 g_engine2;
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEPAWN_ENGINE_2_H_
|
95
sourcepawn/jit/jit_shared.h
Normal file
95
sourcepawn/jit/jit_shared.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEPAWN_JIT_SHARED_H_
|
||||||
|
#define _INCLUDE_SOURCEPAWN_JIT_SHARED_H_
|
||||||
|
|
||||||
|
#include <sp_vm_api.h>
|
||||||
|
|
||||||
|
using namespace SourcePawn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Information about the core plugin tables. These may or may not be present!
|
||||||
|
*/
|
||||||
|
typedef struct sp_plugin_infotab_s
|
||||||
|
{
|
||||||
|
const char *stringbase; /**< base of string table */
|
||||||
|
uint32_t publics_num; /**< number of publics */
|
||||||
|
sp_file_publics_t *publics; /**< public table */
|
||||||
|
uint32_t natives_num; /**< number of natives */
|
||||||
|
sp_file_natives_t *natives; /**< native table */
|
||||||
|
uint32_t pubvars_num; /**< number of pubvars */
|
||||||
|
sp_file_pubvars_t *pubvars; /**< pubvars table */
|
||||||
|
} sp_plugin_infotab_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Information about the plugin's debug tables. These are all present if one is present.
|
||||||
|
*/
|
||||||
|
typedef struct sp_plugin_debug_s
|
||||||
|
{
|
||||||
|
const char *stringbase; /**< base of string table */
|
||||||
|
uint32_t files_num; /**< number of files */
|
||||||
|
sp_fdbg_file_t *files; /**< files table */
|
||||||
|
uint32_t lines_num; /**< number of lines */
|
||||||
|
sp_fdbg_line_t *lines; /**< lines table */
|
||||||
|
uint32_t syms_num; /**< number of symbols */
|
||||||
|
sp_fdbg_symbol_t *symbols; /**< symbol table */
|
||||||
|
} sp_plugin_debug_t;
|
||||||
|
|
||||||
|
class BaseContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Breaks into a debugger
|
||||||
|
* Params:
|
||||||
|
* [0] - plugin context
|
||||||
|
* [1] - frm
|
||||||
|
* [2] - cip
|
||||||
|
*/
|
||||||
|
typedef int (*SPVM_DEBUGBREAK)(BaseContext *, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The rebased memory format of a plugin. This differs from the on-disk structure
|
||||||
|
* to ensure that the format is properly read.
|
||||||
|
*/
|
||||||
|
namespace SourcePawn
|
||||||
|
{
|
||||||
|
typedef struct sp_plugin_s
|
||||||
|
{
|
||||||
|
uint8_t *base; /**< Base of memory for this plugin. */
|
||||||
|
uint8_t *pcode; /**< P-Code of plugin */
|
||||||
|
uint32_t pcode_size; /**< Size of p-code */
|
||||||
|
uint8_t *data; /**< Data/memory layout */
|
||||||
|
uint32_t data_size; /**< Size of data */
|
||||||
|
uint32_t mem_size; /**< Required memory space */
|
||||||
|
uint16_t flags; /**< Code flags */
|
||||||
|
sp_plugin_infotab_t info; /**< Base info table */
|
||||||
|
sp_plugin_debug_t debug; /**< Debug info table */
|
||||||
|
size_t base_size; /**< Size of the entire plugin base */
|
||||||
|
void *codebase; /**< Base of generated code and memory */
|
||||||
|
SPVM_DEBUGBREAK dbreak; /**< Debug break function */
|
||||||
|
uint8_t *memory; /**< Data chunk */
|
||||||
|
sp_public_t *publics; /**< Public functions table */
|
||||||
|
sp_pubvar_t *pubvars; /**< Public variables table */
|
||||||
|
sp_native_t *natives; /**< Natives table */
|
||||||
|
sp_debug_file_t *files; /**< Files */
|
||||||
|
sp_debug_line_t *lines; /**< Lines */
|
||||||
|
sp_debug_symbol_t *symbols; /**< Symbols */
|
||||||
|
IProfiler *profiler; /**< Pointer to IProfiler */
|
||||||
|
uint32_t prof_flags; /**< Profiling flags */
|
||||||
|
uint32_t run_flags; /**< Runtime flags */
|
||||||
|
size_t jit_codesize; /**< JIT compiled codesize */
|
||||||
|
size_t jit_memsize; /**< JIT additional memory */
|
||||||
|
} sp_plugin_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct sp_context_s
|
||||||
|
{
|
||||||
|
cell_t hp; /**< Heap pointer */
|
||||||
|
cell_t sp; /**< Stack pointer */
|
||||||
|
cell_t frm; /**< Frame pointer */
|
||||||
|
int32_t n_err; /**< Error code set by a native */
|
||||||
|
uint32_t n_idx; /**< Current native index being executed */
|
||||||
|
void * vm[8]; /**< VM-specific pointers */
|
||||||
|
} sp_context_t;
|
||||||
|
|
||||||
|
#define SPFLAG_PLUGIN_DEBUG (1<<0)
|
||||||
|
#define SPFLAG_PLUGIN_PAUSED (1<<1)
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEPAWN_JIT_SHARED_H_
|
@ -40,7 +40,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="..\..\..\..\public\jit;..\..\..\..\public\jit\x86;..\..\..\..\public\sourcepawn"
|
AdditionalIncludeDirectories="..\..\..\public\jit;..\..\..\public\jit\x86;..\..\..\public\sourcepawn"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
@ -185,24 +185,44 @@
|
|||||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BaseRuntime.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\dll_exports.cpp"
|
RelativePath="..\dll_exports.cpp"
|
||||||
>
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\engine2.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\x86\jit_x86.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\x86\opcode_helpers.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sp_vm_basecontext.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sp_vm_engine.cpp"
|
||||||
|
>
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
Name="Debug|Win32"
|
Name="Debug|Win32"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
AdditionalIncludeDirectories=""
|
AdditionalIncludeDirectories=""$(SOURCEMM16)\sourcehook""
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\jit_x86.cpp"
|
RelativePath="..\sp_vm_function.cpp"
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\opcode_helpers.cpp"
|
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
@ -211,12 +231,20 @@
|
|||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BaseRuntime.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\dll_exports.h"
|
RelativePath="..\dll_exports.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\..\public\jit\jit_helpers.h"
|
RelativePath="..\engine2.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\jit_shared.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
@ -224,19 +252,23 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\jit_x86.h"
|
RelativePath="..\x86\jit_x86.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\opcode_helpers.h"
|
RelativePath="..\x86\opcode_helpers.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\ungen_opcodes.h"
|
RelativePath="..\sp_vm_basecontext.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\..\public\jit\x86\x86_macros.h"
|
RelativePath="..\sp_vm_engine.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sp_vm_function.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
@ -245,18 +277,6 @@
|
|||||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
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}"
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
>
|
>
|
||||||
<File
|
|
||||||
RelativePath="..\jit_version.tpl"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\opcode_switch.inc"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\ungen_opcode_switch.inc"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\version.rc"
|
RelativePath="..\version.rc"
|
||||||
>
|
>
|
||||||
@ -266,27 +286,75 @@
|
|||||||
Name="SDK"
|
Name="SDK"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\jit_helpers.h"
|
RelativePath="..\..\..\public\sourcepawn\sp_file_headers.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\..\public\sourcepawn\sp_file_headers.h"
|
RelativePath="..\..\..\public\sourcepawn\sp_typeutil.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\..\public\sourcepawn\sp_typeutil.h"
|
RelativePath="..\..\..\public\sourcepawn\sp_vm_api.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\..\public\sourcepawn\sp_vm_api.h"
|
RelativePath="..\..\..\public\sourcepawn\sp_vm_base.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\..\public\sourcepawn\sp_vm_base.h"
|
RelativePath="..\..\..\public\sourcepawn\sp_vm_types.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="zlib"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\zlib\adler32.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\..\public\sourcepawn\sp_vm_types.h"
|
RelativePath="..\zlib\compress.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\zlib\crc32.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\zlib\deflate.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\zlib\gzio.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\zlib\infback.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\zlib\inffast.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\zlib\inflate.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\zlib\inftrees.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\zlib\trees.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\zlib\uncompr.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\zlib\zutil.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
810
sourcepawn/jit/sp_vm_basecontext.cpp
Normal file
810
sourcepawn/jit/sp_vm_basecontext.cpp
Normal file
@ -0,0 +1,810 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* =============================================================================
|
||||||
|
* SourcePawn
|
||||||
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
|
* =============================================================================
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include "sp_vm_api.h"
|
||||||
|
#include "sp_vm_basecontext.h"
|
||||||
|
#include "sp_vm_engine.h"
|
||||||
|
#include "x86/jit_x86.h"
|
||||||
|
|
||||||
|
using namespace SourcePawn;
|
||||||
|
|
||||||
|
#define CELLBOUNDMAX (INT_MAX/sizeof(cell_t))
|
||||||
|
#define STACKMARGIN ((cell_t)(16*sizeof(cell_t)))
|
||||||
|
|
||||||
|
BaseContext::BaseContext(BaseRuntime *pRuntime)
|
||||||
|
{
|
||||||
|
m_pRuntime = pRuntime;
|
||||||
|
m_pPlugin = m_pRuntime->m_pPlugin;
|
||||||
|
|
||||||
|
m_InExec = false;
|
||||||
|
m_CustomMsg = false;
|
||||||
|
|
||||||
|
m_pNullVec = NULL;
|
||||||
|
m_pNullString = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseContext::~BaseContext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IVirtualMachine *BaseContext::GetVirtualMachine()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp_context_t *BaseContext::GetContext()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<sp_context_t *>((IPluginContext * )this);
|
||||||
|
}
|
||||||
|
|
||||||
|
sp_context_t *BaseContext::GetCtx()
|
||||||
|
{
|
||||||
|
return &m_ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseContext::IsDebugging()
|
||||||
|
{
|
||||||
|
return m_pRuntime->IsDebugging();
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::SetDebugBreak(void *newpfn, void *oldpfn)
|
||||||
|
{
|
||||||
|
return SP_ERROR_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPluginDebugInfo *BaseContext::GetDebugInfo()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::Execute(uint32_t code_addr, cell_t *result)
|
||||||
|
{
|
||||||
|
return SP_ERROR_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseContext::SetErrorMessage(const char *msg, va_list ap)
|
||||||
|
{
|
||||||
|
m_CustomMsg = true;
|
||||||
|
|
||||||
|
vsnprintf(m_MsgCache, sizeof(m_MsgCache), msg, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseContext::_SetErrorMessage(const char *msg, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, msg);
|
||||||
|
SetErrorMessage(msg, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_t BaseContext::ThrowNativeErrorEx(int error, const char *msg, ...)
|
||||||
|
{
|
||||||
|
if (!m_InExec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ctx.n_err = error;
|
||||||
|
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, msg);
|
||||||
|
SetErrorMessage(msg, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_t BaseContext::ThrowNativeError(const char *msg, ...)
|
||||||
|
{
|
||||||
|
if (!m_InExec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ctx.n_err = SP_ERROR_NATIVE;
|
||||||
|
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, msg);
|
||||||
|
SetErrorMessage(msg, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr)
|
||||||
|
{
|
||||||
|
cell_t *addr;
|
||||||
|
ucell_t realmem;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (cells > CELLBOUNDMAX)
|
||||||
|
{
|
||||||
|
return SP_ERROR_ARAM;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
assert(cells < CELLBOUNDMAX);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
realmem = cells * sizeof(cell_t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the space between the heap and stack is sufficient.
|
||||||
|
*/
|
||||||
|
if ((cell_t)(m_ctx.sp - m_ctx.hp - realmem) < STACKMARGIN)
|
||||||
|
{
|
||||||
|
return SP_ERROR_HEAPLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = (cell_t *)(m_pPlugin->memory + m_ctx.hp);
|
||||||
|
/* store size of allocation in cells */
|
||||||
|
*addr = (cell_t)cells;
|
||||||
|
addr++;
|
||||||
|
m_ctx.hp += sizeof(cell_t);
|
||||||
|
|
||||||
|
*local_addr = m_ctx.hp;
|
||||||
|
|
||||||
|
if (phys_addr)
|
||||||
|
{
|
||||||
|
*phys_addr = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ctx.hp += realmem;
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::HeapPop(cell_t local_addr)
|
||||||
|
{
|
||||||
|
cell_t cellcount;
|
||||||
|
cell_t *addr;
|
||||||
|
|
||||||
|
/* check the bounds of this address */
|
||||||
|
local_addr -= sizeof(cell_t);
|
||||||
|
if (local_addr < (cell_t)m_pPlugin->data_size || local_addr >= m_ctx.sp)
|
||||||
|
{
|
||||||
|
return SP_ERROR_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = (cell_t *)(m_pPlugin->memory + local_addr);
|
||||||
|
cellcount = (*addr) * sizeof(cell_t);
|
||||||
|
/* check if this memory count looks valid */
|
||||||
|
if ((signed)(m_ctx.hp - cellcount - sizeof(cell_t)) != local_addr)
|
||||||
|
{
|
||||||
|
return SP_ERROR_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ctx.hp = local_addr;
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int BaseContext::HeapRelease(cell_t local_addr)
|
||||||
|
{
|
||||||
|
if (local_addr < (cell_t)m_pPlugin->data_size)
|
||||||
|
{
|
||||||
|
return SP_ERROR_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ctx.hp = local_addr - sizeof(cell_t);
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::FindNativeByName(const char *name, uint32_t *index)
|
||||||
|
{
|
||||||
|
return m_pRuntime->FindNativeByName(name, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::GetNativeByIndex(uint32_t index, sp_native_t **native)
|
||||||
|
{
|
||||||
|
return m_pRuntime->GetNativeByIndex(index, native);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t BaseContext::GetNativesNum()
|
||||||
|
{
|
||||||
|
return m_pRuntime->GetNativesNum();
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::FindPublicByName(const char *name, uint32_t *index)
|
||||||
|
{
|
||||||
|
return m_pRuntime->FindPublicByName(name, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
|
||||||
|
{
|
||||||
|
return m_pRuntime->GetPublicByIndex(index, pblic);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t BaseContext::GetPublicsNum()
|
||||||
|
{
|
||||||
|
return m_pRuntime->GetPublicsNum();
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
|
||||||
|
{
|
||||||
|
return m_pRuntime->GetPubvarByIndex(index, pubvar);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::FindPubvarByName(const char *name, uint32_t *index)
|
||||||
|
{
|
||||||
|
return m_pRuntime->FindPubvarByName(name, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
|
||||||
|
{
|
||||||
|
return m_pRuntime->GetPubvarAddrs(index, local_addr, phys_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t BaseContext::GetPubVarsNum()
|
||||||
|
{
|
||||||
|
return m_pRuntime->GetPubVarsNum();
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite)
|
||||||
|
{
|
||||||
|
return SP_ERROR_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::BindNative(const sp_nativeinfo_t *native)
|
||||||
|
{
|
||||||
|
return SP_ERROR_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC func)
|
||||||
|
{
|
||||||
|
return SP_ERROR_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::BindNativeToAny(SPVM_NATIVE_FUNC native)
|
||||||
|
{
|
||||||
|
return SP_ERROR_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr)
|
||||||
|
{
|
||||||
|
if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
|
||||||
|
|| (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
|
||||||
|
{
|
||||||
|
return SP_ERROR_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phys_addr)
|
||||||
|
{
|
||||||
|
*phys_addr = (cell_t *)(m_pPlugin->memory + local_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::PushCell(cell_t value)
|
||||||
|
{
|
||||||
|
return SP_ERROR_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::PushCellsFromArray(cell_t array[], unsigned int numcells)
|
||||||
|
{
|
||||||
|
return SP_ERROR_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells)
|
||||||
|
{
|
||||||
|
return SP_ERROR_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::LocalToString(cell_t local_addr, char **addr)
|
||||||
|
{
|
||||||
|
if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
|
||||||
|
|| (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
|
||||||
|
{
|
||||||
|
return SP_ERROR_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
*addr = (char *)(m_pPlugin->memory + local_addr);
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::PushString(cell_t *local_addr, char **phys_addr, const char *string)
|
||||||
|
{
|
||||||
|
return SP_ERROR_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source)
|
||||||
|
{
|
||||||
|
char *dest;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
|
||||||
|
|| (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
|
||||||
|
{
|
||||||
|
return SP_ERROR_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes == 0)
|
||||||
|
{
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(source);
|
||||||
|
dest = (char *)(m_pPlugin->memory + local_addr);
|
||||||
|
|
||||||
|
if (len >= bytes)
|
||||||
|
{
|
||||||
|
len = bytes - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(dest, source, len);
|
||||||
|
dest[len] = '\0';
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int __CheckValidChar(char *c)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
int bytecount = 0;
|
||||||
|
|
||||||
|
for (count=1; (*c & 0xC0) == 0x80; count++)
|
||||||
|
{
|
||||||
|
c--;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (*c & 0xF0)
|
||||||
|
{
|
||||||
|
case 0xC0:
|
||||||
|
case 0xD0:
|
||||||
|
{
|
||||||
|
bytecount = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xE0:
|
||||||
|
{
|
||||||
|
bytecount = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xF0:
|
||||||
|
{
|
||||||
|
bytecount = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytecount != count)
|
||||||
|
{
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes)
|
||||||
|
{
|
||||||
|
char *dest;
|
||||||
|
size_t len;
|
||||||
|
bool needtocheck = false;
|
||||||
|
|
||||||
|
if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
|
||||||
|
|| (local_addr < 0)
|
||||||
|
|| ((ucell_t)local_addr >= m_pPlugin->mem_size))
|
||||||
|
{
|
||||||
|
return SP_ERROR_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxbytes == 0)
|
||||||
|
{
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(source);
|
||||||
|
dest = (char *)(m_pPlugin->memory + local_addr);
|
||||||
|
|
||||||
|
if ((size_t)len >= maxbytes)
|
||||||
|
{
|
||||||
|
len = maxbytes - 1;
|
||||||
|
needtocheck = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(dest, source, len);
|
||||||
|
if ((dest[len-1] & 1<<7) && needtocheck)
|
||||||
|
{
|
||||||
|
len -= __CheckValidChar(dest+len-1);
|
||||||
|
}
|
||||||
|
dest[len] = '\0';
|
||||||
|
|
||||||
|
if (wrtnbytes)
|
||||||
|
{
|
||||||
|
*wrtnbytes = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPluginFunction *BaseContext::GetFunctionById(funcid_t func_id)
|
||||||
|
{
|
||||||
|
return m_pRuntime->GetFunctionById(func_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPluginFunction *BaseContext::GetFunctionByName(const char *public_name)
|
||||||
|
{
|
||||||
|
return m_pRuntime->GetFunctionByName(public_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::LocalToStringNULL(cell_t local_addr, char **addr)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
if ((err = LocalToString(local_addr, addr)) != SP_ERROR_NONE)
|
||||||
|
{
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cell_t *)*addr == m_pNullString)
|
||||||
|
{
|
||||||
|
*addr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceMod::IdentityToken_t *BaseContext::GetIdentity()
|
||||||
|
{
|
||||||
|
SourceMod::IdentityToken_t *tok;
|
||||||
|
|
||||||
|
if (GetKey(1, (void **)&tok))
|
||||||
|
{
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_t *BaseContext::GetNullRef(SP_NULL_TYPE type)
|
||||||
|
{
|
||||||
|
if (type == SP_NULL_VECTOR)
|
||||||
|
{
|
||||||
|
return m_pNullVec;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseContext::IsInExec()
|
||||||
|
{
|
||||||
|
return m_InExec;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseContext::Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result)
|
||||||
|
{
|
||||||
|
int ir;
|
||||||
|
int serial;
|
||||||
|
cell_t *sp;
|
||||||
|
funcid_t fnid;
|
||||||
|
sp_public_t *pubfunc;
|
||||||
|
cell_t _ignore_result;
|
||||||
|
|
||||||
|
fnid = function->GetFunctionID();
|
||||||
|
|
||||||
|
if (fnid & 1)
|
||||||
|
{
|
||||||
|
unsigned int public_id;
|
||||||
|
|
||||||
|
public_id = fnid >> 1;
|
||||||
|
|
||||||
|
if (m_pRuntime->GetPublicByIndex(public_id, &pubfunc) != SP_ERROR_NONE)
|
||||||
|
{
|
||||||
|
return SP_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return SP_ERROR_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_pRuntime->IsPaused())
|
||||||
|
{
|
||||||
|
return SP_ERROR_NOT_RUNNABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cell_t)(m_ctx.hp + 16*sizeof(cell_t)) > (cell_t)(m_ctx.sp - (sizeof(cell_t) * (num_params + 1))))
|
||||||
|
{
|
||||||
|
return SP_ERROR_STACKLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
result = &_ignore_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We got this far. It's time to start profiling. */
|
||||||
|
|
||||||
|
if ((m_pPlugin->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS)
|
||||||
|
{
|
||||||
|
serial = m_pPlugin->profiler->OnCallbackBegin(this, pubfunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save our previous state. */
|
||||||
|
|
||||||
|
bool save_exec;
|
||||||
|
uint32_t save_n_idx;
|
||||||
|
cell_t save_sp, save_hp;
|
||||||
|
|
||||||
|
save_sp = m_ctx.sp;
|
||||||
|
save_hp = m_ctx.hp;
|
||||||
|
save_exec = m_InExec;
|
||||||
|
save_n_idx = m_ctx.n_idx;
|
||||||
|
|
||||||
|
/* Push parameters */
|
||||||
|
|
||||||
|
m_ctx.sp -= sizeof(cell_t) * (num_params + 1);
|
||||||
|
sp = (cell_t *)(m_pPlugin->memory + m_ctx.sp);
|
||||||
|
|
||||||
|
sp[0] = num_params;
|
||||||
|
for (unsigned int i = 0; i < num_params; i++)
|
||||||
|
{
|
||||||
|
sp[i + 1] = params[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear internal state */
|
||||||
|
m_ctx.n_err = SP_ERROR_NONE;
|
||||||
|
m_ctx.n_idx = 0;
|
||||||
|
m_MsgCache[0] = '\0';
|
||||||
|
m_CustomMsg = false;
|
||||||
|
m_InExec = false;
|
||||||
|
|
||||||
|
/* Start the tracer */
|
||||||
|
|
||||||
|
g_engine1.PushTracer(this);
|
||||||
|
|
||||||
|
/* Execute the function */
|
||||||
|
|
||||||
|
ir = g_Jit1.ContextExecute(m_pPlugin, &m_ctx, pubfunc->code_offs, result);
|
||||||
|
|
||||||
|
/* Restore some states, stop tracing */
|
||||||
|
|
||||||
|
m_InExec = save_exec;
|
||||||
|
|
||||||
|
if (ir == SP_ERROR_NONE)
|
||||||
|
{
|
||||||
|
m_ctx.n_err = SP_ERROR_NONE;
|
||||||
|
if (m_ctx.sp != save_sp)
|
||||||
|
{
|
||||||
|
ir = SP_ERROR_STACKLEAK;
|
||||||
|
_SetErrorMessage("Stack leak detected: sp:%d should be %d!",
|
||||||
|
m_ctx.sp,
|
||||||
|
save_sp);
|
||||||
|
}
|
||||||
|
if (m_ctx.hp != save_hp)
|
||||||
|
{
|
||||||
|
ir = SP_ERROR_HEAPLEAK;
|
||||||
|
_SetErrorMessage("Heap leak detected: hp:%d should be %d!",
|
||||||
|
m_ctx.hp,
|
||||||
|
save_hp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ctx.sp = save_sp;
|
||||||
|
m_ctx.hp = save_hp;
|
||||||
|
|
||||||
|
g_engine1.PopTracer(ir, m_CustomMsg ? m_MsgCache : NULL);
|
||||||
|
|
||||||
|
if ((m_pPlugin->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS)
|
||||||
|
{
|
||||||
|
m_pPlugin->profiler->OnCallbackEnd(serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ctx.n_idx = save_n_idx;
|
||||||
|
m_ctx.n_err = SP_ERROR_NONE;
|
||||||
|
m_MsgCache[0] = '\0';
|
||||||
|
m_CustomMsg = false;
|
||||||
|
|
||||||
|
return ir;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPluginRuntime *BaseContext::GetRuntime()
|
||||||
|
{
|
||||||
|
return m_pRuntime;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseRuntime::ApplyCompilationOptions(ICompilation *co)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* The JIT does not destroy anything until it is guaranteed to succeed. */
|
||||||
|
if (!g_Jit1.Compile(co, this, &err))
|
||||||
|
{
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshFunctionCache();
|
||||||
|
|
||||||
|
m_pCtx->Refresh();
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugInfo::DebugInfo(sp_plugin_t *plugin) : m_pPlugin(plugin)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#define USHR(x) ((unsigned int)(x)>>1)
|
||||||
|
|
||||||
|
int DebugInfo::LookupFile(ucell_t addr, const char **filename)
|
||||||
|
{
|
||||||
|
int high, low, mid;
|
||||||
|
|
||||||
|
high = m_pPlugin->debug.files_num;
|
||||||
|
low = -1;
|
||||||
|
|
||||||
|
while (high - low > 1)
|
||||||
|
{
|
||||||
|
mid = USHR(low + high);
|
||||||
|
if (m_pPlugin->files[mid].addr <= addr)
|
||||||
|
{
|
||||||
|
low = mid;
|
||||||
|
} else {
|
||||||
|
high = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (low == -1)
|
||||||
|
{
|
||||||
|
return SP_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
*filename = m_pPlugin->files[low].name;
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DebugInfo::LookupFunction(ucell_t addr, const char **name)
|
||||||
|
{
|
||||||
|
uint32_t iter, max = m_pPlugin->debug.syms_num;
|
||||||
|
|
||||||
|
for (iter=0; iter<max; iter++)
|
||||||
|
{
|
||||||
|
if ((m_pPlugin->symbols[iter].sym->ident == SP_SYM_FUNCTION)
|
||||||
|
&& (m_pPlugin->symbols[iter].codestart <= addr)
|
||||||
|
&& (m_pPlugin->symbols[iter].codeend > addr))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter >= max)
|
||||||
|
{
|
||||||
|
return SP_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
*name = m_pPlugin->symbols[iter].name;
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DebugInfo::LookupLine(ucell_t addr, uint32_t *line)
|
||||||
|
{
|
||||||
|
int high, low, mid;
|
||||||
|
|
||||||
|
high = m_pPlugin->debug.lines_num;
|
||||||
|
low = -1;
|
||||||
|
|
||||||
|
while (high - low > 1)
|
||||||
|
{
|
||||||
|
mid = USHR(low + high);
|
||||||
|
if (m_pPlugin->lines[mid].addr <= addr)
|
||||||
|
{
|
||||||
|
low = mid;
|
||||||
|
} else {
|
||||||
|
high = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (low == -1)
|
||||||
|
{
|
||||||
|
return SP_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Since the CIP occurs BEFORE the line, we have to add one */
|
||||||
|
*line = m_pPlugin->lines[low].line + 1;
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef USHR
|
||||||
|
|
||||||
|
int BaseContext::GetLastNativeError()
|
||||||
|
{
|
||||||
|
return m_ctx.n_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_t *BaseContext::GetLocalParams()
|
||||||
|
{
|
||||||
|
return (cell_t *)(m_pPlugin->memory + m_ctx.frm + (2 * sizeof(cell_t)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseContext::SetKey(int k, void *value)
|
||||||
|
{
|
||||||
|
if (k < 1 || k > 4)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_keys[k - 1] = value;
|
||||||
|
m_keys_set[k - 1] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseContext::GetKey(int k, void **value)
|
||||||
|
{
|
||||||
|
if (k < 1 || k > 4 || m_keys_set[k - 1] == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = m_keys[k - 1];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseContext::Refresh()
|
||||||
|
{
|
||||||
|
/* Initialize the null references */
|
||||||
|
uint32_t index;
|
||||||
|
if (FindPubvarByName("NULL_VECTOR", &index) == SP_ERROR_NONE)
|
||||||
|
{
|
||||||
|
sp_pubvar_t *pubvar;
|
||||||
|
GetPubvarByIndex(index, &pubvar);
|
||||||
|
m_pNullVec = pubvar->offs;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pNullVec = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FindPubvarByName("NULL_STRING", &index) == SP_ERROR_NONE)
|
||||||
|
{
|
||||||
|
sp_pubvar_t *pubvar;
|
||||||
|
GetPubvarByIndex(index, &pubvar);
|
||||||
|
m_pNullString = pubvar->offs;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pNullString = NULL;
|
||||||
|
}
|
||||||
|
}
|
114
sourcepawn/jit/sp_vm_basecontext.h
Normal file
114
sourcepawn/jit/sp_vm_basecontext.h
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* =============================================================================
|
||||||
|
* SourcePawn
|
||||||
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
|
* =============================================================================
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
|
||||||
|
#define _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
|
||||||
|
|
||||||
|
#include "sp_vm_api.h"
|
||||||
|
#include "sp_vm_function.h"
|
||||||
|
#include "BaseRuntime.h"
|
||||||
|
#include "jit_shared.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* :TODO: Make functions allocate as a lump instead of individual allocations!
|
||||||
|
*/
|
||||||
|
|
||||||
|
class BaseContext : public IPluginContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BaseContext(BaseRuntime *pRuntime);
|
||||||
|
~BaseContext();
|
||||||
|
public: //IPluginContext
|
||||||
|
IVirtualMachine *GetVirtualMachine();
|
||||||
|
sp_context_t *GetContext();
|
||||||
|
sp_context_t *GetCtx();
|
||||||
|
bool IsDebugging();
|
||||||
|
int SetDebugBreak(void *newpfn, void *oldpfn);
|
||||||
|
IPluginDebugInfo *GetDebugInfo();
|
||||||
|
int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr);
|
||||||
|
int HeapPop(cell_t local_addr);
|
||||||
|
int HeapRelease(cell_t local_addr);
|
||||||
|
int FindNativeByName(const char *name, uint32_t *index);
|
||||||
|
int GetNativeByIndex(uint32_t index, sp_native_t **native);
|
||||||
|
uint32_t GetNativesNum();
|
||||||
|
int FindPublicByName(const char *name, uint32_t *index);
|
||||||
|
int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
|
||||||
|
uint32_t GetPublicsNum();
|
||||||
|
int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
|
||||||
|
int FindPubvarByName(const char *name, uint32_t *index);
|
||||||
|
int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
|
||||||
|
uint32_t GetPubVarsNum();
|
||||||
|
int LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr);
|
||||||
|
int LocalToString(cell_t local_addr, char **addr);
|
||||||
|
int StringToLocal(cell_t local_addr, size_t chars, const char *source);
|
||||||
|
int StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes);
|
||||||
|
int PushCell(cell_t value);
|
||||||
|
int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells);
|
||||||
|
int PushString(cell_t *local_addr, char **phys_addr, const char *string);
|
||||||
|
int PushCellsFromArray(cell_t array[], unsigned int numcells);
|
||||||
|
int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite);
|
||||||
|
int BindNative(const sp_nativeinfo_t *native);
|
||||||
|
int BindNativeToAny(SPVM_NATIVE_FUNC native);
|
||||||
|
int Execute(uint32_t code_addr, cell_t *result);
|
||||||
|
cell_t ThrowNativeErrorEx(int error, const char *msg, ...);
|
||||||
|
cell_t ThrowNativeError(const char *msg, ...);
|
||||||
|
IPluginFunction *GetFunctionByName(const char *public_name);
|
||||||
|
IPluginFunction *GetFunctionById(funcid_t func_id);
|
||||||
|
SourceMod::IdentityToken_t *GetIdentity();
|
||||||
|
cell_t *GetNullRef(SP_NULL_TYPE type);
|
||||||
|
int LocalToStringNULL(cell_t local_addr, char **addr);
|
||||||
|
int BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC native);
|
||||||
|
int Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result);
|
||||||
|
IPluginRuntime *GetRuntime();
|
||||||
|
int GetLastNativeError();
|
||||||
|
cell_t *GetLocalParams();
|
||||||
|
void SetKey(int k, void *value);
|
||||||
|
bool GetKey(int k, void **value);
|
||||||
|
void Refresh();
|
||||||
|
public:
|
||||||
|
bool IsInExec();
|
||||||
|
private:
|
||||||
|
void SetErrorMessage(const char *msg, va_list ap);
|
||||||
|
void _SetErrorMessage(const char *msg, ...);
|
||||||
|
private:
|
||||||
|
sp_plugin_t *m_pPlugin;
|
||||||
|
cell_t *m_pNullVec;
|
||||||
|
cell_t *m_pNullString;
|
||||||
|
char m_MsgCache[1024];
|
||||||
|
bool m_CustomMsg;
|
||||||
|
bool m_InExec;
|
||||||
|
BaseRuntime *m_pRuntime;
|
||||||
|
sp_context_t m_ctx;
|
||||||
|
void *m_keys[4];
|
||||||
|
bool m_keys_set[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_
|
@ -48,6 +48,8 @@
|
|||||||
#include "zlib/zlib.h"
|
#include "zlib/zlib.h"
|
||||||
#include "sp_vm_basecontext.h"
|
#include "sp_vm_basecontext.h"
|
||||||
|
|
||||||
|
SourcePawnEngine g_engine1;
|
||||||
|
|
||||||
#if defined WIN32
|
#if defined WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -92,7 +94,7 @@ static const char *g_ErrorMsgTable[] =
|
|||||||
"Call was aborted",
|
"Call was aborted",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *GetSourcePawnErrorMessage(int error)
|
const char *SourcePawnEngine::GetErrorString(int error)
|
||||||
{
|
{
|
||||||
if (error < 1 || error > ERROR_MESSAGE_MAX)
|
if (error < 1 || error > ERROR_MESSAGE_MAX)
|
||||||
{
|
{
|
||||||
@ -188,281 +190,31 @@ void SourcePawnEngine::BaseFree(void *memory)
|
|||||||
free(memory);
|
free(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPluginContext *SourcePawnEngine::CreateBaseContext(sp_context_t *ctx)
|
|
||||||
{
|
|
||||||
return new BaseContext(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SourcePawnEngine::FreeBaseContext(IPluginContext *ctx)
|
|
||||||
{
|
|
||||||
delete ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp_plugin_t *_ReadPlugin(sp_file_hdr_t *hdr, uint8_t *base, sp_plugin_t *plugin, int *err)
|
|
||||||
{
|
|
||||||
char *nameptr;
|
|
||||||
uint8_t sectnum = 0;
|
|
||||||
sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
|
|
||||||
|
|
||||||
memset(plugin, 0, sizeof(sp_plugin_t));
|
|
||||||
|
|
||||||
plugin->base = base;
|
|
||||||
|
|
||||||
while (sectnum < hdr->sections)
|
|
||||||
{
|
|
||||||
nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
|
|
||||||
|
|
||||||
if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
|
|
||||||
{
|
|
||||||
sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
|
|
||||||
plugin->pcode = base + secptr->dataoffs + cod->code;
|
|
||||||
plugin->pcode_size = cod->codesize;
|
|
||||||
plugin->flags = cod->flags;
|
|
||||||
}
|
|
||||||
else if (!(plugin->data) && !strcmp(nameptr, ".data"))
|
|
||||||
{
|
|
||||||
sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
|
|
||||||
plugin->data = base + secptr->dataoffs + dat->data;
|
|
||||||
plugin->data_size = dat->datasize;
|
|
||||||
plugin->memory = dat->memsize;
|
|
||||||
}
|
|
||||||
else if (!(plugin->info.publics) && !strcmp(nameptr, ".publics"))
|
|
||||||
{
|
|
||||||
plugin->info.publics_num = secptr->size / sizeof(sp_file_publics_t);
|
|
||||||
plugin->info.publics = (sp_file_publics_t *)(base + secptr->dataoffs);
|
|
||||||
}
|
|
||||||
else if (!(plugin->info.pubvars) && !strcmp(nameptr, ".pubvars"))
|
|
||||||
{
|
|
||||||
plugin->info.pubvars_num = secptr->size / sizeof(sp_file_pubvars_t);
|
|
||||||
plugin->info.pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
|
|
||||||
}
|
|
||||||
else if (!(plugin->info.natives) && !strcmp(nameptr, ".natives"))
|
|
||||||
{
|
|
||||||
plugin->info.natives_num = secptr->size / sizeof(sp_file_natives_t);
|
|
||||||
plugin->info.natives = (sp_file_natives_t *)(base + secptr->dataoffs);
|
|
||||||
}
|
|
||||||
else if (!(plugin->info.stringbase) && !strcmp(nameptr, ".names"))
|
|
||||||
{
|
|
||||||
plugin->info.stringbase = (const char *)(base + secptr->dataoffs);
|
|
||||||
}
|
|
||||||
else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
|
|
||||||
{
|
|
||||||
plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
|
|
||||||
}
|
|
||||||
else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
|
|
||||||
{
|
|
||||||
plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
|
|
||||||
}
|
|
||||||
else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
|
|
||||||
{
|
|
||||||
plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
|
|
||||||
}
|
|
||||||
else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
|
|
||||||
{
|
|
||||||
sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
|
|
||||||
plugin->debug.files_num = inf->num_files;
|
|
||||||
plugin->debug.lines_num = inf->num_lines;
|
|
||||||
plugin->debug.syms_num = inf->num_syms;
|
|
||||||
}
|
|
||||||
else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
|
|
||||||
{
|
|
||||||
plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
|
|
||||||
}
|
|
||||||
|
|
||||||
secptr++;
|
|
||||||
sectnum++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(plugin->pcode) || !(plugin->data) || !(plugin->info.stringbase))
|
|
||||||
{
|
|
||||||
goto return_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
|
|
||||||
{
|
|
||||||
goto return_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
*err = SP_ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return plugin;
|
|
||||||
|
|
||||||
return_error:
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
*err = SP_ERROR_FILE_FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp_plugin_t *SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err)
|
sp_plugin_t *SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err)
|
||||||
{
|
{
|
||||||
sp_file_hdr_t hdr;
|
if (err != NULL)
|
||||||
sp_plugin_t *plugin;
|
|
||||||
uint8_t *base;
|
|
||||||
int z_result;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if (!fp)
|
|
||||||
{
|
{
|
||||||
error = SP_ERROR_NOT_FOUND;
|
*err = SP_ERROR_ABORTED;
|
||||||
goto return_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rewind for safety */
|
|
||||||
rewind(fp);
|
|
||||||
fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
|
|
||||||
|
|
||||||
if (hdr.magic != SPFILE_MAGIC)
|
|
||||||
{
|
|
||||||
error = SP_ERROR_FILE_FORMAT;
|
|
||||||
goto return_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (hdr.compression)
|
|
||||||
{
|
|
||||||
case SPFILE_COMPRESSION_GZ:
|
|
||||||
{
|
|
||||||
uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
|
|
||||||
uint32_t compsize = hdr.disksize - hdr.dataoffs;
|
|
||||||
uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
|
|
||||||
uLongf destlen = uncompsize;
|
|
||||||
|
|
||||||
char *tempbuf = (char *)malloc(compsize);
|
|
||||||
void *uncompdata = malloc(uncompsize);
|
|
||||||
void *sectheader = malloc(sectsize);
|
|
||||||
|
|
||||||
fread(sectheader, sectsize, 1, fp);
|
|
||||||
fread(tempbuf, compsize, 1, fp);
|
|
||||||
|
|
||||||
z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
|
|
||||||
free(tempbuf);
|
|
||||||
if (z_result != Z_OK)
|
|
||||||
{
|
|
||||||
free(sectheader);
|
|
||||||
free(uncompdata);
|
|
||||||
error = SP_ERROR_DECOMPRESSOR;
|
|
||||||
goto return_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
base = (uint8_t *)malloc(hdr.imagesize);
|
|
||||||
memcpy(base, &hdr, sizeof(sp_file_hdr_t));
|
|
||||||
memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
|
|
||||||
free(sectheader);
|
|
||||||
memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
|
|
||||||
free(uncompdata);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SPFILE_COMPRESSION_NONE:
|
|
||||||
{
|
|
||||||
base = (uint8_t *)malloc(hdr.imagesize);
|
|
||||||
rewind(fp);
|
|
||||||
fread(base, hdr.imagesize, 1, fp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
error = SP_ERROR_DECOMPRESSOR;
|
|
||||||
goto return_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin = (sp_plugin_t *)malloc(sizeof(sp_plugin_t));
|
|
||||||
if (!_ReadPlugin(&hdr, base, plugin, err))
|
|
||||||
{
|
|
||||||
free(plugin);
|
|
||||||
free(base);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin->allocflags = 0;
|
|
||||||
|
|
||||||
return plugin;
|
|
||||||
|
|
||||||
return_error:
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
*err = error;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp_plugin_t *SourcePawnEngine::LoadFromMemory(void *base, sp_plugin_t *plugin, int *err)
|
sp_plugin_t *SourcePawnEngine::LoadFromMemory(void *base, sp_plugin_t *plugin, int *err)
|
||||||
{
|
{
|
||||||
sp_file_hdr_t hdr;
|
if (err != NULL)
|
||||||
uint8_t noptr = 0;
|
|
||||||
|
|
||||||
memcpy(&hdr, base, sizeof(sp_file_hdr_t));
|
|
||||||
|
|
||||||
if (!plugin)
|
|
||||||
{
|
{
|
||||||
plugin = (sp_plugin_t *)malloc(sizeof(sp_plugin_t));
|
*err = SP_ERROR_ABORTED;
|
||||||
noptr = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_ReadPlugin(&hdr, (uint8_t *)base, plugin, err))
|
return NULL;
|
||||||
{
|
|
||||||
if (noptr)
|
|
||||||
{
|
|
||||||
free(plugin);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!noptr)
|
|
||||||
{
|
|
||||||
plugin->allocflags |= SP_FA_SELF_EXTERNAL;
|
|
||||||
}
|
|
||||||
plugin->allocflags |= SP_FA_BASE_EXTERNAL;
|
|
||||||
|
|
||||||
return plugin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
|
int SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
|
||||||
{
|
{
|
||||||
if (!(plugin->allocflags & SP_FA_BASE_EXTERNAL))
|
return SP_ERROR_ABORTED;
|
||||||
{
|
|
||||||
free(plugin->base);
|
|
||||||
plugin->base = NULL;
|
|
||||||
}
|
|
||||||
if (!(plugin->allocflags & SP_FA_SELF_EXTERNAL))
|
|
||||||
{
|
|
||||||
free(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SP_ERROR_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void SourcePawnEngine::ReleaseFunctionToPool(CFunction *func)
|
|
||||||
{
|
|
||||||
if (!func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
func->Cancel();
|
|
||||||
func->m_pNext = m_pFreeFuncs;
|
|
||||||
m_pFreeFuncs = func;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFunction *SourcePawnEngine::GetFunctionFromPool(funcid_t f, IPluginContext *plugin)
|
|
||||||
{
|
|
||||||
if (!m_pFreeFuncs)
|
|
||||||
{
|
|
||||||
return new CFunction(f, plugin);
|
|
||||||
} else {
|
|
||||||
CFunction *pFunc = m_pFreeFuncs;
|
|
||||||
m_pFreeFuncs = m_pFreeFuncs->m_pNext;
|
|
||||||
pFunc->Set(f, plugin);
|
|
||||||
return pFunc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IDebugListener *SourcePawnEngine::SetDebugListener(IDebugListener *pListener)
|
IDebugListener *SourcePawnEngine::SetDebugListener(IDebugListener *pListener)
|
||||||
{
|
{
|
||||||
IDebugListener *old = m_pDebugHook;
|
IDebugListener *old = m_pDebugHook;
|
||||||
@ -529,7 +281,7 @@ void SourcePawnEngine::FreeTracedCall(TracedCall *pCall)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourcePawnEngine::PushTracer(sp_context_t *ctx)
|
void SourcePawnEngine::PushTracer(BaseContext *ctx)
|
||||||
{
|
{
|
||||||
TracedCall *pCall = MakeTracedCall(true);
|
TracedCall *pCall = MakeTracedCall(true);
|
||||||
|
|
||||||
@ -538,7 +290,7 @@ void SourcePawnEngine::PushTracer(sp_context_t *ctx)
|
|||||||
pCall->frm = INVALID_CIP;
|
pCall->frm = INVALID_CIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourcePawnEngine::RunTracer(sp_context_t *ctx, uint32_t frame, uint32_t codeip)
|
void SourcePawnEngine::RunTracer(BaseContext *ctx, uint32_t frame, uint32_t codeip)
|
||||||
{
|
{
|
||||||
assert(m_CallStack != NULL);
|
assert(m_CallStack != NULL);
|
||||||
assert(m_CallStack->ctx == ctx);
|
assert(m_CallStack->ctx == ctx);
|
||||||
@ -577,13 +329,13 @@ void SourcePawnEngine::PopTracer(int error, const char *msg)
|
|||||||
{
|
{
|
||||||
uint32_t native = INVALID_CIP;
|
uint32_t native = INVALID_CIP;
|
||||||
|
|
||||||
if (m_CallStack->ctx->n_err)
|
if (m_CallStack->ctx->GetCtx()->n_err)
|
||||||
{
|
{
|
||||||
native = m_CallStack->ctx->n_idx;
|
native = m_CallStack->ctx->GetCtx()->n_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
CContextTrace trace(m_CallStack, error, msg, native);
|
CContextTrace trace(m_CallStack, error, msg, native);
|
||||||
m_pDebugHook->OnContextExecuteError(m_CallStack->ctx->context, &trace);
|
m_pDebugHook->OnContextExecuteError(m_CallStack->ctx, &trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now pop the error chain */
|
/* Now pop the error chain */
|
||||||
@ -607,7 +359,7 @@ CContextTrace::CContextTrace(TracedCall *pStart, int error, const char *msg, uin
|
|||||||
|
|
||||||
bool CContextTrace::DebugInfoAvailable()
|
bool CContextTrace::DebugInfoAvailable()
|
||||||
{
|
{
|
||||||
return ((m_pStart->ctx->flags & SP_FLAG_DEBUG) == SP_FLAG_DEBUG);
|
return m_pStart->ctx->IsDebugging();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CContextTrace::GetCustomErrorString()
|
const char *CContextTrace::GetCustomErrorString()
|
||||||
@ -648,7 +400,7 @@ bool CContextTrace::GetTraceInfo(CallStackInfo *trace)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPluginContext *pContext = m_pIterator->ctx->context;
|
IPluginContext *pContext = m_pIterator->ctx;
|
||||||
IPluginDebugInfo *pInfo = pContext->GetDebugInfo();
|
IPluginDebugInfo *pInfo = pContext->GetDebugInfo();
|
||||||
|
|
||||||
if (!pInfo)
|
if (!pInfo)
|
||||||
@ -690,7 +442,7 @@ const char *CContextTrace::GetLastNative(uint32_t *index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sp_native_t *native;
|
sp_native_t *native;
|
||||||
if (m_pIterator->ctx->context->GetNativeByIndex(m_Native, &native) != SP_ERROR_NONE)
|
if (m_pIterator->ctx->GetNativeByIndex(m_Native, &native) != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
@ -35,11 +35,13 @@
|
|||||||
#include "sp_vm_api.h"
|
#include "sp_vm_api.h"
|
||||||
#include "sp_vm_function.h"
|
#include "sp_vm_function.h"
|
||||||
|
|
||||||
|
class BaseContext;
|
||||||
|
|
||||||
struct TracedCall
|
struct TracedCall
|
||||||
{
|
{
|
||||||
uint32_t cip;
|
uint32_t cip;
|
||||||
uint32_t frm;
|
uint32_t frm;
|
||||||
sp_context_t *ctx;
|
BaseContext *ctx;
|
||||||
TracedCall *next;
|
TracedCall *next;
|
||||||
unsigned int chain;
|
unsigned int chain;
|
||||||
};
|
};
|
||||||
@ -73,8 +75,6 @@ public: //ISourcePawnEngine
|
|||||||
sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err);
|
sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err);
|
||||||
sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err);
|
sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err);
|
||||||
int FreeFromMemory(sp_plugin_t *plugin);
|
int FreeFromMemory(sp_plugin_t *plugin);
|
||||||
IPluginContext *CreateBaseContext(sp_context_t *ctx);
|
|
||||||
void FreeBaseContext(IPluginContext *ctx);
|
|
||||||
void *BaseAlloc(size_t size);
|
void *BaseAlloc(size_t size);
|
||||||
void BaseFree(void *memory);
|
void BaseFree(void *memory);
|
||||||
void *ExecAlloc(size_t size);
|
void *ExecAlloc(size_t size);
|
||||||
@ -86,13 +86,14 @@ public: //ISourcePawnEngine
|
|||||||
void SetReadWrite(void *ptr);
|
void SetReadWrite(void *ptr);
|
||||||
void SetReadExecute(void *ptr);
|
void SetReadExecute(void *ptr);
|
||||||
void FreePageMemory(void *ptr);
|
void FreePageMemory(void *ptr);
|
||||||
|
const char *GetErrorString(int err);
|
||||||
public: //Debugger Stuff
|
public: //Debugger Stuff
|
||||||
/**
|
/**
|
||||||
* @brief Pushes a context onto the top of the call tracer.
|
* @brief Pushes a context onto the top of the call tracer.
|
||||||
*
|
*
|
||||||
* @param ctx Plugin context.
|
* @param ctx Plugin context.
|
||||||
*/
|
*/
|
||||||
void PushTracer(sp_context_t *ctx);
|
void PushTracer(BaseContext *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pops a plugin off the call tracer.
|
* @brief Pops a plugin off the call tracer.
|
||||||
@ -102,7 +103,7 @@ public: //Debugger Stuff
|
|||||||
/**
|
/**
|
||||||
* @brief Runs tracer from a debug break.
|
* @brief Runs tracer from a debug break.
|
||||||
*/
|
*/
|
||||||
void RunTracer(sp_context_t *ctx, uint32_t frame, uint32_t codeip);
|
void RunTracer(BaseContext *ctx, uint32_t frame, uint32_t codeip);
|
||||||
public: //Plugin function stuff
|
public: //Plugin function stuff
|
||||||
CFunction *GetFunctionFromPool(funcid_t f, IPluginContext *plugin);
|
CFunction *GetFunctionFromPool(funcid_t f, IPluginContext *plugin);
|
||||||
void ReleaseFunctionToPool(CFunction *func);
|
void ReleaseFunctionToPool(CFunction *func);
|
||||||
@ -117,4 +118,6 @@ private:
|
|||||||
//CFunction *m_pFreeFuncs;
|
//CFunction *m_pFreeFuncs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern SourcePawnEngine g_engine1;
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEPAWN_VM_ENGINE_H_
|
#endif //_INCLUDE_SOURCEPAWN_VM_ENGINE_H_
|
@ -32,76 +32,47 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "sp_vm_function.h"
|
#include "sp_vm_function.h"
|
||||||
#include "sm_stringutil.h"
|
#include "BaseRuntime.h"
|
||||||
|
|
||||||
/********************
|
/********************
|
||||||
* FUNCTION CALLING *
|
* FUNCTION CALLING *
|
||||||
********************/
|
********************/
|
||||||
|
|
||||||
void CFunction::Set(uint32_t code_addr, IPluginContext *plugin, funcid_t id, uint32_t pub_id)
|
void CFunction::Set(uint32_t code_addr, BaseRuntime *runtime, funcid_t fnid, uint32_t pub_id)
|
||||||
{
|
{
|
||||||
m_codeaddr = code_addr;
|
m_codeaddr = code_addr;
|
||||||
m_pContext = plugin;
|
m_pRuntime = runtime;
|
||||||
m_curparam = 0;
|
m_curparam = 0;
|
||||||
m_errorstate = SP_ERROR_NONE;
|
m_errorstate = SP_ERROR_NONE;
|
||||||
m_Invalid = false;
|
m_Invalid = false;
|
||||||
m_pCtx = plugin ? plugin->GetContext() : NULL;
|
m_FnId = fnid;
|
||||||
m_FnId = id;
|
|
||||||
|
|
||||||
m_pContext->GetPublicByIndex(pub_id, &m_pPublic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFunction::IsRunnable()
|
bool CFunction::IsRunnable()
|
||||||
{
|
{
|
||||||
return ((m_pCtx->flags & SPFLAG_PLUGIN_PAUSED) != SPFLAG_PLUGIN_PAUSED);
|
return !m_pRuntime->IsPaused();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
|
int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
|
||||||
{
|
{
|
||||||
int ir, serial;
|
return CallFunction2(m_pRuntime->GetDefaultContext(), params, num_params, result);
|
||||||
|
}
|
||||||
|
|
||||||
if (!IsRunnable())
|
int CFunction::CallFunction2(IPluginContext *pContext, const cell_t *params, unsigned int num_params, cell_t *result)
|
||||||
{
|
{
|
||||||
return SP_ERROR_NOT_RUNNABLE;
|
return pContext->Execute2(this, params, num_params, result);
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_pCtx->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS
|
|
||||||
&& m_pPublic != NULL)
|
|
||||||
{
|
|
||||||
serial = m_pCtx->profiler->OnCallbackBegin(m_pContext, m_pPublic);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (num_params--)
|
|
||||||
{
|
|
||||||
m_pContext->PushCell(params[num_params]);
|
|
||||||
}
|
|
||||||
|
|
||||||
ir = m_pContext->Execute(m_codeaddr, result);
|
|
||||||
|
|
||||||
if ((m_pCtx->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS
|
|
||||||
&& m_pPublic != NULL)
|
|
||||||
{
|
|
||||||
m_pCtx->profiler->OnCallbackEnd(serial);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPluginContext *CFunction::GetParentContext()
|
IPluginContext *CFunction::GetParentContext()
|
||||||
{
|
{
|
||||||
return m_pContext;
|
return m_pRuntime->GetDefaultContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
CFunction::CFunction(uint32_t code_addr, IPluginContext *plugin, funcid_t id, uint32_t pub_id) :
|
CFunction::CFunction(uint32_t code_addr, BaseRuntime *runtime, funcid_t id, uint32_t pub_id) :
|
||||||
m_codeaddr(code_addr), m_pContext(plugin), m_curparam(0),
|
m_codeaddr(code_addr), m_curparam(0), m_errorstate(SP_ERROR_NONE), m_FnId(id)
|
||||||
m_errorstate(SP_ERROR_NONE), m_FnId(id)
|
|
||||||
{
|
{
|
||||||
m_Invalid = false;
|
m_Invalid = false;
|
||||||
if (plugin)
|
m_pRuntime = runtime;
|
||||||
{
|
|
||||||
m_pCtx = plugin->GetContext();
|
|
||||||
}
|
|
||||||
m_pContext->GetPublicByIndex(pub_id, &m_pPublic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CFunction::PushCell(cell_t cell)
|
int CFunction::PushCell(cell_t cell)
|
||||||
@ -198,6 +169,11 @@ void CFunction::Cancel()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int CFunction::Execute(cell_t *result)
|
int CFunction::Execute(cell_t *result)
|
||||||
|
{
|
||||||
|
return Execute2(m_pRuntime->GetDefaultContext(), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CFunction::Execute2(IPluginContext *ctx, cell_t *result)
|
||||||
{
|
{
|
||||||
int err = SP_ERROR_NONE;
|
int err = SP_ERROR_NONE;
|
||||||
|
|
||||||
@ -236,9 +212,9 @@ int CFunction::Execute(cell_t *result)
|
|||||||
if (!temp_info[i].str.is_sz)
|
if (!temp_info[i].str.is_sz)
|
||||||
{
|
{
|
||||||
/* Allocate a normal/generic array */
|
/* Allocate a normal/generic array */
|
||||||
if ((err=m_pContext->HeapAlloc(temp_info[i].size,
|
if ((err=ctx->HeapAlloc(temp_info[i].size,
|
||||||
&(temp_info[i].local_addr),
|
&(temp_info[i].local_addr),
|
||||||
&(temp_info[i].phys_addr)))
|
&(temp_info[i].phys_addr)))
|
||||||
!= SP_ERROR_NONE)
|
!= SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@ -254,9 +230,9 @@ int CFunction::Execute(cell_t *result)
|
|||||||
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
|
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
|
||||||
|
|
||||||
/* Allocate the buffer */
|
/* Allocate the buffer */
|
||||||
if ((err=m_pContext->HeapAlloc(cells,
|
if ((err=ctx->HeapAlloc(cells,
|
||||||
&(temp_info[i].local_addr),
|
&(temp_info[i].local_addr),
|
||||||
&(temp_info[i].phys_addr)))
|
&(temp_info[i].phys_addr)))
|
||||||
!= SP_ERROR_NONE)
|
!= SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@ -267,10 +243,10 @@ int CFunction::Execute(cell_t *result)
|
|||||||
/* Cut off UTF-8 properly */
|
/* Cut off UTF-8 properly */
|
||||||
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
|
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
|
||||||
{
|
{
|
||||||
if ((err=m_pContext->StringToLocalUTF8(temp_info[i].local_addr,
|
if ((err=ctx->StringToLocalUTF8(temp_info[i].local_addr,
|
||||||
temp_info[i].size,
|
temp_info[i].size,
|
||||||
(const char *)temp_info[i].orig_addr,
|
(const char *)temp_info[i].orig_addr,
|
||||||
NULL))
|
NULL))
|
||||||
!= SP_ERROR_NONE)
|
!= SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@ -284,9 +260,9 @@ int CFunction::Execute(cell_t *result)
|
|||||||
/* Copy ASCII characters */
|
/* Copy ASCII characters */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((err=m_pContext->StringToLocal(temp_info[i].local_addr,
|
if ((err=ctx->StringToLocal(temp_info[i].local_addr,
|
||||||
temp_info[i].size,
|
temp_info[i].size,
|
||||||
(const char *)temp_info[i].orig_addr))
|
(const char *)temp_info[i].orig_addr))
|
||||||
!= SP_ERROR_NONE)
|
!= SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@ -307,7 +283,7 @@ int CFunction::Execute(cell_t *result)
|
|||||||
/* Make the call if we can */
|
/* Make the call if we can */
|
||||||
if (err == SP_ERROR_NONE)
|
if (err == SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
if ((err = CallFunction(temp_params, numparams, result)) != SP_ERROR_NONE)
|
if ((err = CallFunction2(ctx, temp_params, numparams, result)) != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
docopies = false;
|
docopies = false;
|
||||||
}
|
}
|
||||||
@ -350,7 +326,7 @@ int CFunction::Execute(cell_t *result)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err=m_pContext->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
|
if ((err=ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -364,3 +340,16 @@ funcid_t CFunction::GetFunctionID()
|
|||||||
return m_FnId;
|
return m_FnId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CFunction::SetError(int err)
|
||||||
|
{
|
||||||
|
m_errorstate = err;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFunction::IsInvalidated()
|
||||||
|
{
|
||||||
|
return m_Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -32,7 +32,11 @@
|
|||||||
#ifndef _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
|
#ifndef _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
|
||||||
#define _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
|
#define _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
|
||||||
|
|
||||||
#include "sm_globals.h"
|
#include <sp_vm_api.h>
|
||||||
|
|
||||||
|
class BaseRuntime;
|
||||||
|
|
||||||
|
using namespace SourcePawn;
|
||||||
|
|
||||||
struct ParamInfo
|
struct ParamInfo
|
||||||
{
|
{
|
||||||
@ -56,7 +60,7 @@ class CFunction : public IPluginFunction
|
|||||||
friend class SourcePawnEngine;
|
friend class SourcePawnEngine;
|
||||||
public:
|
public:
|
||||||
CFunction(uint32_t code_addr,
|
CFunction(uint32_t code_addr,
|
||||||
IPluginContext *pContext,
|
BaseRuntime *pRuntime,
|
||||||
funcid_t fnid,
|
funcid_t fnid,
|
||||||
uint32_t pub_id);
|
uint32_t pub_id);
|
||||||
public:
|
public:
|
||||||
@ -71,29 +75,23 @@ public:
|
|||||||
virtual void Cancel();
|
virtual void Cancel();
|
||||||
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
|
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
|
||||||
virtual IPluginContext *GetParentContext();
|
virtual IPluginContext *GetParentContext();
|
||||||
inline bool IsInvalidated()
|
bool IsInvalidated();
|
||||||
{
|
void Invalidate();
|
||||||
return m_Invalid;
|
|
||||||
}
|
|
||||||
inline void Invalidate()
|
|
||||||
{
|
|
||||||
m_Invalid = true;
|
|
||||||
}
|
|
||||||
bool IsRunnable();
|
bool IsRunnable();
|
||||||
funcid_t GetFunctionID();
|
funcid_t GetFunctionID();
|
||||||
|
int Execute2(IPluginContext *ctx, cell_t *result);
|
||||||
|
int CallFunction2(IPluginContext *ctx,
|
||||||
|
const cell_t *params,
|
||||||
|
unsigned int num_params,
|
||||||
|
cell_t *result);
|
||||||
public:
|
public:
|
||||||
void Set(uint32_t code_addr, IPluginContext *plugin, funcid_t fnid, uint32_t pub_id);
|
void Set(uint32_t code_addr, BaseRuntime *runtime, funcid_t fnid, uint32_t pub_id);
|
||||||
private:
|
private:
|
||||||
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
|
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
|
||||||
inline int SetError(int err)
|
int SetError(int err);
|
||||||
{
|
|
||||||
m_errorstate = err;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
uint32_t m_codeaddr;
|
uint32_t m_codeaddr;
|
||||||
IPluginContext *m_pContext;
|
BaseRuntime *m_pRuntime;
|
||||||
sp_context_t *m_pCtx;
|
|
||||||
cell_t m_params[SP_MAX_EXEC_PARAMS];
|
cell_t m_params[SP_MAX_EXEC_PARAMS];
|
||||||
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
|
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
|
||||||
unsigned int m_curparam;
|
unsigned int m_curparam;
|
||||||
@ -101,7 +99,6 @@ private:
|
|||||||
CFunction *m_pNext;
|
CFunction *m_pNext;
|
||||||
bool m_Invalid;
|
bool m_Invalid;
|
||||||
funcid_t m_FnId;
|
funcid_t m_FnId;
|
||||||
sp_public_t *m_pPublic;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_
|
#endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_
|
@ -35,12 +35,24 @@
|
|||||||
#include "jit_x86.h"
|
#include "jit_x86.h"
|
||||||
#include "opcode_helpers.h"
|
#include "opcode_helpers.h"
|
||||||
#include <x86_macros.h>
|
#include <x86_macros.h>
|
||||||
#include "jit_version.h"
|
#include "../jit_version.h"
|
||||||
|
#include "../sp_vm_engine.h"
|
||||||
|
#include "../engine2.h"
|
||||||
|
#include "../BaseRuntime.h"
|
||||||
|
#include "../sp_vm_basecontext.h"
|
||||||
|
|
||||||
#if defined USE_UNGEN_OPCODES
|
#if defined USE_UNGEN_OPCODES
|
||||||
#include "ungen_opcodes.h"
|
#include "ungen_opcodes.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
JITX86 g_Jit1;
|
||||||
|
ISourcePawnEngine *engine = &g_engine1;
|
||||||
|
|
||||||
|
inline sp_plugin_t *GETPLUGIN(sp_context_t *ctx)
|
||||||
|
{
|
||||||
|
return (sp_plugin_t *)(ctx->vm[JITVARS_PLUGIN]);
|
||||||
|
}
|
||||||
|
|
||||||
inline void WriteOp_Move_Pri(JitWriter *jit)
|
inline void WriteOp_Move_Pri(JitWriter *jit)
|
||||||
{
|
{
|
||||||
//mov eax, edx
|
//mov eax, edx
|
||||||
@ -1318,12 +1330,12 @@ inline void WriteOp_Retn(JitWriter *jit)
|
|||||||
|
|
||||||
void ProfCallGate_Begin(sp_context_t *ctx, const char *name)
|
void ProfCallGate_Begin(sp_context_t *ctx, const char *name)
|
||||||
{
|
{
|
||||||
ctx->profiler->OnFunctionBegin(ctx->context, name);
|
((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionBegin((IPluginContext *)ctx->vm[JITVARS_BASECTX], name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfCallGate_End(sp_context_t *ctx)
|
void ProfCallGate_End(sp_context_t *ctx)
|
||||||
{
|
{
|
||||||
ctx->profiler->OnFunctionEnd();
|
((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
|
const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
|
||||||
@ -2264,8 +2276,11 @@ inline void WriteOp_FloatCompare(JitWriter *jit)
|
|||||||
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
|
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
|
||||||
{
|
{
|
||||||
sp_native_t *native;
|
sp_native_t *native;
|
||||||
|
sp_plugin_t *plugin;
|
||||||
|
|
||||||
|
plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
|
||||||
|
|
||||||
native = &ctx->natives[native_idx];
|
native = &plugin->natives[native_idx];
|
||||||
|
|
||||||
ctx->n_idx = native_idx;
|
ctx->n_idx = native_idx;
|
||||||
|
|
||||||
@ -2276,15 +2291,18 @@ cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return native->pfn(ctx->context, params);
|
return native->pfn(GET_CONTEXT(ctx), params);
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
|
cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
|
||||||
{
|
{
|
||||||
cell_t val;
|
cell_t val;
|
||||||
sp_native_t *native;
|
sp_native_t *native;
|
||||||
|
sp_plugin_t *plugin;
|
||||||
|
|
||||||
native = &ctx->natives[native_idx];
|
plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
|
||||||
|
|
||||||
|
native = &plugin->natives[native_idx];
|
||||||
|
|
||||||
ctx->n_idx = native_idx;
|
ctx->n_idx = native_idx;
|
||||||
|
|
||||||
@ -2295,9 +2313,9 @@ cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *par
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->profiler->OnNativeBegin(ctx->context, native);
|
plugin->profiler->OnNativeBegin(GET_CONTEXT(ctx), native);
|
||||||
val = native->pfn(ctx->context, params);
|
val = native->pfn(GET_CONTEXT(ctx), params);
|
||||||
ctx->profiler->OnNativeEnd();
|
plugin->profiler->OnNativeEnd();
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@ -2307,9 +2325,11 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param
|
|||||||
cell_t save_sp = ctx->sp;
|
cell_t save_sp = ctx->sp;
|
||||||
cell_t save_hp = ctx->hp;
|
cell_t save_hp = ctx->hp;
|
||||||
|
|
||||||
|
sp_plugin_t *pl = GETPLUGIN(ctx);
|
||||||
|
|
||||||
ctx->n_idx = native_idx;
|
ctx->n_idx = native_idx;
|
||||||
|
|
||||||
if (ctx->hp < ctx->heap_base)
|
if (ctx->hp < (cell_t)pl->data_size)
|
||||||
{
|
{
|
||||||
ctx->n_err = SP_ERROR_HEAPMIN;
|
ctx->n_err = SP_ERROR_HEAPMIN;
|
||||||
return 0;
|
return 0;
|
||||||
@ -2321,7 +2341,7 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((uint32_t)ctx->sp >= ctx->mem_size)
|
if ((uint32_t)ctx->sp >= pl->mem_size)
|
||||||
{
|
{
|
||||||
ctx->n_err = SP_ERROR_STACKMIN;
|
ctx->n_err = SP_ERROR_STACKMIN;
|
||||||
return 0;
|
return 0;
|
||||||
@ -2353,9 +2373,11 @@ cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_
|
|||||||
cell_t save_sp = ctx->sp;
|
cell_t save_sp = ctx->sp;
|
||||||
cell_t save_hp = ctx->hp;
|
cell_t save_hp = ctx->hp;
|
||||||
|
|
||||||
|
sp_plugin_t *pl = GETPLUGIN(ctx);
|
||||||
|
|
||||||
ctx->n_idx = native_idx;
|
ctx->n_idx = native_idx;
|
||||||
|
|
||||||
if (ctx->hp < ctx->heap_base)
|
if (ctx->hp < (cell_t)pl->data_size)
|
||||||
{
|
{
|
||||||
ctx->n_err = SP_ERROR_HEAPMIN;
|
ctx->n_err = SP_ERROR_HEAPMIN;
|
||||||
return 0;
|
return 0;
|
||||||
@ -2367,7 +2389,7 @@ cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((uint32_t)ctx->sp >= ctx->mem_size)
|
if ((uint32_t)ctx->sp >= pl->mem_size)
|
||||||
{
|
{
|
||||||
ctx->n_err = SP_ERROR_STACKMIN;
|
ctx->n_err = SP_ERROR_STACKMIN;
|
||||||
return 0;
|
return 0;
|
||||||
@ -2396,10 +2418,7 @@ cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_
|
|||||||
|
|
||||||
static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
|
static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
|
||||||
{
|
{
|
||||||
sp_context_t *ctx = pCtx->GetContext();
|
return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
|
||||||
ctx->n_err = SP_ERROR_INVALID_NATIVE;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
|
jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
|
||||||
@ -2457,11 +2476,27 @@ void WriteErrorRoutines(CompData *data, JitWriter *jit)
|
|||||||
Write_GetError(jit);
|
Write_GetError(jit);
|
||||||
}
|
}
|
||||||
|
|
||||||
sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err)
|
bool JITX86::Compile(ICompilation *co, BaseRuntime *prt, int *err)
|
||||||
{
|
{
|
||||||
CompData *data = (CompData *)co;
|
CompData *data = (CompData *)co;
|
||||||
sp_plugin_t *plugin = data->plugin;
|
sp_plugin_t *plugin = data->plugin;
|
||||||
|
|
||||||
|
if (data->plugin == NULL)
|
||||||
|
{
|
||||||
|
if (data->debug && !(prt->m_pPlugin->flags & SP_FLAG_DEBUG))
|
||||||
|
{
|
||||||
|
if (err != NULL)
|
||||||
|
{
|
||||||
|
*err = SP_ERROR_NOTDEBUGGING;
|
||||||
|
}
|
||||||
|
co->Abort();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->SetRuntime(prt);
|
||||||
|
plugin = data->plugin;
|
||||||
|
}
|
||||||
|
|
||||||
/* The first phase is to browse */
|
/* The first phase is to browse */
|
||||||
uint8_t *code = plugin->pcode;
|
uint8_t *code = plugin->pcode;
|
||||||
uint8_t *end_cip = plugin->pcode + plugin->pcode_size;
|
uint8_t *end_cip = plugin->pcode + plugin->pcode_size;
|
||||||
@ -2584,8 +2619,8 @@ jit_rewind:
|
|||||||
if (data->error_set != SP_ERROR_NONE)
|
if (data->error_set != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
*err = data->error_set;
|
*err = data->error_set;
|
||||||
AbortCompilation(co);
|
co->Abort();
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Write these last because error jumps should be unpredicted, and thus forward */
|
/* Write these last because error jumps should be unpredicted, and thus forward */
|
||||||
@ -2627,23 +2662,29 @@ jit_rewind:
|
|||||||
* FOURTH PASS - Context Setup
|
* FOURTH PASS - Context Setup
|
||||||
*************/
|
*************/
|
||||||
|
|
||||||
sp_context_t *ctx = new sp_context_t;
|
|
||||||
memset(ctx, 0, sizeof(sp_context_t));
|
|
||||||
|
|
||||||
/* setup basics */
|
/* setup basics */
|
||||||
ctx->codebase = writer.outbase;
|
sp_context_t *ctx = data->runtime->GetBaseContext()->GetCtx();
|
||||||
ctx->plugin = plugin;
|
|
||||||
ctx->vmbase = this;
|
/* Clear out any old cruft */
|
||||||
ctx->flags = (data->debug ? SPFLAG_PLUGIN_DEBUG : 0);
|
if (plugin->codebase != NULL)
|
||||||
|
{
|
||||||
|
FreePluginVars(data->runtime->m_pPlugin);
|
||||||
|
FreeContextVars(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin->codebase = writer.outbase;
|
||||||
|
plugin->jit_codesize = codemem;
|
||||||
|
plugin->jit_memsize = 0;
|
||||||
|
|
||||||
/* setup memory */
|
/* setup memory */
|
||||||
ctx->memory = new uint8_t[plugin->memory];
|
|
||||||
memcpy(ctx->memory, plugin->data, plugin->data_size);
|
ctx->hp = plugin->data_size;
|
||||||
ctx->mem_size = plugin->memory;
|
ctx->sp = plugin->mem_size - sizeof(cell_t);
|
||||||
ctx->heap_base = plugin->data_size;
|
ctx->frm = ctx->sp;
|
||||||
ctx->hp = ctx->heap_base;
|
ctx->n_err = SP_ERROR_NONE;
|
||||||
ctx->sp = ctx->mem_size - sizeof(cell_t);
|
ctx->n_idx = SP_ERROR_NONE;
|
||||||
ctx->prof_flags = data->profile;
|
plugin->prof_flags = data->profile;
|
||||||
|
plugin->flags = data->debug ? SPFLAG_PLUGIN_DEBUG : 0;
|
||||||
|
|
||||||
const char *strbase = plugin->info.stringbase;
|
const char *strbase = plugin->info.stringbase;
|
||||||
uint32_t max, iter;
|
uint32_t max, iter;
|
||||||
@ -2651,39 +2692,42 @@ jit_rewind:
|
|||||||
/* relocate public info */
|
/* relocate public info */
|
||||||
if ((max = plugin->info.publics_num))
|
if ((max = plugin->info.publics_num))
|
||||||
{
|
{
|
||||||
ctx->publics = new sp_public_t[max];
|
plugin->publics = new sp_public_t[max];
|
||||||
|
plugin->jit_memsize += sizeof(sp_public_t) * max;
|
||||||
for (iter=0; iter<max; iter++)
|
for (iter=0; iter<max; iter++)
|
||||||
{
|
{
|
||||||
ctx->publics[iter].name = strbase + plugin->info.publics[iter].name;
|
plugin->publics[iter].name = strbase + plugin->info.publics[iter].name;
|
||||||
ctx->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false);
|
plugin->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false);
|
||||||
/* Encode the ID as a straight code offset */
|
/* Encode the ID as a straight code offset */
|
||||||
ctx->publics[iter].funcid = (ctx->publics[iter].code_offs << 1);
|
plugin->publics[iter].funcid = (plugin->publics[iter].code_offs << 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* relocate pubvar info */
|
/* relocate pubvar info */
|
||||||
if ((max = plugin->info.pubvars_num))
|
if ((max = plugin->info.pubvars_num))
|
||||||
{
|
{
|
||||||
uint8_t *dat = ctx->memory;
|
uint8_t *dat = plugin->memory;
|
||||||
ctx->pubvars = new sp_pubvar_t[max];
|
plugin->pubvars = new sp_pubvar_t[max];
|
||||||
|
plugin->jit_memsize += sizeof(sp_pubvar_t) * max;
|
||||||
for (iter=0; iter<max; iter++)
|
for (iter=0; iter<max; iter++)
|
||||||
{
|
{
|
||||||
ctx->pubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
|
plugin->pubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
|
||||||
ctx->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
|
plugin->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* relocate native info */
|
/* relocate native info */
|
||||||
if ((max = plugin->info.natives_num))
|
if ((max = plugin->info.natives_num))
|
||||||
{
|
{
|
||||||
ctx->natives = new sp_native_t[max];
|
plugin->natives = new sp_native_t[max];
|
||||||
|
plugin->jit_memsize += sizeof(sp_native_t) * max;
|
||||||
for (iter=0; iter<max; iter++)
|
for (iter=0; iter<max; iter++)
|
||||||
{
|
{
|
||||||
ctx->natives[iter].name = strbase + plugin->info.natives[iter].name;
|
plugin->natives[iter].name = strbase + plugin->info.natives[iter].name;
|
||||||
ctx->natives[iter].pfn = &InvalidNative;
|
plugin->natives[iter].pfn = &InvalidNative;
|
||||||
ctx->natives[iter].status = SP_NATIVE_UNBOUND;
|
plugin->natives[iter].status = SP_NATIVE_UNBOUND;
|
||||||
ctx->natives[iter].flags = 0;
|
plugin->natives[iter].flags = 0;
|
||||||
ctx->natives[iter].user = NULL;
|
plugin->natives[iter].user = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2696,20 +2740,22 @@ jit_rewind:
|
|||||||
|
|
||||||
/* relocate files */
|
/* relocate files */
|
||||||
max = plugin->debug.files_num;
|
max = plugin->debug.files_num;
|
||||||
ctx->files = new sp_debug_file_t[max];
|
plugin->files = new sp_debug_file_t[max];
|
||||||
|
plugin->jit_memsize += sizeof(sp_debug_file_t) * max;
|
||||||
for (iter=0; iter<max; iter++)
|
for (iter=0; iter<max; iter++)
|
||||||
{
|
{
|
||||||
ctx->files[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
|
plugin->files[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
|
||||||
ctx->files[iter].name = strbase + plugin->debug.files[iter].name;
|
plugin->files[iter].name = strbase + plugin->debug.files[iter].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* relocate lines */
|
/* relocate lines */
|
||||||
max = plugin->debug.lines_num;
|
max = plugin->debug.lines_num;
|
||||||
ctx->lines = new sp_debug_line_t[max];
|
plugin->lines = new sp_debug_line_t[max];
|
||||||
|
plugin->jit_memsize += sizeof(sp_debug_line_t) * max;
|
||||||
for (iter=0; iter<max; iter++)
|
for (iter=0; iter<max; iter++)
|
||||||
{
|
{
|
||||||
ctx->lines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
|
plugin->lines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
|
||||||
ctx->lines[iter].line = plugin->debug.lines[iter].line;
|
plugin->lines[iter].line = plugin->debug.lines[iter].line;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* relocate arrays */
|
/* relocate arrays */
|
||||||
@ -2718,7 +2764,8 @@ jit_rewind:
|
|||||||
uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
|
uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
|
||||||
|
|
||||||
max = plugin->debug.syms_num;
|
max = plugin->debug.syms_num;
|
||||||
ctx->symbols = new sp_debug_symbol_t[max];
|
plugin->symbols = new sp_debug_symbol_t[max];
|
||||||
|
plugin->jit_memsize += sizeof(sp_debug_symbol_t) * max;
|
||||||
for (iter=0; iter<max; iter++)
|
for (iter=0; iter<max; iter++)
|
||||||
{
|
{
|
||||||
sym = (sp_fdbg_symbol_t *)cursor;
|
sym = (sp_fdbg_symbol_t *)cursor;
|
||||||
@ -2730,52 +2777,50 @@ jit_rewind:
|
|||||||
*/
|
*/
|
||||||
if (sym->codestart > data->codesize)
|
if (sym->codestart > data->codesize)
|
||||||
{
|
{
|
||||||
ctx->symbols[iter].codestart = 0;
|
plugin->symbols[iter].codestart = 0;
|
||||||
} else {
|
} else {
|
||||||
ctx->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
|
plugin->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
|
||||||
}
|
}
|
||||||
if (sym->codeend > data->codesize)
|
if (sym->codeend > data->codesize)
|
||||||
{
|
{
|
||||||
ctx->symbols[iter].codeend = data->codesize;
|
plugin->symbols[iter].codeend = data->codesize;
|
||||||
} else {
|
} else {
|
||||||
ctx->symbols[iter].codeend = RelocLookup(jit, sym->codeend, false);
|
plugin->symbols[iter].codeend = RelocLookup(jit, sym->codeend, false);
|
||||||
}
|
}
|
||||||
ctx->symbols[iter].name = strbase + sym->name;
|
plugin->symbols[iter].name = strbase + sym->name;
|
||||||
ctx->symbols[iter].sym = sym;
|
plugin->symbols[iter].sym = sym;
|
||||||
|
|
||||||
if (sym->dimcount > 0)
|
if (sym->dimcount > 0)
|
||||||
{
|
{
|
||||||
cursor += sizeof(sp_fdbg_symbol_t);
|
cursor += sizeof(sp_fdbg_symbol_t);
|
||||||
arr = (sp_fdbg_arraydim_t *)cursor;
|
arr = (sp_fdbg_arraydim_t *)cursor;
|
||||||
ctx->symbols[iter].dims = arr;
|
plugin->symbols[iter].dims = arr;
|
||||||
cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
|
cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->symbols[iter].dims = NULL;
|
plugin->symbols[iter].dims = NULL;
|
||||||
cursor += sizeof(sp_fdbg_symbol_t);
|
cursor += sizeof(sp_fdbg_symbol_t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tracker_t *trk = new tracker_t;
|
tracker_t *trk = new tracker_t;
|
||||||
ctx->vm[JITVARS_TRACKER] = trk;
|
ctx->vm[JITVARS_TRACKER] = trk;
|
||||||
|
ctx->vm[JITVARS_BASECTX] = data->runtime->GetDefaultContext();
|
||||||
|
ctx->vm[JITVARS_PROFILER] = g_engine2.GetProfiler();
|
||||||
|
ctx->vm[JITVARS_PLUGIN] = data->runtime->m_pPlugin;
|
||||||
trk->pBase = (ucell_t *)malloc(1024);
|
trk->pBase = (ucell_t *)malloc(1024);
|
||||||
trk->pCur = trk->pBase;
|
trk->pCur = trk->pBase;
|
||||||
trk->size = 1024 / sizeof(cell_t);
|
trk->size = 1024 / sizeof(cell_t);
|
||||||
|
|
||||||
functracker_t *fnc = new functracker_t;
|
plugin->jit_memsize += trk->size;
|
||||||
ctx->vm[JITVARS_FUNCINFO] = fnc;
|
|
||||||
ctx->vm[JITVARS_REBASE] = data->rebase;
|
|
||||||
fnc->code_size = codemem;
|
|
||||||
fnc->num_functions = data->func_idx;
|
|
||||||
|
|
||||||
/* clean up relocation+compilation memory */
|
/* clean up relocation+compilation memory */
|
||||||
data->rebase = NULL;
|
co->Abort();
|
||||||
AbortCompilation(co);
|
|
||||||
|
|
||||||
*err = SP_ERROR_NONE;
|
*err = SP_ERROR_NONE;
|
||||||
|
|
||||||
return ctx;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
|
SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
|
||||||
@ -2851,126 +2896,149 @@ void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
|
|||||||
engine->FreePageMemory((void *)func);
|
engine->FreePageMemory((void *)func);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *JITX86::GetVMName()
|
int JITX86::ContextExecute(sp_plugin_t *pl, sp_context_t *ctx, uint32_t code_idx, cell_t *result)
|
||||||
{
|
|
||||||
return "JIT (x86)";
|
|
||||||
}
|
|
||||||
|
|
||||||
int JITX86::ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result)
|
|
||||||
{
|
{
|
||||||
typedef int (*CONTEXT_EXECUTE)(sp_context_t *, uint32_t, cell_t *);
|
typedef int (*CONTEXT_EXECUTE)(sp_context_t *, uint32_t, cell_t *);
|
||||||
CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)ctx->codebase;
|
CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)pl->codebase;
|
||||||
return fn(ctx, code_idx, result);
|
return fn(ctx, code_idx, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JITX86::FreeContext(sp_context_t *ctx)
|
ICompilation *JITX86::StartCompilation()
|
||||||
{
|
|
||||||
engine->FreePageMemory(ctx->codebase);
|
|
||||||
delete [] ctx->memory;
|
|
||||||
delete [] ctx->files;
|
|
||||||
delete [] ctx->lines;
|
|
||||||
delete [] ctx->natives;
|
|
||||||
delete [] ctx->publics;
|
|
||||||
delete [] ctx->pubvars;
|
|
||||||
delete [] ctx->symbols;
|
|
||||||
engine->BaseFree(ctx->vm[JITVARS_REBASE]);
|
|
||||||
free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
|
|
||||||
delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
|
|
||||||
delete (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
|
|
||||||
delete ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
ICompilation *JITX86::StartCompilation(sp_plugin_t *plugin)
|
|
||||||
{
|
{
|
||||||
CompData *data = new CompData;
|
CompData *data = new CompData;
|
||||||
|
|
||||||
|
data->jit_float_table = NULL;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompData::SetRuntime(BaseRuntime *runtime)
|
||||||
|
{
|
||||||
|
plugin = runtime->m_pPlugin;
|
||||||
|
|
||||||
uint32_t max_natives = plugin->info.natives_num;
|
uint32_t max_natives = plugin->info.natives_num;
|
||||||
const char *strbase = plugin->info.stringbase;
|
const char *strbase = plugin->info.stringbase;
|
||||||
|
|
||||||
data->plugin = plugin;
|
this->runtime = runtime;
|
||||||
data->inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
|
|
||||||
data->error_set = SP_ERROR_NONE;
|
|
||||||
|
|
||||||
data->jit_float_table = new floattbl_t[max_natives];
|
inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
|
||||||
|
error_set = SP_ERROR_NONE;
|
||||||
|
|
||||||
|
jit_float_table = new floattbl_t[max_natives];
|
||||||
for (uint32_t i=0; i<max_natives; i++)
|
for (uint32_t i=0; i<max_natives; i++)
|
||||||
{
|
{
|
||||||
const char *name = strbase + plugin->info.natives[i].name;
|
const char *name = strbase + plugin->info.natives[i].name;
|
||||||
if (!strcmp(name, "FloatAbs"))
|
if (!strcmp(name, "FloatAbs"))
|
||||||
{
|
{
|
||||||
data->jit_float_table[i].found = true;
|
jit_float_table[i].found = true;
|
||||||
data->jit_float_table[i].index = OP_FABS;
|
jit_float_table[i].index = OP_FABS;
|
||||||
} else if (!strcmp(name, "FloatAdd")) {
|
} else if (!strcmp(name, "FloatAdd")) {
|
||||||
data->jit_float_table[i].found = true;
|
jit_float_table[i].found = true;
|
||||||
data->jit_float_table[i].index = OP_FLOATADD;
|
jit_float_table[i].index = OP_FLOATADD;
|
||||||
} else if (!strcmp(name, "FloatSub")) {
|
} else if (!strcmp(name, "FloatSub")) {
|
||||||
data->jit_float_table[i].found = true;
|
jit_float_table[i].found = true;
|
||||||
data->jit_float_table[i].index = OP_FLOATSUB;
|
jit_float_table[i].index = OP_FLOATSUB;
|
||||||
} else if (!strcmp(name, "FloatMul")) {
|
} else if (!strcmp(name, "FloatMul")) {
|
||||||
data->jit_float_table[i].found = true;
|
jit_float_table[i].found = true;
|
||||||
data->jit_float_table[i].index = OP_FLOATMUL;
|
jit_float_table[i].index = OP_FLOATMUL;
|
||||||
} else if (!strcmp(name, "FloatDiv")) {
|
} else if (!strcmp(name, "FloatDiv")) {
|
||||||
data->jit_float_table[i].found = true;
|
jit_float_table[i].found = true;
|
||||||
data->jit_float_table[i].index = OP_FLOATDIV;
|
jit_float_table[i].index = OP_FLOATDIV;
|
||||||
} else if (!strcmp(name, "float")) {
|
} else if (!strcmp(name, "float")) {
|
||||||
data->jit_float_table[i].found = true;
|
jit_float_table[i].found = true;
|
||||||
data->jit_float_table[i].index = OP_FLOAT;
|
jit_float_table[i].index = OP_FLOAT;
|
||||||
} else if (!strcmp(name, "FloatCompare")) {
|
} else if (!strcmp(name, "FloatCompare")) {
|
||||||
data->jit_float_table[i].found = true;
|
jit_float_table[i].found = true;
|
||||||
data->jit_float_table[i].index = OP_FLOATCMP;
|
jit_float_table[i].index = OP_FLOATCMP;
|
||||||
} else if (!strcmp(name, "RoundToZero")) {
|
} else if (!strcmp(name, "RoundToZero")) {
|
||||||
data->jit_float_table[i].found = true;
|
jit_float_table[i].found = true;
|
||||||
data->jit_float_table[i].index = OP_RND_TO_ZERO;
|
jit_float_table[i].index = OP_RND_TO_ZERO;
|
||||||
} else if (!strcmp(name, "RoundToCeil")) {
|
} else if (!strcmp(name, "RoundToCeil")) {
|
||||||
data->jit_float_table[i].found = true;
|
jit_float_table[i].found = true;
|
||||||
data->jit_float_table[i].index = OP_RND_TO_CEIL;
|
jit_float_table[i].index = OP_RND_TO_CEIL;
|
||||||
} else if (!strcmp(name, "RoundToFloor")) {
|
} else if (!strcmp(name, "RoundToFloor")) {
|
||||||
data->jit_float_table[i].found = true;
|
jit_float_table[i].found = true;
|
||||||
data->jit_float_table[i].index = OP_RND_TO_FLOOR;
|
jit_float_table[i].index = OP_RND_TO_FLOOR;
|
||||||
} else if (!strcmp(name, "RoundToNearest")) {
|
} else if (!strcmp(name, "RoundToNearest")) {
|
||||||
data->jit_float_table[i].found = true;
|
jit_float_table[i].found = true;
|
||||||
data->jit_float_table[i].index = OP_RND_TO_NEAREST;
|
jit_float_table[i].index = OP_RND_TO_NEAREST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ICompilation *JITX86::StartCompilation(BaseRuntime *runtime)
|
||||||
|
{
|
||||||
|
CompData *data = new CompData;
|
||||||
|
|
||||||
|
data->SetRuntime(runtime);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JITX86::AbortCompilation(ICompilation *co)
|
void CompData::Abort()
|
||||||
{
|
{
|
||||||
if (((CompData *)co)->rebase)
|
if (rebase)
|
||||||
{
|
{
|
||||||
engine->BaseFree(((CompData *)co)->rebase);
|
engine->BaseFree(rebase);
|
||||||
}
|
}
|
||||||
delete [] ((CompData *)co)->jit_float_table;
|
delete [] jit_float_table;
|
||||||
delete (CompData *)co;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char *val)
|
void JITX86::FreeContextVars(sp_context_t *ctx)
|
||||||
{
|
{
|
||||||
CompData *data = (CompData *)co;
|
free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
|
||||||
|
delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
|
||||||
|
}
|
||||||
|
|
||||||
|
void JITX86::FreePluginVars(sp_plugin_t *pl)
|
||||||
|
{
|
||||||
|
delete [] pl->files;
|
||||||
|
delete [] pl->lines;
|
||||||
|
delete [] pl->natives;
|
||||||
|
delete [] pl->publics;
|
||||||
|
delete [] pl->pubvars;
|
||||||
|
delete [] pl->symbols;
|
||||||
|
|
||||||
|
if (pl->codebase != NULL)
|
||||||
|
{
|
||||||
|
g_engine1.FreePageMemory(pl->codebase);
|
||||||
|
pl->codebase = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl->files = NULL;
|
||||||
|
pl->lines = NULL;
|
||||||
|
pl->natives = NULL;
|
||||||
|
pl->publics = NULL;
|
||||||
|
pl->pubvars = NULL;
|
||||||
|
pl->symbols = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CompData::SetOption(const char *key, const char *val)
|
||||||
|
{
|
||||||
if (strcmp(key, SP_JITCONF_DEBUG) == 0)
|
if (strcmp(key, SP_JITCONF_DEBUG) == 0)
|
||||||
{
|
{
|
||||||
if ((atoi(val) == 1) || !strcmp(val, "yes"))
|
if ((atoi(val) == 1) || !strcmp(val, "yes"))
|
||||||
{
|
{
|
||||||
data->debug = true;
|
debug = true;
|
||||||
} else {
|
} else {
|
||||||
data->debug = false;
|
debug = false;
|
||||||
}
|
}
|
||||||
if (data->debug && !(data->plugin->flags & SP_FLAG_DEBUG))
|
if (debug && plugin && !(plugin->flags & SP_FLAG_DEBUG))
|
||||||
{
|
{
|
||||||
data->debug = false;
|
debug = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
|
else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
|
||||||
{
|
{
|
||||||
data->profile = atoi(val);
|
profile = atoi(val);
|
||||||
|
|
||||||
/** Callbacks must be profiled to profile functions! */
|
/** Callbacks must be profiled to profile functions! */
|
||||||
if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
|
if ((profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
|
||||||
{
|
{
|
||||||
data->profile |= SP_PROF_CALLBACKS;
|
profile |= SP_PROF_CALLBACKS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2979,83 +3047,3 @@ bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int JITX86::GetAPIVersion()
|
|
||||||
{
|
|
||||||
return SOURCEPAWN_VM_API_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JITX86::FunctionPLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result)
|
|
||||||
{
|
|
||||||
uint8_t *rebase = (uint8_t *)ctx->vm[JITVARS_REBASE];
|
|
||||||
|
|
||||||
/* Is this within the pcode bounds? */
|
|
||||||
if (code_addr >= ctx->plugin->pcode_size - sizeof(uint32_t))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Relocate this */
|
|
||||||
code_addr = *(jitoffs_t *)(rebase + code_addr);
|
|
||||||
|
|
||||||
/* Check if this is in the relocation bounds */
|
|
||||||
functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
|
|
||||||
if (code_addr >= fnc->code_size)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the function info and sanity check */
|
|
||||||
funcinfo_t *f = (funcinfo_t *)((char *)ctx->codebase + code_addr - sizeof(funcinfo_t));
|
|
||||||
if (f->magic != JIT_FUNCMAGIC || f->index >= fnc->num_functions)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
*result = f->index;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JITX86::FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result)
|
|
||||||
{
|
|
||||||
/* Check if this is in the relocation bounds */
|
|
||||||
functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
|
|
||||||
if (code_addr >= fnc->code_size)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the function info and sanity check */
|
|
||||||
funcinfo_t *f = (funcinfo_t *)((char *)ctx->codebase + code_addr - sizeof(funcinfo_t));
|
|
||||||
if (f->magic != JIT_FUNCMAGIC || f->index >= fnc->num_functions)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
*result = f->index;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int JITX86::FunctionCount(const sp_context_t *ctx)
|
|
||||||
{
|
|
||||||
functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
|
|
||||||
|
|
||||||
return fnc->num_functions;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *JITX86::GetVersionString()
|
|
||||||
{
|
|
||||||
return SVN_FULL_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *JITX86::GetCPUOptimizations()
|
|
||||||
{
|
|
||||||
return "Generic i686";
|
|
||||||
}
|
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#include <sp_vm_types.h>
|
#include <sp_vm_types.h>
|
||||||
#include <sp_vm_api.h>
|
#include <sp_vm_api.h>
|
||||||
#include <jit_helpers.h>
|
#include <jit_helpers.h>
|
||||||
|
#include "../jit_shared.h"
|
||||||
|
#include "../BaseRuntime.h"
|
||||||
|
|
||||||
using namespace SourcePawn;
|
using namespace SourcePawn;
|
||||||
|
|
||||||
@ -44,11 +46,14 @@ using namespace SourcePawn;
|
|||||||
#define JIT_FUNCMAGIC 0x214D4148 //magic function offset
|
#define JIT_FUNCMAGIC 0x214D4148 //magic function offset
|
||||||
|
|
||||||
#define JITVARS_TRACKER 0 //important: don't change this to avoid trouble
|
#define JITVARS_TRACKER 0 //important: don't change this to avoid trouble
|
||||||
#define JITVARS_FUNCINFO 1 //important: don't change this aWOAWOGJQG I LIKE HAM
|
#define JITVARS_BASECTX 1 //important: don't change this aWOAWOGJQG I LIKE HAM
|
||||||
#define JITVARS_REBASE 2 //important: hi, i'm bail
|
#define JITVARS_PROFILER 2 //profiler
|
||||||
|
#define JITVARS_PLUGIN 3 //sp_plugin_t
|
||||||
|
|
||||||
#define sDIMEN_MAX 5 //this must mirror what the compiler has.
|
#define sDIMEN_MAX 5 //this must mirror what the compiler has.
|
||||||
|
|
||||||
|
#define GET_CONTEXT(c) ((IPluginContext *)c->vm[JITVARS_BASECTX])
|
||||||
|
|
||||||
typedef struct tracker_s
|
typedef struct tracker_s
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
@ -87,7 +92,11 @@ public:
|
|||||||
error_set(SP_ERROR_NONE), func_idx(0)
|
error_set(SP_ERROR_NONE), func_idx(0)
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
bool SetOption(const char *key, const char *val);
|
||||||
|
void SetRuntime(BaseRuntime *runtime);
|
||||||
|
void Abort();
|
||||||
public:
|
public:
|
||||||
|
BaseRuntime *runtime; /* runtime handle */
|
||||||
sp_plugin_t *plugin; /* plugin handle */
|
sp_plugin_t *plugin; /* plugin handle */
|
||||||
bool debug; /* whether to compile debug mode */
|
bool debug; /* whether to compile debug mode */
|
||||||
int profile; /* profiling flags */
|
int profile; /* profiling flags */
|
||||||
@ -116,22 +125,15 @@ public:
|
|||||||
uint32_t codesize; /* total codesize */
|
uint32_t codesize; /* total codesize */
|
||||||
};
|
};
|
||||||
|
|
||||||
class JITX86 : public IVirtualMachine
|
class JITX86
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const char *GetVMName();
|
ICompilation *StartCompilation(BaseRuntime *runtime);
|
||||||
ICompilation *StartCompilation(sp_plugin_t *plugin);
|
ICompilation *StartCompilation();
|
||||||
bool SetCompilationOption(ICompilation *co, const char *key, const char *val);
|
bool Compile(ICompilation *co, BaseRuntime *runtime, int *err);
|
||||||
sp_context_t *CompileToContext(ICompilation *co, int *err);
|
void FreePluginVars(sp_plugin_t *pl);
|
||||||
void AbortCompilation(ICompilation *co);
|
void FreeContextVars(sp_context_t *ctx);
|
||||||
void FreeContext(sp_context_t *ctx);
|
int ContextExecute(sp_plugin_t *pl, sp_context_t *ctx, uint32_t code_idx, cell_t *result);
|
||||||
int ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result);
|
|
||||||
unsigned int GetAPIVersion();
|
|
||||||
bool FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result);
|
|
||||||
bool FunctionPLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result);
|
|
||||||
unsigned int FunctionCount(const sp_context_t *ctx);
|
|
||||||
const char *GetVersionString();
|
|
||||||
const char *GetCPUOptimizations();
|
|
||||||
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
|
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
|
||||||
void DestroyFakeNative(SPVM_NATIVE_FUNC func);
|
void DestroyFakeNative(SPVM_NATIVE_FUNC func);
|
||||||
};
|
};
|
||||||
@ -157,6 +159,6 @@ jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative=false);
|
|||||||
#define AMX_INFO_CONTEXT 12 //physical
|
#define AMX_INFO_CONTEXT 12 //physical
|
||||||
#define AMX_INFO_STACKTOP 16 //relocated
|
#define AMX_INFO_STACKTOP 16 //relocated
|
||||||
|
|
||||||
extern ISourcePawnEngine *engine;
|
extern JITX86 g_Jit1;
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_
|
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
jitoffs_t Write_Execute_Function(JitWriter *jit)
|
jitoffs_t Write_Execute_Function(JitWriter *jit)
|
||||||
{
|
{
|
||||||
|
CompData *co = (CompData *)jit->data;
|
||||||
/**
|
/**
|
||||||
* The variables we're passed in:
|
* The variables we're passed in:
|
||||||
* sp_context_t *ctx, uint32_t code_idx, cell_t *result
|
* sp_context_t *ctx, uint32_t code_idx, cell_t *result
|
||||||
@ -76,14 +77,14 @@ jitoffs_t Write_Execute_Function(JitWriter *jit)
|
|||||||
//mov [esi+12], eax - store context into info pointer
|
//mov [esi+12], eax - store context into info pointer
|
||||||
//mov ecx, [eax+<offs>] - get heap pointer
|
//mov ecx, [eax+<offs>] - get heap pointer
|
||||||
//mov [esi+4], ecx - store heap into info pointer
|
//mov [esi+4], ecx - store heap into info pointer
|
||||||
//mov ebp, [eax+<offs>] - get data pointer
|
//mov ebp, <addr> - get data pointer
|
||||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 16);
|
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 16);
|
||||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_RETVAL);
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_RETVAL);
|
||||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 8);
|
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 8);
|
||||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_CONTEXT);
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_CONTEXT);
|
||||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, hp));
|
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, hp));
|
||||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_HEAP);
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_HEAP);
|
||||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_DAT, REG_EAX, offsetof(sp_context_t, memory));
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_DAT, jit_int32_t(co->plugin->memory));
|
||||||
|
|
||||||
/* Frame setup */
|
/* Frame setup */
|
||||||
//mov edi, [eax+<offs>] - get stack pointer
|
//mov edi, [eax+<offs>] - get stack pointer
|
||||||
@ -97,15 +98,23 @@ jitoffs_t Write_Execute_Function(JitWriter *jit)
|
|||||||
//mov ecx, [eax+<offs>] - copy memsize to temp var
|
//mov ecx, [eax+<offs>] - copy memsize to temp var
|
||||||
//add ecx, ebp - relocate
|
//add ecx, ebp - relocate
|
||||||
//mov [esi+x], ecx - store relocated
|
//mov [esi+x], ecx - store relocated
|
||||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, mem_size));
|
IA32_Mov_Reg_Imm32(jit, REG_ECX, co->plugin->mem_size);
|
||||||
IA32_Add_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG);
|
IA32_Add_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG);
|
||||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_STACKTOP);
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_STACKTOP);
|
||||||
|
|
||||||
/* Remaining needed vars */
|
/* Remaining needed vars */
|
||||||
//mov ecx, [esp+(4*(NUM_INFO_PARAMS+3))+12] - get code index (normally esp+12, but we have another array on the stack)
|
//mov ecx, [esp+(4*(NUM_INFO_PARAMS+3))+12] - get code index (normally esp+12, but we have another array on the stack)
|
||||||
//add ecx, [eax+<offs>] - add code base to index
|
//push eax
|
||||||
|
//mov eax, <addr of addr of code>
|
||||||
|
//mov eax, [eax]
|
||||||
|
//add ecx, eax
|
||||||
|
//pop eax
|
||||||
IA32_Mov_Reg_Esp_Disp8(jit, REG_ECX, 12+(4*(NUM_INFO_PARAMS+3)));
|
IA32_Mov_Reg_Esp_Disp8(jit, REG_ECX, 12+(4*(NUM_INFO_PARAMS+3)));
|
||||||
IA32_Add_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, codebase));
|
IA32_Push_Reg(jit, REG_EAX);
|
||||||
|
IA32_Mov_Reg_Imm32(jit, REG_EAX, jit_int32_t(&co->plugin->codebase));
|
||||||
|
IA32_Mov_Reg_Rm(jit, REG_EAX, REG_EAX, MOD_MEM_REG);
|
||||||
|
IA32_Add_Reg_Rm(jit, REG_ECX, REG_EAX, MOD_REG);
|
||||||
|
IA32_Pop_Reg(jit, REG_EAX);
|
||||||
|
|
||||||
/* by now, everything is set up, so we can call into the plugin */
|
/* by now, everything is set up, so we can call into the plugin */
|
||||||
//call ecx
|
//call ecx
|
||||||
@ -161,36 +170,30 @@ void Write_BreakDebug(JitWriter *jit)
|
|||||||
//push edi
|
//push edi
|
||||||
//mov edi, ecx
|
//mov edi, ecx
|
||||||
//mov ecx, [esi+ctx]
|
//mov ecx, [esi+ctx]
|
||||||
//cmp [ecx+dbreak], 0
|
|
||||||
//jnz :nocall
|
|
||||||
IA32_Push_Reg(jit, REG_EDI);
|
IA32_Push_Reg(jit, REG_EDI);
|
||||||
IA32_Mov_Reg_Rm(jit, REG_EDI, REG_ECX, MOD_REG);
|
IA32_Mov_Reg_Rm(jit, REG_EDI, REG_ECX, MOD_REG);
|
||||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
||||||
IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, dbreak), 0);
|
|
||||||
jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_Z, 0);
|
|
||||||
|
|
||||||
//:TODO: align the stack to 16bytes like in sysreq.x
|
//:TODO: align the stack to 16bytes like in sysreq.x
|
||||||
/* NOTE, Hack! PUSHAD pushes EDI last which still has the CIP */
|
/* NOTE, Hack! PUSHAD pushes EDI last which still has the CIP */
|
||||||
//pushad
|
//pushad
|
||||||
//push [esi+frm]
|
//push [esi+frm]
|
||||||
//push ctx
|
//push [ctx+basectx]
|
||||||
//mov ecx, [ecx+dbreak]
|
//mov ecx, <dbreak>
|
||||||
//call ecx
|
//call ecx
|
||||||
//add esp, 8
|
//add esp, 8
|
||||||
//popad
|
//popad
|
||||||
IA32_Pushad(jit);
|
IA32_Pushad(jit);
|
||||||
IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_FRAME); //:TODO: move to regs and push? and dont disp for 0
|
IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_FRAME); //:TODO: move to regs and push? and dont disp for 0
|
||||||
IA32_Push_Reg(jit, AMX_REG_TMP);
|
IA32_Push_Rm_Disp8(jit, AMX_REG_TMP, offsetof(sp_context_t, vm[JITVARS_BASECTX]));
|
||||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_TMP, offsetof(sp_context_t, dbreak));
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, jit_int32_t(((CompData *)jit->data)->plugin->dbreak));
|
||||||
IA32_Call_Reg(jit, AMX_REG_TMP);
|
IA32_Call_Reg(jit, AMX_REG_TMP);
|
||||||
IA32_Add_Rm_Imm8(jit, REG_ESP, 4*2, MOD_REG);
|
IA32_Add_Rm_Imm8(jit, REG_ESP, 4*2, MOD_REG);
|
||||||
IA32_Popad(jit);
|
IA32_Popad(jit);
|
||||||
|
|
||||||
//:nocall
|
|
||||||
//pop edi
|
//pop edi
|
||||||
//ret
|
//ret
|
||||||
IA32_Pop_Reg(jit, REG_EDI);
|
IA32_Pop_Reg(jit, REG_EDI);
|
||||||
IA32_Send_Jump8_Here(jit, jmp);
|
|
||||||
IA32_Return(jit);
|
IA32_Return(jit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,7 +317,7 @@ void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg)
|
|||||||
/* Part 1: Check if we're in the memory bounds */
|
/* Part 1: Check if we're in the memory bounds */
|
||||||
//cmp <reg>, <stpu>
|
//cmp <reg>, <stpu>
|
||||||
//jae :error
|
//jae :error
|
||||||
IA32_Cmp_Rm_Imm32(jit, MOD_REG, reg, ((CompData *)jit->data)->plugin->memory);
|
IA32_Cmp_Rm_Imm32(jit, MOD_REG, reg, ((CompData *)jit->data)->plugin->mem_size);
|
||||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_memaccess);
|
IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_memaccess);
|
||||||
|
|
||||||
/* Part 2: Check if we're in the invalid region between HP and SP */
|
/* Part 2: Check if we're in the invalid region between HP and SP */
|
||||||
|
Loading…
Reference in New Issue
Block a user