Modernize sp_vm_engine style.

This commit is contained in:
dvander@alliedmods.net 2015-02-23 13:08:28 -08:00
parent bcd88b4437
commit 1b47aa10ca
2 changed files with 246 additions and 283 deletions

View File

@ -1,34 +1,15 @@
/** // vim: set sts=2 ts=8 sw=2 tw=99 et:
* vim: set ts=4 sw=4 tw=99 et: //
* ============================================================================= // Copyright (C) 2006-2015 AlliedModders LLC
* SourcePawn //
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. // This file is part of SourcePawn. SourcePawn is free software: you can
* ============================================================================= // redistribute it and/or modify it under the terms of the GNU General Public
* // License as published by the Free Software Foundation, either version 3 of
* This program is free software; you can redistribute it and/or modify it under // the License, or (at your option) any later version.
* the terms of the GNU General Public License, version 3.0, as published by the //
* Free Software Foundation. // You should have received a copy of the GNU General Public License along with
* // SourcePawn. If not, see http://www.gnu.org/licenses/.
* 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 <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
@ -57,298 +38,294 @@ SourcePawnEngine g_engine1;
using namespace SourcePawn; using namespace SourcePawn;
#define ERROR_MESSAGE_MAX 30 #define ERROR_MESSAGE_MAX 30
static const char *g_ErrorMsgTable[] = static const char *g_ErrorMsgTable[] =
{ {
NULL, NULL,
"Unrecognizable file format", "Unrecognizable file format",
"Decompressor was not found", "Decompressor was not found",
"Not enough space on the heap", "Not enough space on the heap",
"Invalid parameter or parameter type", "Invalid parameter or parameter type",
"Invalid plugin address", "Invalid plugin address",
"Object or index not found", "Object or index not found",
"Invalid index or index not found", "Invalid index or index not found",
"Not enough space on the stack", "Not enough space on the stack",
"Debug section not found or debug not enabled", "Debug section not found or debug not enabled",
"Invalid instruction", "Invalid instruction",
"Invalid memory access", "Invalid memory access",
"Stack went below stack boundary", "Stack went below stack boundary",
"Heap went below heap boundary", "Heap went below heap boundary",
"Divide by zero", "Divide by zero",
"Array index is out of bounds", "Array index is out of bounds",
"Instruction contained invalid parameter", "Instruction contained invalid parameter",
"Stack memory leaked by native", "Stack memory leaked by native",
"Heap memory leaked by native", "Heap memory leaked by native",
"Dynamic array is too big", "Dynamic array is too big",
"Tracker stack is out of bounds", "Tracker stack is out of bounds",
"Native is not bound", "Native is not bound",
"Maximum number of parameters reached", "Maximum number of parameters reached",
"Native detected error", "Native detected error",
"Plugin not runnable", "Plugin not runnable",
"Call was aborted", "Call was aborted",
"Plugin format is too old", "Plugin format is too old",
"Plugin format is too new", "Plugin format is too new",
"Out of memory", "Out of memory",
"Integer overflow", "Integer overflow",
"Script execution timed out" "Script execution timed out"
}; };
const char *SourcePawnEngine::GetErrorString(int error) const char *
SourcePawnEngine::GetErrorString(int error)
{ {
if (error < 1 || error > ERROR_MESSAGE_MAX) if (error < 1 || error > ERROR_MESSAGE_MAX)
{ return NULL;
return NULL; return g_ErrorMsgTable[error];
}
return g_ErrorMsgTable[error];
} }
SourcePawnEngine::SourcePawnEngine() SourcePawnEngine::SourcePawnEngine()
{ {
m_pDebugHook = NULL; m_pDebugHook = NULL;
} }
SourcePawnEngine::~SourcePawnEngine() SourcePawnEngine::~SourcePawnEngine()
{ {
} }
void *SourcePawnEngine::ExecAlloc(size_t size) void *
SourcePawnEngine::ExecAlloc(size_t size)
{ {
#if defined WIN32 #if defined WIN32
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#elif defined __GNUC__ #elif defined __GNUC__
# if defined __APPLE__ # if defined __APPLE__
void *base = valloc(size); void *base = valloc(size);
# else # else
void *base = memalign(sysconf(_SC_PAGESIZE), size); void *base = memalign(sysconf(_SC_PAGESIZE), size);
# endif # endif
if (mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC) != 0) if (mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC) != 0) {
{ free(base);
free(base); return NULL;
return NULL; }
} return base;
return base;
#endif #endif
} }
void *SourcePawnEngine::AllocatePageMemory(size_t size) void *
SourcePawnEngine::AllocatePageMemory(size_t size)
{ {
return g_Jit.AllocCode(size); return g_Jit.AllocCode(size);
} }
void SourcePawnEngine::SetReadExecute(void *ptr) void
SourcePawnEngine::SetReadExecute(void *ptr)
{ {
/* already re */ /* already re */
} }
void SourcePawnEngine::SetReadWrite(void *ptr) void
SourcePawnEngine::SetReadWrite(void *ptr)
{ {
/* already rw */ /* already rw */
} }
void SourcePawnEngine::FreePageMemory(void *ptr) void
SourcePawnEngine::FreePageMemory(void *ptr)
{ {
g_Jit.FreeCode(ptr); g_Jit.FreeCode(ptr);
} }
void SourcePawnEngine::ExecFree(void *address) void
SourcePawnEngine::ExecFree(void *address)
{ {
#if defined WIN32 #if defined WIN32
VirtualFree(address, 0, MEM_RELEASE); VirtualFree(address, 0, MEM_RELEASE);
#elif defined __GNUC__ #elif defined __GNUC__
free(address); free(address);
#endif #endif
} }
void SourcePawnEngine::SetReadWriteExecute(void *ptr) void
SourcePawnEngine::SetReadWriteExecute(void *ptr)
{ {
//:TODO: g_ExeMemory.SetRWE(ptr); //:TODO: g_ExeMemory.SetRWE(ptr);
SetReadExecute(ptr); SetReadExecute(ptr);
} }
void *SourcePawnEngine::BaseAlloc(size_t size) void *
SourcePawnEngine::BaseAlloc(size_t size)
{ {
return malloc(size); return malloc(size);
} }
void SourcePawnEngine::BaseFree(void *memory) void
SourcePawnEngine::BaseFree(void *memory)
{ {
free(memory); free(memory);
} }
sp_plugin_t *SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err) sp_plugin_t *
SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err)
{ {
if (err != NULL) if (err != NULL)
{ *err = SP_ERROR_ABORTED;
*err = SP_ERROR_ABORTED;
}
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)
{ {
if (err != NULL) if (err != NULL)
{ *err = SP_ERROR_ABORTED;
*err = SP_ERROR_ABORTED;
}
return NULL; return NULL;
} }
int SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin) int
SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
{ {
return SP_ERROR_ABORTED; return SP_ERROR_ABORTED;
} }
IDebugListener *SourcePawnEngine::SetDebugListener(IDebugListener *pListener) IDebugListener *
SourcePawnEngine::SetDebugListener(IDebugListener *pListener)
{ {
IDebugListener *old = m_pDebugHook; IDebugListener *old = m_pDebugHook;
m_pDebugHook = pListener; m_pDebugHook = pListener;
return old; return old;
} }
unsigned int SourcePawnEngine::GetEngineAPIVersion() unsigned int
SourcePawnEngine::GetEngineAPIVersion()
{ {
return SOURCEPAWN_ENGINE_API_VERSION; return SOURCEPAWN_ENGINE_API_VERSION;
} }
unsigned int SourcePawnEngine::GetContextCallCount() unsigned int
SourcePawnEngine::GetContextCallCount()
{ {
return 0; return 0;
} }
void SourcePawnEngine::ReportError(BaseRuntime *runtime, int err, const char *errstr, cell_t rp_start) void
SourcePawnEngine::ReportError(BaseRuntime *runtime, int err, const char *errstr, cell_t rp_start)
{ {
if (m_pDebugHook == NULL) if (m_pDebugHook == NULL)
{ return;
return;
}
CContextTrace trace(runtime, err, errstr, rp_start); CContextTrace trace(runtime, err, errstr, rp_start);
m_pDebugHook->OnContextExecuteError(runtime->GetDefaultContext(), &trace); m_pDebugHook->OnContextExecuteError(runtime->GetDefaultContext(), &trace);
} }
CContextTrace::CContextTrace(BaseRuntime *pRuntime, int err, const char *errstr, cell_t start_rp) CContextTrace::CContextTrace(BaseRuntime *pRuntime, int err, const char *errstr, cell_t start_rp)
: m_pRuntime(pRuntime), m_Error(err), m_pMsg(errstr), m_StartRp(start_rp), m_Level(0) : m_pRuntime(pRuntime),
m_Error(err),
m_pMsg(errstr),
m_StartRp(start_rp),
m_Level(0)
{ {
m_ctx = pRuntime->m_pCtx->GetCtx(); m_ctx = pRuntime->m_pCtx->GetCtx();
m_pDebug = m_pRuntime->GetDebugInfo(); m_pDebug = m_pRuntime->GetDebugInfo();
} }
bool CContextTrace::DebugInfoAvailable() bool
CContextTrace::DebugInfoAvailable()
{ {
return (m_pDebug != NULL); return (m_pDebug != NULL);
} }
const char *CContextTrace::GetCustomErrorString() const char *
CContextTrace::GetCustomErrorString()
{ {
return m_pMsg; return m_pMsg;
} }
int CContextTrace::GetErrorCode() int
CContextTrace::GetErrorCode()
{ {
return m_Error; return m_Error;
} }
const char *CContextTrace::GetErrorString() const char *
CContextTrace::GetErrorString()
{ {
if (m_Error > ERROR_MESSAGE_MAX || m_Error < 1) if (m_Error > ERROR_MESSAGE_MAX || m_Error < 1)
{ return "Invalid error code";
return "Invalid error code"; return g_ErrorMsgTable[m_Error];
}
else
{
return g_ErrorMsgTable[m_Error];
}
} }
void CContextTrace::ResetTrace() void
CContextTrace::ResetTrace()
{ {
m_Level = 0; m_Level = 0;
} }
bool CContextTrace::GetTraceInfo(CallStackInfo *trace) bool
CContextTrace::GetTraceInfo(CallStackInfo *trace)
{ {
cell_t cip; cell_t cip;
if (m_Level == 0) if (m_Level == 0) {
{ cip = m_ctx->cip;
cip = m_ctx->cip; } else if (m_ctx->rp > 0) {
} /* Entries go from ctx.rp - 1 to m_StartRp */
else if (m_ctx->rp > 0) cell_t offs, start, end;
{
/* Entries go from ctx.rp - 1 to m_StartRp */
cell_t offs, start, end;
offs = m_Level - 1; offs = m_Level - 1;
start = m_ctx->rp - 1; start = m_ctx->rp - 1;
end = m_StartRp; end = m_StartRp;
if (start - offs < end) if (start - offs < end)
{ {
return false; return false;
} }
cip = m_ctx->rstk_cips[start - offs]; cip = m_ctx->rstk_cips[start - offs];
} } else {
else return false;
{ }
return false;
}
if (trace == NULL) if (trace == NULL) {
{ m_Level++;
m_Level++; return true;
return true; }
}
if (m_pDebug->LookupFile(cip, &(trace->filename)) != SP_ERROR_NONE) if (m_pDebug->LookupFile(cip, &(trace->filename)) != SP_ERROR_NONE)
{ trace->filename = NULL;
trace->filename = NULL;
}
if (m_pDebug->LookupFunction(cip, &(trace->function)) != SP_ERROR_NONE) if (m_pDebug->LookupFunction(cip, &(trace->function)) != SP_ERROR_NONE)
{ trace->function = NULL;
trace->function = NULL;
}
if (m_pDebug->LookupLine(cip, &(trace->line)) != SP_ERROR_NONE) if (m_pDebug->LookupLine(cip, &(trace->line)) != SP_ERROR_NONE)
{ trace->line = 0;
trace->line = 0;
}
m_Level++; m_Level++;
return true; return true;
} }
const char *CContextTrace::GetLastNative(uint32_t *index) const char *
CContextTrace::GetLastNative(uint32_t *index)
{ {
if (m_ctx->n_err == SP_ERROR_NONE) if (m_ctx->n_err == SP_ERROR_NONE)
{ return NULL;
return NULL;
}
sp_native_t *native; sp_native_t *native;
if (m_pRuntime->GetNativeByIndex(m_ctx->n_idx, &native) != SP_ERROR_NONE) if (m_pRuntime->GetNativeByIndex(m_ctx->n_idx, &native) != SP_ERROR_NONE)
{ return NULL;
return NULL;
}
if (index) if (index)
{ *index = m_ctx->n_idx;
*index = m_ctx->n_idx;
}
return native->name; return native->name;
} }
IDebugListener *SourcePawnEngine::GetDebugHook() IDebugListener *
SourcePawnEngine::GetDebugHook()
{ {
return m_pDebugHook; return m_pDebugHook;
} }

View File

@ -1,34 +1,15 @@
/** // vim: set sts=2 ts=8 sw=2 tw=99 et:
* vim: set ts=4 : //
* ============================================================================= // Copyright (C) 2006-2015 AlliedModders LLC
* SourcePawn //
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. // This file is part of SourcePawn. SourcePawn is free software: you can
* ============================================================================= // redistribute it and/or modify it under the terms of the GNU General Public
* // License as published by the Free Software Foundation, either version 3 of
* This program is free software; you can redistribute it and/or modify it under // the License, or (at your option) any later version.
* the terms of the GNU General Public License, version 3.0, as published by the //
* Free Software Foundation. // You should have received a copy of the GNU General Public License along with
* // SourcePawn. If not, see http://www.gnu.org/licenses/.
* 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_VM_ENGINE_H_ #ifndef _INCLUDE_SOURCEPAWN_VM_ENGINE_H_
#define _INCLUDE_SOURCEPAWN_VM_ENGINE_H_ #define _INCLUDE_SOURCEPAWN_VM_ENGINE_H_
@ -39,55 +20,60 @@ class BaseContext;
class CContextTrace : public IContextTrace class CContextTrace : public IContextTrace
{ {
public: public:
CContextTrace(BaseRuntime *pRuntime, int err, const char *errstr, cell_t start_rp); CContextTrace(BaseRuntime *pRuntime, int err, const char *errstr, cell_t start_rp);
public:
int GetErrorCode(); public:
const char *GetErrorString(); int GetErrorCode();
bool DebugInfoAvailable(); const char *GetErrorString();
const char *GetCustomErrorString(); bool DebugInfoAvailable();
bool GetTraceInfo(CallStackInfo *trace); const char *GetCustomErrorString();
void ResetTrace(); bool GetTraceInfo(CallStackInfo *trace);
const char *GetLastNative(uint32_t *index); void ResetTrace();
private: const char *GetLastNative(uint32_t *index);
BaseRuntime *m_pRuntime;
sp_context_t *m_ctx; private:
int m_Error; BaseRuntime *m_pRuntime;
const char *m_pMsg; sp_context_t *m_ctx;
cell_t m_StartRp; int m_Error;
cell_t m_Level; const char *m_pMsg;
IPluginDebugInfo *m_pDebug; cell_t m_StartRp;
cell_t m_Level;
IPluginDebugInfo *m_pDebug;
}; };
class SourcePawnEngine : public ISourcePawnEngine class SourcePawnEngine : public ISourcePawnEngine
{ {
public: public:
SourcePawnEngine(); SourcePawnEngine();
~SourcePawnEngine(); ~SourcePawnEngine();
public: //ISourcePawnEngine
sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err); public: //ISourcePawnEngine
sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err); sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err);
int FreeFromMemory(sp_plugin_t *plugin); sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err);
void *BaseAlloc(size_t size); int FreeFromMemory(sp_plugin_t *plugin);
void BaseFree(void *memory); void *BaseAlloc(size_t size);
void *ExecAlloc(size_t size); void BaseFree(void *memory);
void ExecFree(void *address); void *ExecAlloc(size_t size);
IDebugListener *SetDebugListener(IDebugListener *pListener); void ExecFree(void *address);
unsigned int GetContextCallCount(); IDebugListener *SetDebugListener(IDebugListener *pListener);
unsigned int GetEngineAPIVersion(); unsigned int GetContextCallCount();
void *AllocatePageMemory(size_t size); unsigned int GetEngineAPIVersion();
void SetReadWrite(void *ptr); void *AllocatePageMemory(size_t size);
void SetReadExecute(void *ptr); void SetReadWrite(void *ptr);
void SetReadWriteExecute(void *ptr); void SetReadExecute(void *ptr);
void FreePageMemory(void *ptr); void SetReadWriteExecute(void *ptr);
const char *GetErrorString(int err); void FreePageMemory(void *ptr);
void ReportError(BaseRuntime *runtime, int err, const char *errstr, cell_t rp_start); const char *GetErrorString(int err);
public: //Plugin function stuff void ReportError(BaseRuntime *runtime, int err, const char *errstr, cell_t rp_start);
CFunction *GetFunctionFromPool(funcid_t f, IPluginContext *plugin);
void ReleaseFunctionToPool(CFunction *func); public: //Plugin function stuff
IDebugListener *GetDebugHook(); CFunction *GetFunctionFromPool(funcid_t f, IPluginContext *plugin);
private: void ReleaseFunctionToPool(CFunction *func);
IDebugListener *m_pDebugHook; IDebugListener *GetDebugHook();
private:
IDebugListener *m_pDebugHook;
}; };
extern SourcePawnEngine g_engine1; extern SourcePawnEngine g_engine1;