5 #include "BaseRuntime.h"
6 #include "sp_vm_engine.h"
7 #include "x86/jit_x86.h"
8 #include "sp_vm_basecontext.h"
13 using namespace SourcePawn;
15 BaseRuntime::BaseRuntime() : m_Debug(&m_plugin), m_pPlugin(&m_plugin), m_pCtx(NULL),
16 m_PubFuncs(NULL), m_PubJitFuncs(NULL), m_pCo(NULL), m_CompSerial(0)
18 memset(&m_plugin, 0, sizeof(m_plugin));
24 memset(m_CodeHash, 0, sizeof(m_CodeHash));
25 memset(m_DataHash, 0, sizeof(m_DataHash));
28 BaseRuntime::~BaseRuntime()
30 for (uint32_t i = 0; i < m_pPlugin->num_publics; i++)
36 delete [] m_PubJitFuncs;
38 for (unsigned int i = 0; i < m_NumFuncs; i++)
40 delete m_FuncCache[i];
50 free(m_pPlugin->base);
51 delete [] m_pPlugin->memory;
52 delete [] m_pPlugin->publics;
53 delete [] m_pPlugin->pubvars;
54 delete [] m_pPlugin->natives;
55 free(m_pPlugin->name);
58 static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
60 return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
63 int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base)
68 sp_plugin_t *plugin = m_pPlugin;
69 sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
71 memset(plugin, 0, sizeof(sp_plugin_t));
74 plugin->base_size = hdr->imagesize;
75 set_err = SP_ERROR_NONE;
77 if (hdr->version == 0x0101)
79 plugin->debug.unpacked = true;
82 /* We have to read the name section first */
83 for (sectnum = 0; sectnum < hdr->sections; sectnum++)
85 nameptr = (char *)(base + hdr->stringtab + secptr[sectnum].nameoffs);
86 if (strcmp(nameptr, ".names") == 0)
88 plugin->stringbase = (const char *)(base + secptr[sectnum].dataoffs);
95 /* Now read the rest of the sections */
96 while (sectnum < hdr->sections)
98 nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
100 if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
102 sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
104 if (cod->codeversion < SP_CODEVERS_JIT1)
106 return SP_ERROR_CODE_TOO_OLD;
108 else if (cod->codeversion > SP_CODEVERS_JIT2)
110 return SP_ERROR_CODE_TOO_NEW;
113 plugin->pcode = base + secptr->dataoffs + cod->code;
114 plugin->pcode_size = cod->codesize;
115 plugin->flags = cod->flags;
116 plugin->pcode_version = cod->codeversion;
118 else if (!(plugin->data) && !strcmp(nameptr, ".data"))
120 sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
121 plugin->data = base + secptr->dataoffs + dat->data;
122 plugin->data_size = dat->datasize;
123 plugin->mem_size = dat->memsize;
124 plugin->memory = new uint8_t[plugin->mem_size];
125 memcpy(plugin->memory, plugin->data, plugin->data_size);
127 else if ((plugin->publics == NULL) && !strcmp(nameptr, ".publics"))
129 sp_file_publics_t *publics;
131 publics = (sp_file_publics_t *)(base + secptr->dataoffs);
132 plugin->num_publics = secptr->size / sizeof(sp_file_publics_t);
134 if (plugin->num_publics > 0)
136 plugin->publics = new sp_public_t[plugin->num_publics];
138 for (uint32_t i = 0; i < plugin->num_publics; i++)
140 plugin->publics[i].code_offs = publics[i].address;
141 plugin->publics[i].funcid = (i << 1) | 1;
142 plugin->publics[i].name = plugin->stringbase + publics[i].name;
146 else if ((plugin->pubvars == NULL) && !strcmp(nameptr, ".pubvars"))
148 sp_file_pubvars_t *pubvars;
150 pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
151 plugin->num_pubvars = secptr->size / sizeof(sp_file_pubvars_t);
153 if (plugin->num_pubvars > 0)
155 plugin->pubvars = new sp_pubvar_t[plugin->num_pubvars];
157 for (uint32_t i = 0; i < plugin->num_pubvars; i++)
159 plugin->pubvars[i].name = plugin->stringbase + pubvars[i].name;
160 plugin->pubvars[i].offs = (cell_t *)(plugin->memory + pubvars[i].address);
164 else if ((plugin->natives == NULL) && !strcmp(nameptr, ".natives"))
166 sp_file_natives_t *natives;
168 natives = (sp_file_natives_t *)(base + secptr->dataoffs);
169 plugin->num_natives = secptr->size / sizeof(sp_file_natives_t);
171 if (plugin->num_natives > 0)
173 plugin->natives = new sp_native_t[plugin->num_natives];
175 for (uint32_t i = 0; i < plugin->num_natives; i++)
177 plugin->natives[i].flags = 0;
178 plugin->natives[i].pfn = InvalidNative;
179 plugin->natives[i].status = SP_NATIVE_UNBOUND;
180 plugin->natives[i].user = NULL;
181 plugin->natives[i].name = plugin->stringbase + natives[i].name;
185 else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
187 plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
189 else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
191 plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
193 else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
195 plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
197 else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
199 sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
200 plugin->debug.files_num = inf->num_files;
201 plugin->debug.lines_num = inf->num_lines;
202 plugin->debug.syms_num = inf->num_syms;
204 else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
206 plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
208 else if (strcmp(nameptr, ".dbg.natives") == 0)
210 plugin->debug.unpacked = false;
217 if (plugin->pcode == NULL || plugin->data == NULL)
219 return SP_ERROR_FILE_FORMAT;
222 if ((plugin->flags & SP_FLAG_DEBUG) && (
223 !(plugin->debug.files) ||
224 !(plugin->debug.lines) ||
225 !(plugin->debug.symbols) ||
226 !(plugin->debug.stringbase) ))
228 return SP_ERROR_FILE_FORMAT;
231 if (m_pPlugin->num_publics > 0)
233 m_PubFuncs = new CFunction *[m_pPlugin->num_publics];
234 memset(m_PubFuncs, 0, sizeof(CFunction *) * m_pPlugin->num_publics);
235 m_PubJitFuncs = new JitFunction *[m_pPlugin->num_publics];
236 memset(m_PubJitFuncs, 0, sizeof(JitFunction *) * m_pPlugin->num_publics);
240 md5_pcode.update(plugin->pcode, plugin->pcode_size);
241 md5_pcode.finalize();
242 md5_pcode.raw_digest(m_CodeHash);
245 md5_data.update(plugin->data, plugin->data_size);
247 md5_data.raw_digest(m_DataHash);
249 m_pPlugin->profiler = g_engine2.GetProfiler();
250 m_pCtx = new BaseContext(this);
251 m_pCo = g_Jit.StartCompilation(this);
253 return SP_ERROR_NONE;
256 int BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
260 high = m_pPlugin->num_natives - 1;
262 for (uint32_t i=0; i<m_pPlugin->num_natives; i++)
264 if (strcmp(m_pPlugin->natives[i].name, name) == 0)
270 return SP_ERROR_NONE;
274 return SP_ERROR_NOT_FOUND;
277 int BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
279 if (index >= m_pPlugin->num_natives)
281 return SP_ERROR_INDEX;
286 *native = &(m_pPlugin->natives[index]);
289 return SP_ERROR_NONE;
293 uint32_t BaseRuntime::GetNativesNum()
295 return m_pPlugin->num_natives;
298 int BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
303 high = m_pPlugin->num_publics - 1;
308 mid = (low + high) / 2;
309 diff = strcmp(m_pPlugin->publics[mid].name, name);
316 return SP_ERROR_NONE;
317 } else if (diff < 0) {
324 return SP_ERROR_NOT_FOUND;
327 int BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
329 if (index >= m_pPlugin->num_publics)
331 return SP_ERROR_INDEX;
336 *pblic = &(m_pPlugin->publics[index]);
339 return SP_ERROR_NONE;
342 uint32_t BaseRuntime::GetPublicsNum()
344 return m_pPlugin->num_publics;
347 int BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
349 if (index >= m_pPlugin->num_pubvars)
351 return SP_ERROR_INDEX;
356 *pubvar = &(m_pPlugin->pubvars[index]);
359 return SP_ERROR_NONE;
362 int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
367 high = m_pPlugin->num_pubvars - 1;
372 mid = (low + high) / 2;
373 diff = strcmp(m_pPlugin->pubvars[mid].name, name);
380 return SP_ERROR_NONE;
392 return SP_ERROR_NOT_FOUND;
395 int BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
397 if (index >= m_pPlugin->num_pubvars)
399 return SP_ERROR_INDEX;
402 *local_addr = (uint8_t *)m_pPlugin->pubvars[index].offs - m_pPlugin->memory;
403 *phys_addr = m_pPlugin->pubvars[index].offs;
405 return SP_ERROR_NONE;
408 uint32_t BaseRuntime::GetPubVarsNum()
410 return m_pPlugin->num_pubvars;
413 IPluginContext *BaseRuntime::GetDefaultContext()
418 IPluginDebugInfo *BaseRuntime::GetDebugInfo()
423 IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id)
425 CFunction *pFunc = NULL;
430 if (func_id >= m_pPlugin->num_publics)
434 pFunc = m_PubFuncs[func_id];
437 m_PubFuncs[func_id] = new CFunction(this,
440 pFunc = m_PubFuncs[func_id];
447 IPluginFunction *BaseRuntime::GetFunctionByName(const char *public_name)
451 if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
456 CFunction *pFunc = m_PubFuncs[index];
459 sp_public_t *pub = NULL;
460 GetPublicByIndex(index, &pub);
463 m_PubFuncs[index] = new CFunction(this, (index << 1) | 1, index);
465 pFunc = m_PubFuncs[index];
471 bool BaseRuntime::IsDebugging()
476 void BaseRuntime::SetPauseState(bool paused)
480 m_pPlugin->run_flags |= SPFLAG_PLUGIN_PAUSED;
484 m_pPlugin->run_flags &= ~SPFLAG_PLUGIN_PAUSED;
488 bool BaseRuntime::IsPaused()
490 return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
493 size_t BaseRuntime::GetMemUsage()
498 mem += sizeof(sp_plugin_t);
499 mem += sizeof(BaseContext);
500 mem += m_pPlugin->base_size;
505 unsigned char *BaseRuntime::GetCodeHash()
510 unsigned char *BaseRuntime::GetDataHash()
515 BaseContext *BaseRuntime::GetBaseContext()
520 int BaseRuntime::ApplyCompilationOptions(ICompilation *co)
524 return SP_ERROR_NONE;
527 m_pCo = g_Jit.ApplyOptions(m_pCo, co);
528 m_pPlugin->prof_flags = ((CompData *)m_pCo)->profile;
530 return SP_ERROR_NONE;
533 JitFunction *BaseRuntime::GetJittedFunction(uint32_t idx)
535 assert(idx <= m_NumFuncs);
537 if (idx == 0 || idx > m_NumFuncs)
542 return m_FuncCache[idx - 1];
545 uint32_t BaseRuntime::AddJittedFunction(JitFunction *fn)
547 if (m_NumFuncs + 1 > m_MaxFuncs)
558 m_FuncCache = (JitFunction **)realloc(
560 sizeof(JitFunction *) * m_MaxFuncs);
563 m_FuncCache[m_NumFuncs++] = fn;
568 int BaseRuntime::CreateBlank(uint32_t heastk)
570 memset(m_pPlugin, 0, sizeof(sp_plugin_t));
572 /* Align to cell_t bytes */
573 heastk += sizeof(cell_t);
574 heastk -= heastk % sizeof(cell_t);
576 m_pPlugin->mem_size = heastk;
577 m_pPlugin->memory = new uint8_t[heastk];
579 m_pPlugin->profiler = g_engine2.GetProfiler();
580 m_pCtx = new BaseContext(this);
581 m_pCo = g_Jit.StartCompilation(this);
583 return SP_ERROR_NONE;