Updated some CS:GO gamedata.
1 // vim: set ts=8 sts=2 sw=2 tw=99 et:
6 #include "BaseRuntime.h"
7 #include "sp_vm_engine.h"
8 #include "x86/jit_x86.h"
9 #include "sp_vm_basecontext.h"
14 using namespace SourcePawn;
17 IsPointerCellAligned(void *p)
19 return uintptr_t(p) % 4 == 0;
22 BaseRuntime::BaseRuntime()
30 memset(&m_plugin, 0, sizeof(m_plugin));
38 memset(m_CodeHash, 0, sizeof(m_CodeHash));
39 memset(m_DataHash, 0, sizeof(m_DataHash));
42 BaseRuntime::~BaseRuntime()
44 for (uint32_t i = 0; i < m_plugin.num_publics; i++)
47 delete [] m_PubJitFuncs;
48 delete [] float_table_;
49 delete [] function_map_;
52 for (size_t i = 0; i < m_JitFunctions.length(); i++)
53 delete m_JitFunctions[i];
60 delete [] m_plugin.memory;
61 delete [] m_plugin.publics;
62 delete [] m_plugin.pubvars;
63 delete [] m_plugin.natives;
68 BaseRuntime::SetupFloatNativeRemapping()
70 float_table_ = new floattbl_t[m_plugin.num_natives];
71 for (size_t i = 0; i < m_plugin.num_natives; i++) {
72 const char *name = m_plugin.natives[i].name;
73 if (!strcmp(name, "FloatAbs")) {
74 float_table_[i].found = true;
75 float_table_[i].index = OP_FABS;
76 } else if (!strcmp(name, "FloatAdd")) {
77 float_table_[i].found = true;
78 float_table_[i].index = OP_FLOATADD;
79 } else if (!strcmp(name, "FloatSub")) {
80 float_table_[i].found = true;
81 float_table_[i].index = OP_FLOATSUB;
82 } else if (!strcmp(name, "FloatMul")) {
83 float_table_[i].found = true;
84 float_table_[i].index = OP_FLOATMUL;
85 } else if (!strcmp(name, "FloatDiv")) {
86 float_table_[i].found = true;
87 float_table_[i].index = OP_FLOATDIV;
88 } else if (!strcmp(name, "float")) {
89 float_table_[i].found = true;
90 float_table_[i].index = OP_FLOAT;
91 } else if (!strcmp(name, "FloatCompare")) {
92 float_table_[i].found = true;
93 float_table_[i].index = OP_FLOATCMP;
94 } else if (!strcmp(name, "RoundToZero")) {
95 float_table_[i].found = true;
96 float_table_[i].index = OP_RND_TO_ZERO;
97 } else if (!strcmp(name, "RoundToCeil")) {
98 float_table_[i].found = true;
99 float_table_[i].index = OP_RND_TO_CEIL;
100 } else if (!strcmp(name, "RoundToFloor")) {
101 float_table_[i].found = true;
102 float_table_[i].index = OP_RND_TO_FLOOR;
103 } else if (!strcmp(name, "RoundToNearest")) {
104 float_table_[i].found = true;
105 float_table_[i].index = OP_RND_TO_NEAREST;
111 BaseRuntime::GetNativeReplacement(size_t index)
113 if (!float_table_[index].found)
115 return float_table_[index].index;
119 BaseRuntime::SetName(const char *name)
121 m_plugin.name = strdup(name);
124 static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
126 return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
129 int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base)
133 sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
135 memset(&m_plugin, 0, sizeof(m_plugin));
137 m_plugin.base = base;
138 m_plugin.base_size = hdr->imagesize;
140 if (hdr->version == 0x0101)
141 m_plugin.debug.unpacked = true;
143 /* We have to read the name section first */
144 for (sectnum = 0; sectnum < hdr->sections; sectnum++) {
145 nameptr = (char *)(base + hdr->stringtab + secptr[sectnum].nameoffs);
146 if (strcmp(nameptr, ".names") == 0) {
147 m_plugin.stringbase = (const char *)(base + secptr[sectnum].dataoffs);
154 /* Now read the rest of the sections */
155 while (sectnum < hdr->sections) {
156 nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
158 if (!(m_plugin.pcode) && !strcmp(nameptr, ".code")) {
159 sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
161 if (cod->codeversion < SP_CODEVERS_JIT1)
162 return SP_ERROR_CODE_TOO_OLD;
163 if (cod->codeversion > SP_CODEVERS_JIT2)
164 return SP_ERROR_CODE_TOO_NEW;
166 m_plugin.pcode = base + secptr->dataoffs + cod->code;
167 m_plugin.pcode_size = cod->codesize;
168 m_plugin.flags = cod->flags;
169 m_plugin.pcode_version = cod->codeversion;
170 if (!IsPointerCellAligned(m_plugin.pcode)) {
171 // The JIT requires that pcode is cell-aligned, so if it's not, we
172 // remap the code segment to a new address.
173 alt_pcode_ = new uint8_t[m_plugin.pcode_size];
174 memcpy(alt_pcode_, m_plugin.pcode, m_plugin.pcode_size);
175 assert(IsPointerCellAligned(alt_pcode_));
177 m_plugin.pcode = alt_pcode_;
179 } else if (!(m_plugin.data) && !strcmp(nameptr, ".data")) {
180 sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
181 m_plugin.data = base + secptr->dataoffs + dat->data;
182 m_plugin.data_size = dat->datasize;
183 m_plugin.mem_size = dat->memsize;
184 m_plugin.memory = new uint8_t[m_plugin.mem_size];
185 memcpy(m_plugin.memory, m_plugin.data, m_plugin.data_size);
186 } else if ((m_plugin.publics == NULL) && !strcmp(nameptr, ".publics")) {
187 sp_file_publics_t *publics;
189 publics = (sp_file_publics_t *)(base + secptr->dataoffs);
190 m_plugin.num_publics = secptr->size / sizeof(sp_file_publics_t);
192 if (m_plugin.num_publics > 0) {
193 m_plugin.publics = new sp_public_t[m_plugin.num_publics];
195 for (uint32_t i = 0; i < m_plugin.num_publics; i++) {
196 m_plugin.publics[i].code_offs = publics[i].address;
197 m_plugin.publics[i].funcid = (i << 1) | 1;
198 m_plugin.publics[i].name = m_plugin.stringbase + publics[i].name;
201 } else if ((m_plugin.pubvars == NULL) && !strcmp(nameptr, ".pubvars")) {
202 sp_file_pubvars_t *pubvars;
204 pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
205 m_plugin.num_pubvars = secptr->size / sizeof(sp_file_pubvars_t);
207 if (m_plugin.num_pubvars > 0) {
208 m_plugin.pubvars = new sp_pubvar_t[m_plugin.num_pubvars];
210 for (uint32_t i = 0; i < m_plugin.num_pubvars; i++) {
211 m_plugin.pubvars[i].name = m_plugin.stringbase + pubvars[i].name;
212 m_plugin.pubvars[i].offs = (cell_t *)(m_plugin.memory + pubvars[i].address);
215 } else if ((m_plugin.natives == NULL) && !strcmp(nameptr, ".natives")) {
216 sp_file_natives_t *natives;
218 natives = (sp_file_natives_t *)(base + secptr->dataoffs);
219 m_plugin.num_natives = secptr->size / sizeof(sp_file_natives_t);
221 if (m_plugin.num_natives > 0) {
222 m_plugin.natives = new sp_native_t[m_plugin.num_natives];
224 for (uint32_t i = 0; i < m_plugin.num_natives; i++) {
225 m_plugin.natives[i].flags = 0;
226 m_plugin.natives[i].pfn = InvalidNative;
227 m_plugin.natives[i].status = SP_NATIVE_UNBOUND;
228 m_plugin.natives[i].user = NULL;
229 m_plugin.natives[i].name = m_plugin.stringbase + natives[i].name;
232 } else if (!(m_plugin.debug.files) && !strcmp(nameptr, ".dbg.files")) {
233 m_plugin.debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
234 } else if (!(m_plugin.debug.lines) && !strcmp(nameptr, ".dbg.lines")) {
235 m_plugin.debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
236 } else if (!(m_plugin.debug.symbols) && !strcmp(nameptr, ".dbg.symbols")) {
237 m_plugin.debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
238 } else if (!(m_plugin.debug.lines_num) && !strcmp(nameptr, ".dbg.info")) {
239 sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
240 m_plugin.debug.files_num = inf->num_files;
241 m_plugin.debug.lines_num = inf->num_lines;
242 m_plugin.debug.syms_num = inf->num_syms;
243 } else if (!(m_plugin.debug.stringbase) && !strcmp(nameptr, ".dbg.strings")) {
244 m_plugin.debug.stringbase = (const char *)(base + secptr->dataoffs);
245 } else if (strcmp(nameptr, ".dbg.natives") == 0) {
246 m_plugin.debug.unpacked = false;
253 if (m_plugin.pcode == NULL || m_plugin.data == NULL)
254 return SP_ERROR_FILE_FORMAT;
256 if ((m_plugin.flags & SP_FLAG_DEBUG) && (
257 !(m_plugin.debug.files) ||
258 !(m_plugin.debug.lines) ||
259 !(m_plugin.debug.symbols) ||
260 !(m_plugin.debug.stringbase) ))
262 return SP_ERROR_FILE_FORMAT;
265 if (m_plugin.num_publics > 0) {
266 m_PubFuncs = new CFunction *[m_plugin.num_publics];
267 memset(m_PubFuncs, 0, sizeof(CFunction *) * m_plugin.num_publics);
268 m_PubJitFuncs = new JitFunction *[m_plugin.num_publics];
269 memset(m_PubJitFuncs, 0, sizeof(JitFunction *) * m_plugin.num_publics);
273 md5_pcode.update(m_plugin.pcode, m_plugin.pcode_size);
274 md5_pcode.finalize();
275 md5_pcode.raw_digest(m_CodeHash);
278 md5_data.update(m_plugin.data, m_plugin.data_size);
280 md5_data.raw_digest(m_DataHash);
282 m_plugin.profiler = g_engine2.GetProfiler();
283 m_pCtx = new BaseContext(this);
284 co_ = g_Jit.StartCompilation(this);
286 SetupFloatNativeRemapping();
287 function_map_size_ = m_plugin.pcode_size / sizeof(cell_t) + 1;
288 function_map_ = new JitFunction *[function_map_size_];
289 memset(function_map_, 0, function_map_size_ * sizeof(JitFunction *));
291 return SP_ERROR_NONE;
295 BaseRuntime::AddJittedFunction(JitFunction *fn)
297 m_JitFunctions.append(fn);
299 cell_t pcode_offset = fn->GetPCodeAddress();
300 assert(pcode_offset % 4 == 0);
302 uint32_t pcode_index = pcode_offset / 4;
303 assert(pcode_index < function_map_size_);
305 function_map_[pcode_index] = fn;
309 BaseRuntime::GetJittedFunctionByOffset(cell_t pcode_offset)
311 assert(pcode_offset % 4 == 0);
313 uint32_t pcode_index = pcode_offset / 4;
314 assert(pcode_index < function_map_size_);
316 return function_map_[pcode_index];
320 BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
322 for (uint32_t i=0; i<m_plugin.num_natives; i++) {
323 if (strcmp(m_plugin.natives[i].name, name) == 0) {
326 return SP_ERROR_NONE;
330 return SP_ERROR_NOT_FOUND;
334 BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
336 if (index >= m_plugin.num_natives)
337 return SP_ERROR_INDEX;
340 *native = &(m_plugin.natives[index]);
342 return SP_ERROR_NONE;
347 BaseRuntime::GetNativesNum()
349 return m_plugin.num_natives;
353 BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
358 high = m_plugin.num_publics - 1;
361 while (low <= high) {
362 mid = (low + high) / 2;
363 diff = strcmp(m_plugin.publics[mid].name, name);
367 return SP_ERROR_NONE;
368 } else if (diff < 0) {
375 return SP_ERROR_NOT_FOUND;
379 BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
381 if (index >= m_plugin.num_publics)
382 return SP_ERROR_INDEX;
385 *pblic = &(m_plugin.publics[index]);
387 return SP_ERROR_NONE;
391 BaseRuntime::GetPublicsNum()
393 return m_plugin.num_publics;
397 BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
399 if (index >= m_plugin.num_pubvars)
400 return SP_ERROR_INDEX;
403 *pubvar = &(m_plugin.pubvars[index]);
405 return SP_ERROR_NONE;
409 BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
414 high = m_plugin.num_pubvars - 1;
417 while (low <= high) {
418 mid = (low + high) / 2;
419 diff = strcmp(m_plugin.pubvars[mid].name, name);
423 return SP_ERROR_NONE;
424 } else if (diff < 0) {
431 return SP_ERROR_NOT_FOUND;
435 BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
437 if (index >= m_plugin.num_pubvars)
438 return SP_ERROR_INDEX;
440 *local_addr = (uint8_t *)m_plugin.pubvars[index].offs - m_plugin.memory;
441 *phys_addr = m_plugin.pubvars[index].offs;
443 return SP_ERROR_NONE;
447 BaseRuntime::GetPubVarsNum()
449 return m_plugin.num_pubvars;
453 BaseRuntime::GetDefaultContext()
459 BaseRuntime::GetDebugInfo()
465 BaseRuntime::GetFunctionById(funcid_t func_id)
467 CFunction *pFunc = NULL;
471 if (func_id >= m_plugin.num_publics)
473 pFunc = m_PubFuncs[func_id];
475 m_PubFuncs[func_id] = new CFunction(this,
478 pFunc = m_PubFuncs[func_id];
486 BaseRuntime::GetFunctionByName(const char *public_name)
490 if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
493 CFunction *pFunc = m_PubFuncs[index];
495 sp_public_t *pub = NULL;
496 GetPublicByIndex(index, &pub);
498 m_PubFuncs[index] = new CFunction(this, (index << 1) | 1, index);
499 pFunc = m_PubFuncs[index];
505 bool BaseRuntime::IsDebugging()
510 void BaseRuntime::SetPauseState(bool paused)
514 m_plugin.run_flags |= SPFLAG_PLUGIN_PAUSED;
518 m_plugin.run_flags &= ~SPFLAG_PLUGIN_PAUSED;
522 bool BaseRuntime::IsPaused()
524 return ((m_plugin.run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
527 size_t BaseRuntime::GetMemUsage()
532 mem += sizeof(sp_plugin_t);
533 mem += sizeof(BaseContext);
534 mem += m_plugin.base_size;
539 unsigned char *BaseRuntime::GetCodeHash()
544 unsigned char *BaseRuntime::GetDataHash()
549 BaseContext *BaseRuntime::GetBaseContext()
555 BaseRuntime::ApplyCompilationOptions(ICompilation *co)
558 return SP_ERROR_NONE;
560 co_ = g_Jit.ApplyOptions(co_, co);
561 m_plugin.prof_flags = ((CompData *)co_)->profile;
563 return SP_ERROR_NONE;
567 BaseRuntime::CreateBlank(uint32_t heastk)
569 memset(&m_plugin, 0, sizeof(m_plugin));
571 /* Align to cell_t bytes */
572 heastk += sizeof(cell_t);
573 heastk -= heastk % sizeof(cell_t);
575 m_plugin.mem_size = heastk;
576 m_plugin.memory = new uint8_t[heastk];
578 m_plugin.profiler = g_engine2.GetProfiler();
579 m_pCtx = new BaseContext(this);
580 co_ = g_Jit.StartCompilation(this);
582 return SP_ERROR_NONE;