refac-jit is almost done i think, next comes getting core compatible.
--HG-- branch : refac-jit extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/refac-jit%402373
This commit is contained in:
parent
307adb34ab
commit
3f38171d8c
333
sourcepawn/jit/BaseRuntime.cpp
Normal file
333
sourcepawn/jit/BaseRuntime.cpp
Normal file
@ -0,0 +1,333 @@
|
||||
#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"
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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->GetContext());
|
||||
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, pub->funcid, 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,
|
||||
m_pPlugin->publics[func_id].funcid,
|
||||
func_id);
|
||||
pFunc = m_PubFuncs[func_id];
|
||||
}
|
||||
else if (pFunc->IsInvalidated())
|
||||
{
|
||||
pFunc->Set(m_pPlugin->publics[func_id].code_offs,
|
||||
this,
|
||||
m_pPlugin->publics[func_id].funcid,
|
||||
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, pub->funcid, 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, pub->funcid, 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);
|
||||
}
|
57
sourcepawn/jit/BaseRuntime.h
Normal file
57
sourcepawn/jit/BaseRuntime.h
Normal file
@ -0,0 +1,57 @@
|
||||
#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();
|
||||
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_
|
@ -31,44 +31,21 @@
|
||||
|
||||
#include <sp_vm_api.h>
|
||||
#include <malloc.h>
|
||||
#include "jit_x86.h"
|
||||
#include "x86/jit_x86.h"
|
||||
#include "dll_exports.h"
|
||||
#include "sp_vm_engine.h"
|
||||
#include "engine2.h"
|
||||
|
||||
SourcePawn::ISourcePawnEngine *engine = NULL;
|
||||
JITX86 g_jit;
|
||||
SourcePawnEngine2 g_engine2;
|
||||
|
||||
EXPORTFUNC int GiveEnginePointer2(SourcePawn::ISourcePawnEngine *engine_p, unsigned int api_version)
|
||||
EXPORTFUNC ISourcePawnEngine *GetSourcePawnEngine1()
|
||||
{
|
||||
engine = engine_p;
|
||||
|
||||
if (api_version > SOURCEPAWN_ENGINE_API_VERSION || api_version < 2)
|
||||
{
|
||||
return SP_ERROR_PARAM;
|
||||
}
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
return &g_engine1;
|
||||
}
|
||||
|
||||
EXPORTFUNC unsigned int GetExportCount()
|
||||
EXPORTFUNC ISourcePawnEngine2 *GetSourcePawnEngine2()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
return &g_engine2;
|
||||
}
|
||||
|
||||
#if defined __linux__
|
||||
|
271
sourcepawn/jit/engine2.cpp
Normal file
271
sourcepawn/jit/engine2.cpp
Normal file
@ -0,0 +1,271 @@
|
||||
#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;
|
||||
|
||||
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));
|
||||
|
||||
if (!_ReadPlugin(&hdr, base, plugin, err))
|
||||
{
|
||||
delete plugin;
|
||||
free(base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BaseRuntime *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();
|
||||
}
|
34
sourcepawn/jit/engine2.h
Normal file
34
sourcepawn/jit/engine2.h
Normal file
@ -0,0 +1,34 @@
|
||||
#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();
|
||||
public:
|
||||
IProfiler *GetProfiler();
|
||||
private:
|
||||
IProfiler *m_Profiler;
|
||||
};
|
||||
}
|
||||
|
||||
extern SourcePawn::SourcePawnEngine2 g_engine2;
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_ENGINE_2_H_
|
92
sourcepawn/jit/jit_shared.h
Normal file
92
sourcepawn/jit/jit_shared.h
Normal file
@ -0,0 +1,92 @@
|
||||
#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 */
|
||||
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 */
|
||||
} 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
|
||||
Name="VCCLCompilerTool"
|
||||
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"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
@ -185,24 +185,44 @@
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\BaseRuntime.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
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
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
AdditionalIncludeDirectories=""$(SOURCEMM16)\sourcehook""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\jit_x86.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\opcode_helpers.cpp"
|
||||
RelativePath="..\sp_vm_function.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
@ -211,12 +231,20 @@
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\BaseRuntime.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\dll_exports.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\jit\jit_helpers.h"
|
||||
RelativePath="..\engine2.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\jit_shared.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
@ -224,19 +252,23 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\jit_x86.h"
|
||||
RelativePath="..\x86\jit_x86.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\opcode_helpers.h"
|
||||
RelativePath="..\x86\opcode_helpers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ungen_opcodes.h"
|
||||
RelativePath="..\sp_vm_basecontext.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\jit\x86\x86_macros.h"
|
||||
RelativePath="..\sp_vm_engine.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sp_vm_function.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
@ -245,18 +277,6 @@
|
||||
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}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\jit_version.tpl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\opcode_switch.inc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ungen_opcode_switch.inc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\version.rc"
|
||||
>
|
||||
@ -266,27 +286,75 @@
|
||||
Name="SDK"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\jit_helpers.h"
|
||||
RelativePath="..\..\..\public\sourcepawn\sp_file_headers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\sourcepawn\sp_file_headers.h"
|
||||
RelativePath="..\..\..\public\sourcepawn\sp_typeutil.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\sourcepawn\sp_typeutil.h"
|
||||
RelativePath="..\..\..\public\sourcepawn\sp_vm_api.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\sourcepawn\sp_vm_api.h"
|
||||
RelativePath="..\..\..\public\sourcepawn\sp_vm_base.h"
|
||||
>
|
||||
</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
|
||||
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>
|
||||
</Filter>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,91 +34,75 @@
|
||||
|
||||
#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!
|
||||
*/
|
||||
|
||||
extern IProfiler *sm_profiler;
|
||||
|
||||
namespace SourcePawn
|
||||
class BaseContext : public IPluginContext
|
||||
{
|
||||
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;
|
||||
};
|
||||
public:
|
||||
BaseContext(BaseRuntime *pRuntime);
|
||||
~BaseContext();
|
||||
public: //IPluginContext
|
||||
IVirtualMachine *GetVirtualMachine();
|
||||
sp_context_t *GetContext();
|
||||
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();
|
||||
void SetIdentity(SourceMod::IdentityToken_t *token);
|
||||
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 Execute(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result);
|
||||
IPluginRuntime *GetRuntime();
|
||||
public:
|
||||
bool IsInExec();
|
||||
private:
|
||||
void SetErrorMessage(const char *msg, va_list ap);
|
||||
void _SetErrorMessage(const char *msg, ...);
|
||||
private:
|
||||
sp_plugin_t *m_pPlugin;
|
||||
SourceMod::IdentityToken_t *m_pToken;
|
||||
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;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_
|
||||
|
@ -48,6 +48,8 @@
|
||||
#include "zlib/zlib.h"
|
||||
#include "sp_vm_basecontext.h"
|
||||
|
||||
SourcePawnEngine g_engine1;
|
||||
|
||||
#if defined WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
@ -188,281 +190,31 @@ void SourcePawnEngine::BaseFree(void *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_file_hdr_t hdr;
|
||||
sp_plugin_t *plugin;
|
||||
uint8_t *base;
|
||||
int z_result;
|
||||
int error;
|
||||
|
||||
if (!fp)
|
||||
if (err != NULL)
|
||||
{
|
||||
error = SP_ERROR_NOT_FOUND;
|
||||
goto return_error;
|
||||
*err = SP_ERROR_ABORTED;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
sp_plugin_t *SourcePawnEngine::LoadFromMemory(void *base, sp_plugin_t *plugin, int *err)
|
||||
{
|
||||
sp_file_hdr_t hdr;
|
||||
uint8_t noptr = 0;
|
||||
|
||||
memcpy(&hdr, base, sizeof(sp_file_hdr_t));
|
||||
|
||||
if (!plugin)
|
||||
if (err != NULL)
|
||||
{
|
||||
plugin = (sp_plugin_t *)malloc(sizeof(sp_plugin_t));
|
||||
noptr = 1;
|
||||
*err = SP_ERROR_ABORTED;
|
||||
}
|
||||
|
||||
if (!_ReadPlugin(&hdr, (uint8_t *)base, plugin, err))
|
||||
{
|
||||
if (noptr)
|
||||
{
|
||||
free(plugin);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!noptr)
|
||||
{
|
||||
plugin->allocflags |= SP_FA_SELF_EXTERNAL;
|
||||
}
|
||||
plugin->allocflags |= SP_FA_BASE_EXTERNAL;
|
||||
|
||||
return plugin;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
|
||||
{
|
||||
if (!(plugin->allocflags & SP_FA_BASE_EXTERNAL))
|
||||
{
|
||||
free(plugin->base);
|
||||
plugin->base = NULL;
|
||||
}
|
||||
if (!(plugin->allocflags & SP_FA_SELF_EXTERNAL))
|
||||
{
|
||||
free(plugin);
|
||||
}
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
return SP_ERROR_ABORTED;
|
||||
}
|
||||
|
||||
#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 *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);
|
||||
|
||||
@ -538,7 +290,7 @@ void SourcePawnEngine::PushTracer(sp_context_t *ctx)
|
||||
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->ctx == ctx);
|
||||
@ -577,13 +329,13 @@ void SourcePawnEngine::PopTracer(int error, const char *msg)
|
||||
{
|
||||
uint32_t native = INVALID_CIP;
|
||||
|
||||
if (m_CallStack->ctx->n_err)
|
||||
if (m_CallStack->ctx->GetContext()->n_err)
|
||||
{
|
||||
native = m_CallStack->ctx->n_idx;
|
||||
native = m_CallStack->ctx->GetContext()->n_idx;
|
||||
}
|
||||
|
||||
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 */
|
||||
@ -607,7 +359,7 @@ CContextTrace::CContextTrace(TracedCall *pStart, int error, const char *msg, uin
|
||||
|
||||
bool CContextTrace::DebugInfoAvailable()
|
||||
{
|
||||
return ((m_pStart->ctx->flags & SP_FLAG_DEBUG) == SP_FLAG_DEBUG);
|
||||
return m_pStart->ctx->IsDebugging();
|
||||
}
|
||||
|
||||
const char *CContextTrace::GetCustomErrorString()
|
||||
@ -648,7 +400,7 @@ bool CContextTrace::GetTraceInfo(CallStackInfo *trace)
|
||||
return false;
|
||||
}
|
||||
|
||||
IPluginContext *pContext = m_pIterator->ctx->context;
|
||||
IPluginContext *pContext = m_pIterator->ctx;
|
||||
IPluginDebugInfo *pInfo = pContext->GetDebugInfo();
|
||||
|
||||
if (!pInfo)
|
||||
@ -690,7 +442,7 @@ const char *CContextTrace::GetLastNative(uint32_t *index)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -35,11 +35,13 @@
|
||||
#include "sp_vm_api.h"
|
||||
#include "sp_vm_function.h"
|
||||
|
||||
class BaseContext;
|
||||
|
||||
struct TracedCall
|
||||
{
|
||||
uint32_t cip;
|
||||
uint32_t frm;
|
||||
sp_context_t *ctx;
|
||||
BaseContext *ctx;
|
||||
TracedCall *next;
|
||||
unsigned int chain;
|
||||
};
|
||||
@ -73,8 +75,6 @@ public: //ISourcePawnEngine
|
||||
sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err);
|
||||
sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err);
|
||||
int FreeFromMemory(sp_plugin_t *plugin);
|
||||
IPluginContext *CreateBaseContext(sp_context_t *ctx);
|
||||
void FreeBaseContext(IPluginContext *ctx);
|
||||
void *BaseAlloc(size_t size);
|
||||
void BaseFree(void *memory);
|
||||
void *ExecAlloc(size_t size);
|
||||
@ -92,7 +92,7 @@ public: //Debugger Stuff
|
||||
*
|
||||
* @param ctx Plugin context.
|
||||
*/
|
||||
void PushTracer(sp_context_t *ctx);
|
||||
void PushTracer(BaseContext *ctx);
|
||||
|
||||
/**
|
||||
* @brief Pops a plugin off the call tracer.
|
||||
@ -102,7 +102,7 @@ public: //Debugger Stuff
|
||||
/**
|
||||
* @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
|
||||
CFunction *GetFunctionFromPool(funcid_t f, IPluginContext *plugin);
|
||||
void ReleaseFunctionToPool(CFunction *func);
|
||||
@ -117,4 +117,6 @@ private:
|
||||
//CFunction *m_pFreeFuncs;
|
||||
};
|
||||
|
||||
extern SourcePawnEngine g_engine1;
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_VM_ENGINE_H_
|
||||
|
@ -32,76 +32,47 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sp_vm_function.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "BaseRuntime.h"
|
||||
|
||||
/********************
|
||||
* 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_pContext = plugin;
|
||||
m_pRuntime = runtime;
|
||||
m_curparam = 0;
|
||||
m_errorstate = SP_ERROR_NONE;
|
||||
m_Invalid = false;
|
||||
m_pCtx = plugin ? plugin->GetContext() : NULL;
|
||||
m_FnId = id;
|
||||
|
||||
m_pContext->GetPublicByIndex(pub_id, &m_pPublic);
|
||||
m_FnId = fnid;
|
||||
}
|
||||
|
||||
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 ir, serial;
|
||||
return CallFunction(m_pRuntime->GetDefaultContext(), params, num_params, result);
|
||||
}
|
||||
|
||||
if (!IsRunnable())
|
||||
{
|
||||
return SP_ERROR_NOT_RUNNABLE;
|
||||
}
|
||||
|
||||
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;
|
||||
int CFunction::CallFunction(IPluginContext *pContext, const cell_t *params, unsigned int num_params, cell_t *result)
|
||||
{
|
||||
return pContext->Execute(this, params, num_params, result);
|
||||
}
|
||||
|
||||
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) :
|
||||
m_codeaddr(code_addr), m_pContext(plugin), m_curparam(0),
|
||||
m_errorstate(SP_ERROR_NONE), m_FnId(id)
|
||||
CFunction::CFunction(uint32_t code_addr, BaseRuntime *runtime, funcid_t id, uint32_t pub_id) :
|
||||
m_codeaddr(code_addr), m_curparam(0), m_errorstate(SP_ERROR_NONE), m_FnId(id)
|
||||
{
|
||||
m_Invalid = false;
|
||||
if (plugin)
|
||||
{
|
||||
m_pCtx = plugin->GetContext();
|
||||
}
|
||||
m_pContext->GetPublicByIndex(pub_id, &m_pPublic);
|
||||
m_pRuntime = runtime;
|
||||
}
|
||||
|
||||
int CFunction::PushCell(cell_t cell)
|
||||
@ -198,6 +169,11 @@ void CFunction::Cancel()
|
||||
}
|
||||
|
||||
int CFunction::Execute(cell_t *result)
|
||||
{
|
||||
return Execute(m_pRuntime->GetDefaultContext(), result);
|
||||
}
|
||||
|
||||
int CFunction::Execute(IPluginContext *ctx, cell_t *result)
|
||||
{
|
||||
int err = SP_ERROR_NONE;
|
||||
|
||||
@ -236,9 +212,9 @@ int CFunction::Execute(cell_t *result)
|
||||
if (!temp_info[i].str.is_sz)
|
||||
{
|
||||
/* Allocate a normal/generic array */
|
||||
if ((err=m_pContext->HeapAlloc(temp_info[i].size,
|
||||
&(temp_info[i].local_addr),
|
||||
&(temp_info[i].phys_addr)))
|
||||
if ((err=ctx->HeapAlloc(temp_info[i].size,
|
||||
&(temp_info[i].local_addr),
|
||||
&(temp_info[i].phys_addr)))
|
||||
!= SP_ERROR_NONE)
|
||||
{
|
||||
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);
|
||||
|
||||
/* Allocate the buffer */
|
||||
if ((err=m_pContext->HeapAlloc(cells,
|
||||
&(temp_info[i].local_addr),
|
||||
&(temp_info[i].phys_addr)))
|
||||
if ((err=ctx->HeapAlloc(cells,
|
||||
&(temp_info[i].local_addr),
|
||||
&(temp_info[i].phys_addr)))
|
||||
!= SP_ERROR_NONE)
|
||||
{
|
||||
break;
|
||||
@ -267,10 +243,10 @@ int CFunction::Execute(cell_t *result)
|
||||
/* Cut off UTF-8 properly */
|
||||
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
|
||||
{
|
||||
if ((err=m_pContext->StringToLocalUTF8(temp_info[i].local_addr,
|
||||
temp_info[i].size,
|
||||
(const char *)temp_info[i].orig_addr,
|
||||
NULL))
|
||||
if ((err=ctx->StringToLocalUTF8(temp_info[i].local_addr,
|
||||
temp_info[i].size,
|
||||
(const char *)temp_info[i].orig_addr,
|
||||
NULL))
|
||||
!= SP_ERROR_NONE)
|
||||
{
|
||||
break;
|
||||
@ -284,9 +260,9 @@ int CFunction::Execute(cell_t *result)
|
||||
/* Copy ASCII characters */
|
||||
else
|
||||
{
|
||||
if ((err=m_pContext->StringToLocal(temp_info[i].local_addr,
|
||||
temp_info[i].size,
|
||||
(const char *)temp_info[i].orig_addr))
|
||||
if ((err=ctx->StringToLocal(temp_info[i].local_addr,
|
||||
temp_info[i].size,
|
||||
(const char *)temp_info[i].orig_addr))
|
||||
!= SP_ERROR_NONE)
|
||||
{
|
||||
break;
|
||||
@ -307,7 +283,7 @@ int CFunction::Execute(cell_t *result)
|
||||
/* Make the call if we can */
|
||||
if (err == SP_ERROR_NONE)
|
||||
{
|
||||
if ((err = CallFunction(temp_params, numparams, result)) != SP_ERROR_NONE)
|
||||
if ((err = CallFunction(ctx, temp_params, numparams, result)) != SP_ERROR_NONE)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@ -364,3 +340,16 @@ funcid_t CFunction::GetFunctionID()
|
||||
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_
|
||||
#define _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
|
||||
|
||||
#include "sm_globals.h"
|
||||
#include <sp_vm_api.h>
|
||||
|
||||
class BaseRuntime;
|
||||
|
||||
using namespace SourcePawn;
|
||||
|
||||
struct ParamInfo
|
||||
{
|
||||
@ -56,7 +60,7 @@ class CFunction : public IPluginFunction
|
||||
friend class SourcePawnEngine;
|
||||
public:
|
||||
CFunction(uint32_t code_addr,
|
||||
IPluginContext *pContext,
|
||||
BaseRuntime *pRuntime,
|
||||
funcid_t fnid,
|
||||
uint32_t pub_id);
|
||||
public:
|
||||
@ -71,29 +75,23 @@ public:
|
||||
virtual void Cancel();
|
||||
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
|
||||
virtual IPluginContext *GetParentContext();
|
||||
inline bool IsInvalidated()
|
||||
{
|
||||
return m_Invalid;
|
||||
}
|
||||
inline void Invalidate()
|
||||
{
|
||||
m_Invalid = true;
|
||||
}
|
||||
bool IsInvalidated();
|
||||
void Invalidate();
|
||||
bool IsRunnable();
|
||||
funcid_t GetFunctionID();
|
||||
int Execute(IPluginContext *ctx, cell_t *result);
|
||||
int CallFunction(IPluginContext *ctx,
|
||||
const cell_t *params,
|
||||
unsigned int num_params,
|
||||
cell_t *result);
|
||||
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:
|
||||
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
|
||||
inline int SetError(int err)
|
||||
{
|
||||
m_errorstate = err;
|
||||
return err;
|
||||
}
|
||||
int SetError(int err);
|
||||
private:
|
||||
uint32_t m_codeaddr;
|
||||
IPluginContext *m_pContext;
|
||||
sp_context_t *m_pCtx;
|
||||
BaseRuntime *m_pRuntime;
|
||||
cell_t m_params[SP_MAX_EXEC_PARAMS];
|
||||
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
|
||||
unsigned int m_curparam;
|
||||
@ -101,7 +99,6 @@ private:
|
||||
CFunction *m_pNext;
|
||||
bool m_Invalid;
|
||||
funcid_t m_FnId;
|
||||
sp_public_t *m_pPublic;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_
|
||||
|
@ -35,12 +35,22 @@
|
||||
#include "jit_x86.h"
|
||||
#include "opcode_helpers.h"
|
||||
#include <x86_macros.h>
|
||||
#include "jit_version.h"
|
||||
#include "../jit_version.h"
|
||||
#include "../sp_vm_engine.h"
|
||||
#include "../engine2.h"
|
||||
|
||||
#if defined USE_UNGEN_OPCODES
|
||||
#include "ungen_opcodes.h"
|
||||
#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)
|
||||
{
|
||||
//mov eax, edx
|
||||
@ -1318,12 +1328,12 @@ inline void WriteOp_Retn(JitWriter *jit)
|
||||
|
||||
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)
|
||||
{
|
||||
ctx->profiler->OnFunctionEnd();
|
||||
((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionEnd();
|
||||
}
|
||||
|
||||
const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
|
||||
@ -2264,8 +2274,11 @@ inline void WriteOp_FloatCompare(JitWriter *jit)
|
||||
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
|
||||
{
|
||||
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;
|
||||
|
||||
@ -2276,15 +2289,18 @@ cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
|
||||
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 val;
|
||||
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;
|
||||
|
||||
@ -2295,9 +2311,9 @@ cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *par
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->profiler->OnNativeBegin(ctx->context, native);
|
||||
val = native->pfn(ctx->context, params);
|
||||
ctx->profiler->OnNativeEnd();
|
||||
plugin->profiler->OnNativeBegin(GET_CONTEXT(ctx), native);
|
||||
val = native->pfn(GET_CONTEXT(ctx), params);
|
||||
plugin->profiler->OnNativeEnd();
|
||||
|
||||
return val;
|
||||
}
|
||||
@ -2307,9 +2323,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_hp = ctx->hp;
|
||||
|
||||
sp_plugin_t *pl = GETPLUGIN(ctx);
|
||||
|
||||
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;
|
||||
return 0;
|
||||
@ -2321,7 +2339,7 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((uint32_t)ctx->sp >= ctx->mem_size)
|
||||
if ((uint32_t)ctx->sp >= pl->mem_size)
|
||||
{
|
||||
ctx->n_err = SP_ERROR_STACKMIN;
|
||||
return 0;
|
||||
@ -2353,9 +2371,11 @@ cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_
|
||||
cell_t save_sp = ctx->sp;
|
||||
cell_t save_hp = ctx->hp;
|
||||
|
||||
sp_plugin_t *pl = GETPLUGIN(ctx);
|
||||
|
||||
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;
|
||||
return 0;
|
||||
@ -2367,7 +2387,7 @@ cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((uint32_t)ctx->sp >= ctx->mem_size)
|
||||
if ((uint32_t)ctx->sp >= pl->mem_size)
|
||||
{
|
||||
ctx->n_err = SP_ERROR_STACKMIN;
|
||||
return 0;
|
||||
@ -2457,11 +2477,26 @@ void WriteErrorRoutines(CompData *data, JitWriter *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;
|
||||
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);
|
||||
}
|
||||
|
||||
/* The first phase is to browse */
|
||||
uint8_t *code = plugin->pcode;
|
||||
uint8_t *end_cip = plugin->pcode + plugin->pcode_size;
|
||||
@ -2584,8 +2619,8 @@ jit_rewind:
|
||||
if (data->error_set != SP_ERROR_NONE)
|
||||
{
|
||||
*err = data->error_set;
|
||||
AbortCompilation(co);
|
||||
return NULL;
|
||||
co->Abort();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* Write these last because error jumps should be unpredicted, and thus forward */
|
||||
@ -2627,23 +2662,27 @@ jit_rewind:
|
||||
* FOURTH PASS - Context Setup
|
||||
*************/
|
||||
|
||||
sp_context_t *ctx = new sp_context_t;
|
||||
memset(ctx, 0, sizeof(sp_context_t));
|
||||
|
||||
/* setup basics */
|
||||
ctx->codebase = writer.outbase;
|
||||
ctx->plugin = plugin;
|
||||
ctx->vmbase = this;
|
||||
ctx->flags = (data->debug ? SPFLAG_PLUGIN_DEBUG : 0);
|
||||
sp_context_t *ctx = data->runtime->GetDefaultContext()->GetContext();
|
||||
|
||||
/* Clear out any old cruft */
|
||||
if (plugin->codebase != NULL)
|
||||
{
|
||||
FreePluginVars(data->runtime->m_pPlugin);
|
||||
FreeContextVars(ctx);
|
||||
}
|
||||
|
||||
plugin->codebase = writer.outbase;
|
||||
|
||||
/* setup memory */
|
||||
ctx->memory = new uint8_t[plugin->memory];
|
||||
memcpy(ctx->memory, plugin->data, plugin->data_size);
|
||||
ctx->mem_size = plugin->memory;
|
||||
ctx->heap_base = plugin->data_size;
|
||||
ctx->hp = ctx->heap_base;
|
||||
ctx->sp = ctx->mem_size - sizeof(cell_t);
|
||||
ctx->prof_flags = data->profile;
|
||||
|
||||
ctx->hp = plugin->data_size;
|
||||
ctx->sp = plugin->mem_size - sizeof(cell_t);
|
||||
ctx->frm = ctx->sp;
|
||||
ctx->n_err = SP_ERROR_NONE;
|
||||
ctx->n_idx = SP_ERROR_NONE;
|
||||
plugin->prof_flags = data->profile;
|
||||
plugin->flags = data->debug ? SPFLAG_PLUGIN_DEBUG : 0;
|
||||
|
||||
const char *strbase = plugin->info.stringbase;
|
||||
uint32_t max, iter;
|
||||
@ -2651,39 +2690,39 @@ jit_rewind:
|
||||
/* relocate public info */
|
||||
if ((max = plugin->info.publics_num))
|
||||
{
|
||||
ctx->publics = new sp_public_t[max];
|
||||
plugin->publics = new sp_public_t[max];
|
||||
for (iter=0; iter<max; iter++)
|
||||
{
|
||||
ctx->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].name = strbase + plugin->info.publics[iter].name;
|
||||
plugin->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false);
|
||||
/* 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 */
|
||||
if ((max = plugin->info.pubvars_num))
|
||||
{
|
||||
uint8_t *dat = ctx->memory;
|
||||
ctx->pubvars = new sp_pubvar_t[max];
|
||||
uint8_t *dat = plugin->memory;
|
||||
plugin->pubvars = new sp_pubvar_t[max];
|
||||
for (iter=0; iter<max; iter++)
|
||||
{
|
||||
ctx->pubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
|
||||
ctx->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
|
||||
plugin->pubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
|
||||
plugin->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
|
||||
}
|
||||
}
|
||||
|
||||
/* relocate native info */
|
||||
if ((max = plugin->info.natives_num))
|
||||
{
|
||||
ctx->natives = new sp_native_t[max];
|
||||
plugin->natives = new sp_native_t[max];
|
||||
for (iter=0; iter<max; iter++)
|
||||
{
|
||||
ctx->natives[iter].name = strbase + plugin->info.natives[iter].name;
|
||||
ctx->natives[iter].pfn = &InvalidNative;
|
||||
ctx->natives[iter].status = SP_NATIVE_UNBOUND;
|
||||
ctx->natives[iter].flags = 0;
|
||||
ctx->natives[iter].user = NULL;
|
||||
plugin->natives[iter].name = strbase + plugin->info.natives[iter].name;
|
||||
plugin->natives[iter].pfn = &InvalidNative;
|
||||
plugin->natives[iter].status = SP_NATIVE_UNBOUND;
|
||||
plugin->natives[iter].flags = 0;
|
||||
plugin->natives[iter].user = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2696,20 +2735,20 @@ jit_rewind:
|
||||
|
||||
/* relocate files */
|
||||
max = plugin->debug.files_num;
|
||||
ctx->files = new sp_debug_file_t[max];
|
||||
plugin->files = new sp_debug_file_t[max];
|
||||
for (iter=0; iter<max; iter++)
|
||||
{
|
||||
ctx->files[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
|
||||
ctx->files[iter].name = strbase + plugin->debug.files[iter].name;
|
||||
plugin->files[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
|
||||
plugin->files[iter].name = strbase + plugin->debug.files[iter].name;
|
||||
}
|
||||
|
||||
/* relocate lines */
|
||||
max = plugin->debug.lines_num;
|
||||
ctx->lines = new sp_debug_line_t[max];
|
||||
plugin->lines = new sp_debug_line_t[max];
|
||||
for (iter=0; iter<max; iter++)
|
||||
{
|
||||
ctx->lines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
|
||||
ctx->lines[iter].line = plugin->debug.lines[iter].line;
|
||||
plugin->lines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
|
||||
plugin->lines[iter].line = plugin->debug.lines[iter].line;
|
||||
}
|
||||
|
||||
/* relocate arrays */
|
||||
@ -2718,7 +2757,7 @@ jit_rewind:
|
||||
uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
|
||||
|
||||
max = plugin->debug.syms_num;
|
||||
ctx->symbols = new sp_debug_symbol_t[max];
|
||||
plugin->symbols = new sp_debug_symbol_t[max];
|
||||
for (iter=0; iter<max; iter++)
|
||||
{
|
||||
sym = (sp_fdbg_symbol_t *)cursor;
|
||||
@ -2730,52 +2769,48 @@ jit_rewind:
|
||||
*/
|
||||
if (sym->codestart > data->codesize)
|
||||
{
|
||||
ctx->symbols[iter].codestart = 0;
|
||||
plugin->symbols[iter].codestart = 0;
|
||||
} else {
|
||||
ctx->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
|
||||
plugin->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
|
||||
}
|
||||
if (sym->codeend > data->codesize)
|
||||
{
|
||||
ctx->symbols[iter].codeend = data->codesize;
|
||||
plugin->symbols[iter].codeend = data->codesize;
|
||||
} 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;
|
||||
ctx->symbols[iter].sym = sym;
|
||||
plugin->symbols[iter].name = strbase + sym->name;
|
||||
plugin->symbols[iter].sym = sym;
|
||||
|
||||
if (sym->dimcount > 0)
|
||||
{
|
||||
cursor += sizeof(sp_fdbg_symbol_t);
|
||||
arr = (sp_fdbg_arraydim_t *)cursor;
|
||||
ctx->symbols[iter].dims = arr;
|
||||
plugin->symbols[iter].dims = arr;
|
||||
cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
|
||||
continue;
|
||||
}
|
||||
|
||||
ctx->symbols[iter].dims = NULL;
|
||||
plugin->symbols[iter].dims = NULL;
|
||||
cursor += sizeof(sp_fdbg_symbol_t);
|
||||
}
|
||||
}
|
||||
|
||||
tracker_t *trk = new tracker_t;
|
||||
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->pCur = trk->pBase;
|
||||
trk->size = 1024 / sizeof(cell_t);
|
||||
|
||||
functracker_t *fnc = new functracker_t;
|
||||
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 */
|
||||
data->rebase = NULL;
|
||||
AbortCompilation(co);
|
||||
co->Abort();
|
||||
|
||||
*err = SP_ERROR_NONE;
|
||||
|
||||
return ctx;
|
||||
return true;
|
||||
}
|
||||
|
||||
SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
|
||||
@ -2851,126 +2886,146 @@ void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
|
||||
engine->FreePageMemory((void *)func);
|
||||
}
|
||||
|
||||
const char *JITX86::GetVMName()
|
||||
{
|
||||
return "JIT (x86)";
|
||||
}
|
||||
|
||||
int JITX86::ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result)
|
||||
int JITX86::ContextExecute(sp_plugin_t *pl, sp_context_t *ctx, uint32_t code_idx, cell_t *result)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
void JITX86::FreeContext(sp_context_t *ctx)
|
||||
{
|
||||
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)
|
||||
ICompilation *JITX86::StartCompilation()
|
||||
{
|
||||
CompData *data = new CompData;
|
||||
|
||||
data->jit_float_table = NULL;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void CompData::SetRuntime(BaseRuntime *runtime)
|
||||
{
|
||||
uint32_t max_natives = plugin->info.natives_num;
|
||||
const char *strbase = plugin->info.stringbase;
|
||||
|
||||
data->plugin = plugin;
|
||||
data->inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
|
||||
data->error_set = SP_ERROR_NONE;
|
||||
plugin = runtime->m_pPlugin;
|
||||
inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
|
||||
error_set = SP_ERROR_NONE;
|
||||
|
||||
data->jit_float_table = new floattbl_t[max_natives];
|
||||
jit_float_table = new floattbl_t[max_natives];
|
||||
for (uint32_t i=0; i<max_natives; i++)
|
||||
{
|
||||
const char *name = strbase + plugin->info.natives[i].name;
|
||||
if (!strcmp(name, "FloatAbs"))
|
||||
{
|
||||
data->jit_float_table[i].found = true;
|
||||
data->jit_float_table[i].index = OP_FABS;
|
||||
jit_float_table[i].found = true;
|
||||
jit_float_table[i].index = OP_FABS;
|
||||
} else if (!strcmp(name, "FloatAdd")) {
|
||||
data->jit_float_table[i].found = true;
|
||||
data->jit_float_table[i].index = OP_FLOATADD;
|
||||
jit_float_table[i].found = true;
|
||||
jit_float_table[i].index = OP_FLOATADD;
|
||||
} else if (!strcmp(name, "FloatSub")) {
|
||||
data->jit_float_table[i].found = true;
|
||||
data->jit_float_table[i].index = OP_FLOATSUB;
|
||||
jit_float_table[i].found = true;
|
||||
jit_float_table[i].index = OP_FLOATSUB;
|
||||
} else if (!strcmp(name, "FloatMul")) {
|
||||
data->jit_float_table[i].found = true;
|
||||
data->jit_float_table[i].index = OP_FLOATMUL;
|
||||
jit_float_table[i].found = true;
|
||||
jit_float_table[i].index = OP_FLOATMUL;
|
||||
} else if (!strcmp(name, "FloatDiv")) {
|
||||
data->jit_float_table[i].found = true;
|
||||
data->jit_float_table[i].index = OP_FLOATDIV;
|
||||
jit_float_table[i].found = true;
|
||||
jit_float_table[i].index = OP_FLOATDIV;
|
||||
} else if (!strcmp(name, "float")) {
|
||||
data->jit_float_table[i].found = true;
|
||||
data->jit_float_table[i].index = OP_FLOAT;
|
||||
jit_float_table[i].found = true;
|
||||
jit_float_table[i].index = OP_FLOAT;
|
||||
} else if (!strcmp(name, "FloatCompare")) {
|
||||
data->jit_float_table[i].found = true;
|
||||
data->jit_float_table[i].index = OP_FLOATCMP;
|
||||
jit_float_table[i].found = true;
|
||||
jit_float_table[i].index = OP_FLOATCMP;
|
||||
} else if (!strcmp(name, "RoundToZero")) {
|
||||
data->jit_float_table[i].found = true;
|
||||
data->jit_float_table[i].index = OP_RND_TO_ZERO;
|
||||
jit_float_table[i].found = true;
|
||||
jit_float_table[i].index = OP_RND_TO_ZERO;
|
||||
} else if (!strcmp(name, "RoundToCeil")) {
|
||||
data->jit_float_table[i].found = true;
|
||||
data->jit_float_table[i].index = OP_RND_TO_CEIL;
|
||||
jit_float_table[i].found = true;
|
||||
jit_float_table[i].index = OP_RND_TO_CEIL;
|
||||
} else if (!strcmp(name, "RoundToFloor")) {
|
||||
data->jit_float_table[i].found = true;
|
||||
data->jit_float_table[i].index = OP_RND_TO_FLOOR;
|
||||
jit_float_table[i].found = true;
|
||||
jit_float_table[i].index = OP_RND_TO_FLOOR;
|
||||
} else if (!strcmp(name, "RoundToNearest")) {
|
||||
data->jit_float_table[i].found = true;
|
||||
data->jit_float_table[i].index = OP_RND_TO_NEAREST;
|
||||
jit_float_table[i].found = true;
|
||||
jit_float_table[i].index = OP_RND_TO_NEAREST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ICompilation *JITX86::StartCompilation(BaseRuntime *runtime)
|
||||
{
|
||||
CompData *data = new CompData;
|
||||
|
||||
data->SetRuntime(runtime);
|
||||
|
||||
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 (CompData *)co;
|
||||
delete [] jit_float_table;
|
||||
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 ((atoi(val) == 1) || !strcmp(val, "yes"))
|
||||
{
|
||||
data->debug = true;
|
||||
debug = true;
|
||||
} 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 true;
|
||||
}
|
||||
else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
|
||||
{
|
||||
data->profile = atoi(val);
|
||||
profile = atoi(val);
|
||||
|
||||
/** 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;
|
||||
@ -2979,83 +3034,3 @@ bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char
|
||||
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_api.h>
|
||||
#include <jit_helpers.h>
|
||||
#include "../jit_shared.h"
|
||||
#include "../BaseRuntime.h"
|
||||
|
||||
using namespace SourcePawn;
|
||||
|
||||
@ -44,11 +46,14 @@ using namespace SourcePawn;
|
||||
#define JIT_FUNCMAGIC 0x214D4148 //magic function offset
|
||||
|
||||
#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_REBASE 2 //important: hi, i'm bail
|
||||
#define JITVARS_BASECTX 1 //important: don't change this aWOAWOGJQG I LIKE HAM
|
||||
#define JITVARS_PROFILER 2 //profiler
|
||||
#define JITVARS_PLUGIN 3 //sp_plugin_t
|
||||
|
||||
#define sDIMEN_MAX 5 //this must mirror what the compiler has.
|
||||
|
||||
#define GET_CONTEXT(c) ((IPluginContext *)c->vm[JITVARS_BASECTX])
|
||||
|
||||
typedef struct tracker_s
|
||||
{
|
||||
size_t size;
|
||||
@ -87,7 +92,11 @@ public:
|
||||
error_set(SP_ERROR_NONE), func_idx(0)
|
||||
{
|
||||
};
|
||||
bool SetOption(const char *key, const char *val);
|
||||
void SetRuntime(BaseRuntime *runtime);
|
||||
void Abort();
|
||||
public:
|
||||
BaseRuntime *runtime; /* runtime handle */
|
||||
sp_plugin_t *plugin; /* plugin handle */
|
||||
bool debug; /* whether to compile debug mode */
|
||||
int profile; /* profiling flags */
|
||||
@ -116,22 +125,15 @@ public:
|
||||
uint32_t codesize; /* total codesize */
|
||||
};
|
||||
|
||||
class JITX86 : public IVirtualMachine
|
||||
class JITX86
|
||||
{
|
||||
public:
|
||||
const char *GetVMName();
|
||||
ICompilation *StartCompilation(sp_plugin_t *plugin);
|
||||
bool SetCompilationOption(ICompilation *co, const char *key, const char *val);
|
||||
sp_context_t *CompileToContext(ICompilation *co, int *err);
|
||||
void AbortCompilation(ICompilation *co);
|
||||
void FreeContext(sp_context_t *ctx);
|
||||
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();
|
||||
ICompilation *StartCompilation(BaseRuntime *runtime);
|
||||
ICompilation *StartCompilation();
|
||||
bool Compile(ICompilation *co, BaseRuntime *runtime, int *err);
|
||||
void FreePluginVars(sp_plugin_t *pl);
|
||||
void FreeContextVars(sp_context_t *ctx);
|
||||
int ContextExecute(sp_plugin_t *pl, sp_context_t *ctx, uint32_t code_idx, cell_t *result);
|
||||
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
|
||||
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_STACKTOP 16 //relocated
|
||||
|
||||
extern ISourcePawnEngine *engine;
|
||||
extern JITX86 g_Jit1;
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
jitoffs_t Write_Execute_Function(JitWriter *jit)
|
||||
{
|
||||
CompData *co = (CompData *)jit->data;
|
||||
/**
|
||||
* The variables we're passed in:
|
||||
* 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 ecx, [eax+<offs>] - get heap 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_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_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_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 */
|
||||
//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
|
||||
//add ecx, ebp - relocate
|
||||
//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_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_STACKTOP);
|
||||
|
||||
/* 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)
|
||||
//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_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 */
|
||||
//call ecx
|
||||
@ -161,36 +170,30 @@ void Write_BreakDebug(JitWriter *jit)
|
||||
//push edi
|
||||
//mov edi, ecx
|
||||
//mov ecx, [esi+ctx]
|
||||
//cmp [ecx+dbreak], 0
|
||||
//jnz :nocall
|
||||
IA32_Push_Reg(jit, REG_EDI);
|
||||
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_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
|
||||
/* NOTE, Hack! PUSHAD pushes EDI last which still has the CIP */
|
||||
//pushad
|
||||
//push [esi+frm]
|
||||
//push ctx
|
||||
//mov ecx, [ecx+dbreak]
|
||||
//push [ctx+basectx]
|
||||
//mov ecx, <dbreak>
|
||||
//call ecx
|
||||
//add esp, 8
|
||||
//popad
|
||||
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_Reg(jit, AMX_REG_TMP);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_TMP, offsetof(sp_context_t, dbreak));
|
||||
IA32_Push_Rm_Disp8(jit, AMX_REG_TMP, offsetof(sp_context_t, vm[JITVARS_BASECTX]));
|
||||
IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, jit_int32_t(((CompData *)jit->data)->plugin->dbreak));
|
||||
IA32_Call_Reg(jit, AMX_REG_TMP);
|
||||
IA32_Add_Rm_Imm8(jit, REG_ESP, 4*2, MOD_REG);
|
||||
IA32_Popad(jit);
|
||||
|
||||
//:nocall
|
||||
//pop edi
|
||||
//ret
|
||||
IA32_Pop_Reg(jit, REG_EDI);
|
||||
IA32_Send_Jump8_Here(jit, jmp);
|
||||
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 */
|
||||
//cmp <reg>, <stpu>
|
||||
//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);
|
||||
|
||||
/* Part 2: Check if we're in the invalid region between HP and SP */
|
||||
|
Loading…
Reference in New Issue
Block a user