2015-02-24 01:40:36 +01:00
|
|
|
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
|
|
|
//
|
|
|
|
// Copyright (C) 2006-2015 AlliedModders LLC
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
// the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License along with
|
|
|
|
// SourcePawn. If not, see http://www.gnu.org/licenses/.
|
|
|
|
//
|
2008-07-11 10:18:43 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2008-08-15 07:22:26 +02:00
|
|
|
#include <assert.h>
|
2015-02-24 01:44:15 +01:00
|
|
|
#include "plugin-runtime.h"
|
2008-07-11 10:18:43 +02:00
|
|
|
#include "x86/jit_x86.h"
|
2015-02-24 21:55:00 +01:00
|
|
|
#include "plugin-context.h"
|
2015-02-24 08:49:39 +01:00
|
|
|
#include "environment.h"
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2012-08-09 02:54:43 +02:00
|
|
|
#include "md5/md5.h"
|
|
|
|
|
2014-08-22 07:16:07 +02:00
|
|
|
using namespace sp;
|
2008-07-11 10:18:43 +02:00
|
|
|
using namespace SourcePawn;
|
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
static inline bool
|
|
|
|
IsPointerCellAligned(void *p)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return uintptr_t(p) % 4 == 0;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::PluginRuntime()
|
2013-08-08 18:41:24 +02:00
|
|
|
: m_Debug(&m_plugin),
|
|
|
|
m_pCtx(NULL),
|
|
|
|
m_PubFuncs(NULL),
|
|
|
|
m_PubJitFuncs(NULL),
|
|
|
|
m_CompSerial(0)
|
|
|
|
{
|
|
|
|
memset(&m_plugin, 0, sizeof(m_plugin));
|
|
|
|
|
|
|
|
m_MaxFuncs = 0;
|
|
|
|
m_NumFuncs = 0;
|
|
|
|
float_table_ = NULL;
|
|
|
|
function_map_ = NULL;
|
|
|
|
alt_pcode_ = NULL;
|
|
|
|
|
|
|
|
memset(m_CodeHash, 0, sizeof(m_CodeHash));
|
|
|
|
memset(m_DataHash, 0, sizeof(m_DataHash));
|
2013-08-15 08:54:25 +02:00
|
|
|
|
2015-02-24 08:49:39 +01:00
|
|
|
ke::AutoLock lock(Environment::get()->lock());
|
|
|
|
Environment::get()->RegisterRuntime(this);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::~PluginRuntime()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-15 08:54:25 +02:00
|
|
|
// The watchdog thread takes the global JIT lock while it patches all
|
|
|
|
// runtimes. It is not enough to ensure that the unlinking of the runtime is
|
|
|
|
// protected; we cannot delete functions or code while the watchdog might be
|
|
|
|
// executing. Therefore, the entire destructor is guarded.
|
2015-02-24 08:49:39 +01:00
|
|
|
ke::AutoLock lock(Environment::get()->lock());
|
2013-08-15 08:54:25 +02:00
|
|
|
|
2015-02-24 08:49:39 +01:00
|
|
|
Environment::get()->DeregisterRuntime(this);
|
2013-08-15 08:54:25 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
for (uint32_t i = 0; i < m_plugin.num_publics; i++)
|
|
|
|
delete m_PubFuncs[i];
|
|
|
|
delete [] m_PubFuncs;
|
|
|
|
delete [] m_PubJitFuncs;
|
|
|
|
delete [] float_table_;
|
|
|
|
delete [] function_map_;
|
|
|
|
delete [] alt_pcode_;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < m_JitFunctions.length(); i++)
|
|
|
|
delete m_JitFunctions[i];
|
|
|
|
|
|
|
|
delete m_pCtx;
|
|
|
|
|
|
|
|
free(m_plugin.base);
|
|
|
|
delete [] m_plugin.memory;
|
|
|
|
delete [] m_plugin.publics;
|
|
|
|
delete [] m_plugin.pubvars;
|
|
|
|
delete [] m_plugin.natives;
|
|
|
|
free(m_plugin.name);
|
|
|
|
}
|
|
|
|
|
2014-04-23 04:40:45 +02:00
|
|
|
struct NativeMapping {
|
|
|
|
const char *name;
|
|
|
|
unsigned opcode;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const NativeMapping sNativeMap[] = {
|
|
|
|
{ "FloatAbs", OP_FABS },
|
|
|
|
{ "FloatAdd", OP_FLOATADD },
|
|
|
|
{ "FloatSub", OP_FLOATSUB },
|
|
|
|
{ "FloatMul", OP_FLOATMUL },
|
|
|
|
{ "FloatDiv", OP_FLOATDIV },
|
|
|
|
{ "float", OP_FLOAT },
|
|
|
|
{ "FloatCompare", OP_FLOATCMP },
|
|
|
|
{ "RoundToCeil", OP_RND_TO_CEIL },
|
|
|
|
{ "RoundToZero", OP_RND_TO_ZERO },
|
|
|
|
{ "RoundToFloor", OP_RND_TO_FLOOR },
|
|
|
|
{ "RoundToNearest", OP_RND_TO_NEAREST },
|
|
|
|
{ "__FLOAT_GT__", OP_FLOAT_GT },
|
|
|
|
{ "__FLOAT_GE__", OP_FLOAT_GE },
|
|
|
|
{ "__FLOAT_LT__", OP_FLOAT_LT },
|
|
|
|
{ "__FLOAT_LE__", OP_FLOAT_LE },
|
|
|
|
{ "__FLOAT_EQ__", OP_FLOAT_EQ },
|
|
|
|
{ "__FLOAT_NE__", OP_FLOAT_NE },
|
|
|
|
{ "__FLOAT_NOT__", OP_FLOAT_NOT },
|
|
|
|
{ NULL, 0 },
|
|
|
|
};
|
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
void
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::SetupFloatNativeRemapping()
|
2013-08-08 18:41:24 +02:00
|
|
|
{
|
|
|
|
float_table_ = new floattbl_t[m_plugin.num_natives];
|
|
|
|
for (size_t i = 0; i < m_plugin.num_natives; i++) {
|
|
|
|
const char *name = m_plugin.natives[i].name;
|
2014-04-23 04:40:45 +02:00
|
|
|
const NativeMapping *iter = sNativeMap;
|
|
|
|
while (iter->name) {
|
|
|
|
if (strcmp(name, iter->name) == 0) {
|
|
|
|
float_table_[i].found = true;
|
|
|
|
float_table_[i].index = iter->opcode;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
iter++;
|
2013-08-08 18:41:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetNativeReplacement(size_t index)
|
2013-08-08 18:41:24 +02:00
|
|
|
{
|
|
|
|
if (!float_table_[index].found)
|
|
|
|
return OP_NOP;
|
|
|
|
return float_table_[index].index;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::SetName(const char *name)
|
2013-08-08 18:41:24 +02:00
|
|
|
{
|
|
|
|
m_plugin.name = strdup(name);
|
2008-08-15 07:22:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
|
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-24 01:40:36 +01:00
|
|
|
int PluginRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
char *nameptr;
|
|
|
|
uint8_t sectnum = 0;
|
|
|
|
sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
|
|
|
|
|
|
|
|
memset(&m_plugin, 0, sizeof(m_plugin));
|
|
|
|
|
|
|
|
m_plugin.base = base;
|
|
|
|
m_plugin.base_size = hdr->imagesize;
|
|
|
|
|
|
|
|
if (hdr->version == 0x0101)
|
|
|
|
m_plugin.debug.unpacked = true;
|
|
|
|
|
|
|
|
/* We have to read the name section first */
|
|
|
|
for (sectnum = 0; sectnum < hdr->sections; sectnum++) {
|
|
|
|
nameptr = (char *)(base + hdr->stringtab + secptr[sectnum].nameoffs);
|
|
|
|
if (strcmp(nameptr, ".names") == 0) {
|
|
|
|
m_plugin.stringbase = (const char *)(base + secptr[sectnum].dataoffs);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sectnum = 0;
|
|
|
|
|
|
|
|
/* Now read the rest of the sections */
|
|
|
|
while (sectnum < hdr->sections) {
|
|
|
|
nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
|
|
|
|
|
|
|
|
if (!(m_plugin.pcode) && !strcmp(nameptr, ".code")) {
|
|
|
|
sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
|
|
|
|
|
2014-08-24 04:26:51 +02:00
|
|
|
if (cod->codeversion < SmxConsts::CODE_VERSION_SP1_MIN)
|
2013-08-08 18:41:24 +02:00
|
|
|
return SP_ERROR_CODE_TOO_OLD;
|
2014-08-24 04:26:51 +02:00
|
|
|
if (cod->codeversion > SmxConsts::CODE_VERSION_SP1_MAX)
|
2013-08-08 18:41:24 +02:00
|
|
|
return SP_ERROR_CODE_TOO_NEW;
|
|
|
|
|
|
|
|
m_plugin.pcode = base + secptr->dataoffs + cod->code;
|
|
|
|
m_plugin.pcode_size = cod->codesize;
|
|
|
|
m_plugin.flags = cod->flags;
|
|
|
|
m_plugin.pcode_version = cod->codeversion;
|
|
|
|
if (!IsPointerCellAligned(m_plugin.pcode)) {
|
|
|
|
// The JIT requires that pcode is cell-aligned, so if it's not, we
|
|
|
|
// remap the code segment to a new address.
|
|
|
|
alt_pcode_ = new uint8_t[m_plugin.pcode_size];
|
|
|
|
memcpy(alt_pcode_, m_plugin.pcode, m_plugin.pcode_size);
|
|
|
|
assert(IsPointerCellAligned(alt_pcode_));
|
|
|
|
|
|
|
|
m_plugin.pcode = alt_pcode_;
|
|
|
|
}
|
|
|
|
} else if (!(m_plugin.data) && !strcmp(nameptr, ".data")) {
|
|
|
|
sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
|
|
|
|
m_plugin.data = base + secptr->dataoffs + dat->data;
|
|
|
|
m_plugin.data_size = dat->datasize;
|
|
|
|
m_plugin.mem_size = dat->memsize;
|
|
|
|
m_plugin.memory = new uint8_t[m_plugin.mem_size];
|
|
|
|
memcpy(m_plugin.memory, m_plugin.data, m_plugin.data_size);
|
|
|
|
} else if ((m_plugin.publics == NULL) && !strcmp(nameptr, ".publics")) {
|
|
|
|
sp_file_publics_t *publics;
|
|
|
|
|
|
|
|
publics = (sp_file_publics_t *)(base + secptr->dataoffs);
|
|
|
|
m_plugin.num_publics = secptr->size / sizeof(sp_file_publics_t);
|
|
|
|
|
|
|
|
if (m_plugin.num_publics > 0) {
|
|
|
|
m_plugin.publics = new sp_public_t[m_plugin.num_publics];
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < m_plugin.num_publics; i++) {
|
|
|
|
m_plugin.publics[i].code_offs = publics[i].address;
|
|
|
|
m_plugin.publics[i].funcid = (i << 1) | 1;
|
|
|
|
m_plugin.publics[i].name = m_plugin.stringbase + publics[i].name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ((m_plugin.pubvars == NULL) && !strcmp(nameptr, ".pubvars")) {
|
|
|
|
sp_file_pubvars_t *pubvars;
|
|
|
|
|
|
|
|
pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
|
|
|
|
m_plugin.num_pubvars = secptr->size / sizeof(sp_file_pubvars_t);
|
|
|
|
|
|
|
|
if (m_plugin.num_pubvars > 0) {
|
|
|
|
m_plugin.pubvars = new sp_pubvar_t[m_plugin.num_pubvars];
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < m_plugin.num_pubvars; i++) {
|
|
|
|
m_plugin.pubvars[i].name = m_plugin.stringbase + pubvars[i].name;
|
|
|
|
m_plugin.pubvars[i].offs = (cell_t *)(m_plugin.memory + pubvars[i].address);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ((m_plugin.natives == NULL) && !strcmp(nameptr, ".natives")) {
|
|
|
|
sp_file_natives_t *natives;
|
|
|
|
|
|
|
|
natives = (sp_file_natives_t *)(base + secptr->dataoffs);
|
|
|
|
m_plugin.num_natives = secptr->size / sizeof(sp_file_natives_t);
|
|
|
|
|
|
|
|
if (m_plugin.num_natives > 0) {
|
|
|
|
m_plugin.natives = new sp_native_t[m_plugin.num_natives];
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < m_plugin.num_natives; i++) {
|
|
|
|
m_plugin.natives[i].flags = 0;
|
|
|
|
m_plugin.natives[i].pfn = InvalidNative;
|
|
|
|
m_plugin.natives[i].status = SP_NATIVE_UNBOUND;
|
|
|
|
m_plugin.natives[i].user = NULL;
|
|
|
|
m_plugin.natives[i].name = m_plugin.stringbase + natives[i].name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (!(m_plugin.debug.files) && !strcmp(nameptr, ".dbg.files")) {
|
|
|
|
m_plugin.debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
|
|
|
|
} else if (!(m_plugin.debug.lines) && !strcmp(nameptr, ".dbg.lines")) {
|
|
|
|
m_plugin.debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
|
|
|
|
} else if (!(m_plugin.debug.symbols) && !strcmp(nameptr, ".dbg.symbols")) {
|
|
|
|
m_plugin.debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
|
|
|
|
} else if (!(m_plugin.debug.lines_num) && !strcmp(nameptr, ".dbg.info")) {
|
|
|
|
sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
|
|
|
|
m_plugin.debug.files_num = inf->num_files;
|
|
|
|
m_plugin.debug.lines_num = inf->num_lines;
|
|
|
|
m_plugin.debug.syms_num = inf->num_syms;
|
|
|
|
} else if (!(m_plugin.debug.stringbase) && !strcmp(nameptr, ".dbg.strings")) {
|
|
|
|
m_plugin.debug.stringbase = (const char *)(base + secptr->dataoffs);
|
|
|
|
} else if (strcmp(nameptr, ".dbg.natives") == 0) {
|
|
|
|
m_plugin.debug.unpacked = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
secptr++;
|
|
|
|
sectnum++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_plugin.pcode == NULL || m_plugin.data == NULL)
|
|
|
|
return SP_ERROR_FILE_FORMAT;
|
|
|
|
|
2014-08-22 07:16:07 +02:00
|
|
|
if ((m_plugin.flags & sp::CODEFLAG_DEBUG) && (
|
2013-08-08 18:41:24 +02:00
|
|
|
!(m_plugin.debug.files) ||
|
|
|
|
!(m_plugin.debug.lines) ||
|
|
|
|
!(m_plugin.debug.symbols) ||
|
|
|
|
!(m_plugin.debug.stringbase) ))
|
|
|
|
{
|
|
|
|
return SP_ERROR_FILE_FORMAT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_plugin.num_publics > 0) {
|
2015-02-24 00:47:47 +01:00
|
|
|
m_PubFuncs = new ScriptedInvoker *[m_plugin.num_publics];
|
|
|
|
memset(m_PubFuncs, 0, sizeof(ScriptedInvoker *) * m_plugin.num_publics);
|
2015-02-24 01:27:57 +01:00
|
|
|
m_PubJitFuncs = new CompiledFunction *[m_plugin.num_publics];
|
|
|
|
memset(m_PubJitFuncs, 0, sizeof(CompiledFunction *) * m_plugin.num_publics);
|
2013-08-08 18:41:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
MD5 md5_pcode;
|
|
|
|
md5_pcode.update(m_plugin.pcode, m_plugin.pcode_size);
|
|
|
|
md5_pcode.finalize();
|
|
|
|
md5_pcode.raw_digest(m_CodeHash);
|
|
|
|
|
|
|
|
MD5 md5_data;
|
|
|
|
md5_data.update(m_plugin.data, m_plugin.data_size);
|
|
|
|
md5_data.finalize();
|
|
|
|
md5_data.raw_digest(m_DataHash);
|
|
|
|
|
2015-02-24 21:50:09 +01:00
|
|
|
m_pCtx = new PluginContext(this);
|
2013-08-08 18:41:24 +02:00
|
|
|
|
|
|
|
SetupFloatNativeRemapping();
|
|
|
|
function_map_size_ = m_plugin.pcode_size / sizeof(cell_t) + 1;
|
2015-02-24 01:27:57 +01:00
|
|
|
function_map_ = new CompiledFunction *[function_map_size_];
|
|
|
|
memset(function_map_, 0, function_map_size_ * sizeof(CompiledFunction *));
|
2013-08-08 18:41:24 +02:00
|
|
|
|
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
void
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::AddJittedFunction(CompiledFunction *fn)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
m_JitFunctions.append(fn);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-24 00:47:47 +01:00
|
|
|
cell_t pcode_offset = fn->GetCodeOffset();
|
2013-08-08 18:41:24 +02:00
|
|
|
assert(pcode_offset % 4 == 0);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
uint32_t pcode_index = pcode_offset / 4;
|
|
|
|
assert(pcode_index < function_map_size_);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
function_map_[pcode_index] = fn;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-24 01:27:57 +01:00
|
|
|
CompiledFunction *
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetJittedFunctionByOffset(cell_t pcode_offset)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
assert(pcode_offset % 4 == 0);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
uint32_t pcode_index = pcode_offset / 4;
|
|
|
|
assert(pcode_index < function_map_size_);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
return function_map_[pcode_index];
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
int
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::FindNativeByName(const char *name, uint32_t *index)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
for (uint32_t i=0; i<m_plugin.num_natives; i++) {
|
|
|
|
if (strcmp(m_plugin.natives[i].name, name) == 0) {
|
|
|
|
if (index)
|
|
|
|
*index = i;
|
|
|
|
return SP_ERROR_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SP_ERROR_NOT_FOUND;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
int
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
if (index >= m_plugin.num_natives)
|
|
|
|
return SP_ERROR_INDEX;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
if (native)
|
|
|
|
*native = &(m_plugin.natives[index]);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2014-05-11 23:36:32 +02:00
|
|
|
sp_native_t *
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetNativeByIndex(uint32_t index)
|
2014-05-11 23:36:32 +02:00
|
|
|
{
|
|
|
|
assert(index < m_plugin.num_natives);
|
|
|
|
return &m_plugin.natives[index];
|
|
|
|
}
|
2013-08-08 18:41:24 +02:00
|
|
|
|
|
|
|
uint32_t
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetNativesNum()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return m_plugin.num_natives;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
int
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::FindPublicByName(const char *name, uint32_t *index)
|
2013-08-08 18:41:24 +02:00
|
|
|
{
|
|
|
|
int diff, high, low;
|
|
|
|
uint32_t mid;
|
|
|
|
|
|
|
|
high = m_plugin.num_publics - 1;
|
|
|
|
low = 0;
|
|
|
|
|
|
|
|
while (low <= high) {
|
|
|
|
mid = (low + high) / 2;
|
|
|
|
diff = strcmp(m_plugin.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;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
int
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
|
2013-08-08 18:41:24 +02:00
|
|
|
{
|
|
|
|
if (index >= m_plugin.num_publics)
|
|
|
|
return SP_ERROR_INDEX;
|
|
|
|
|
|
|
|
if (pblic)
|
|
|
|
*pblic = &(m_plugin.publics[index]);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
uint32_t
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetPublicsNum()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return m_plugin.num_publics;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
int
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
|
2013-08-08 18:41:24 +02:00
|
|
|
{
|
|
|
|
if (index >= m_plugin.num_pubvars)
|
|
|
|
return SP_ERROR_INDEX;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
if (pubvar)
|
|
|
|
*pubvar = &(m_plugin.pubvars[index]);
|
|
|
|
|
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
int
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::FindPubvarByName(const char *name, uint32_t *index)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
int diff, high, low;
|
|
|
|
uint32_t mid;
|
|
|
|
|
|
|
|
high = m_plugin.num_pubvars - 1;
|
|
|
|
low = 0;
|
|
|
|
|
|
|
|
while (low <= high) {
|
|
|
|
mid = (low + high) / 2;
|
|
|
|
diff = strcmp(m_plugin.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;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
int
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
if (index >= m_plugin.num_pubvars)
|
|
|
|
return SP_ERROR_INDEX;
|
|
|
|
|
|
|
|
*local_addr = (uint8_t *)m_plugin.pubvars[index].offs - m_plugin.memory;
|
|
|
|
*phys_addr = m_plugin.pubvars[index].offs;
|
|
|
|
|
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
uint32_t
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetPubVarsNum()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return m_plugin.num_pubvars;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
IPluginContext *
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetDefaultContext()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return m_pCtx;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
IPluginDebugInfo *
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetDebugInfo()
|
2013-08-08 18:41:24 +02:00
|
|
|
{
|
|
|
|
return &m_Debug;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
IPluginFunction *
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetFunctionById(funcid_t func_id)
|
2013-08-08 18:41:24 +02:00
|
|
|
{
|
2015-02-24 00:47:47 +01:00
|
|
|
ScriptedInvoker *pFunc = NULL;
|
2013-08-08 18:41:24 +02:00
|
|
|
|
|
|
|
if (func_id & 1) {
|
|
|
|
func_id >>= 1;
|
|
|
|
if (func_id >= m_plugin.num_publics)
|
|
|
|
return NULL;
|
|
|
|
pFunc = m_PubFuncs[func_id];
|
|
|
|
if (!pFunc) {
|
2015-02-24 00:47:47 +01:00
|
|
|
m_PubFuncs[func_id] = new ScriptedInvoker(this, (func_id << 1) | 1, func_id);
|
2013-08-08 18:41:24 +02:00
|
|
|
pFunc = m_PubFuncs[func_id];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pFunc;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-24 00:47:47 +01:00
|
|
|
ScriptedInvoker *
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetPublicFunction(size_t index)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-24 00:47:47 +01:00
|
|
|
ScriptedInvoker *pFunc = m_PubFuncs[index];
|
2013-08-08 18:41:24 +02:00
|
|
|
if (!pFunc) {
|
|
|
|
sp_public_t *pub = NULL;
|
|
|
|
GetPublicByIndex(index, &pub);
|
|
|
|
if (pub)
|
2015-02-24 00:47:47 +01:00
|
|
|
m_PubFuncs[index] = new ScriptedInvoker(this, (index << 1) | 1, index);
|
2013-08-08 18:41:24 +02:00
|
|
|
pFunc = m_PubFuncs[index];
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
return pFunc;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2014-06-24 10:04:13 +02:00
|
|
|
IPluginFunction *
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::GetFunctionByName(const char *public_name)
|
2014-06-24 10:04:13 +02:00
|
|
|
{
|
|
|
|
uint32_t index;
|
|
|
|
|
|
|
|
if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return GetPublicFunction(index);
|
|
|
|
}
|
|
|
|
|
2015-02-24 01:40:36 +01:00
|
|
|
bool PluginRuntime::IsDebugging()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return true;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-24 01:40:36 +01:00
|
|
|
void PluginRuntime::SetPauseState(bool paused)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
if (paused)
|
|
|
|
{
|
|
|
|
m_plugin.run_flags |= SPFLAG_PLUGIN_PAUSED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_plugin.run_flags &= ~SPFLAG_PLUGIN_PAUSED;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-24 01:40:36 +01:00
|
|
|
bool PluginRuntime::IsPaused()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return ((m_plugin.run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-24 01:40:36 +01:00
|
|
|
size_t PluginRuntime::GetMemUsage()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
size_t mem = 0;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
mem += sizeof(this);
|
|
|
|
mem += sizeof(sp_plugin_t);
|
2015-02-24 21:50:09 +01:00
|
|
|
mem += sizeof(PluginContext);
|
2013-08-08 18:41:24 +02:00
|
|
|
mem += m_plugin.base_size;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
return mem;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-24 01:40:36 +01:00
|
|
|
unsigned char *PluginRuntime::GetCodeHash()
|
2012-08-09 02:54:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return m_CodeHash;
|
2012-08-09 02:54:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-24 01:40:36 +01:00
|
|
|
unsigned char *PluginRuntime::GetDataHash()
|
2012-08-09 02:54:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return m_DataHash;
|
2012-08-09 02:54:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext *PluginRuntime::GetBaseContext()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return m_pCtx;
|
2008-08-15 07:22:26 +02:00
|
|
|
}
|
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
int
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::ApplyCompilationOptions(ICompilation *co)
|
2008-08-15 07:22:26 +02:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
return SP_ERROR_NONE;
|
2008-08-15 07:22:26 +02:00
|
|
|
}
|
2009-02-01 08:03:03 +01:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
int
|
2015-02-24 01:40:36 +01:00
|
|
|
PluginRuntime::CreateBlank(uint32_t heastk)
|
2009-02-01 08:03:03 +01:00
|
|
|
{
|
2013-08-08 18:41:24 +02:00
|
|
|
memset(&m_plugin, 0, sizeof(m_plugin));
|
2009-02-01 08:03:03 +01:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
/* Align to cell_t bytes */
|
|
|
|
heastk += sizeof(cell_t);
|
|
|
|
heastk -= heastk % sizeof(cell_t);
|
2009-02-01 08:03:03 +01:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
m_plugin.mem_size = heastk;
|
|
|
|
m_plugin.memory = new uint8_t[heastk];
|
2009-02-01 08:03:03 +01:00
|
|
|
|
2015-02-24 21:50:09 +01:00
|
|
|
m_pCtx = new PluginContext(this);
|
2009-02-01 08:03:03 +01:00
|
|
|
|
2013-08-08 18:41:24 +02:00
|
|
|
return SP_ERROR_NONE;
|
2009-02-01 08:03:03 +01:00
|
|
|
}
|