Update CS:GO team score 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));
41 ke::AutoLock lock(g_Jit.Mutex());
42 g_Jit.RegisterRuntime(this);
45 BaseRuntime::~BaseRuntime()
47 // The watchdog thread takes the global JIT lock while it patches all
48 // runtimes. It is not enough to ensure that the unlinking of the runtime is
49 // protected; we cannot delete functions or code while the watchdog might be
50 // executing. Therefore, the entire destructor is guarded.
51 ke::AutoLock lock(g_Jit.Mutex());
53 g_Jit.DeregisterRuntime(this);
55 for (uint32_t i = 0; i < m_plugin.num_publics; i++)
58 delete [] m_PubJitFuncs;
59 delete [] float_table_;
60 delete [] function_map_;
63 for (size_t i = 0; i < m_JitFunctions.length(); i++)
64 delete m_JitFunctions[i];
71 delete [] m_plugin.memory;
72 delete [] m_plugin.publics;
73 delete [] m_plugin.pubvars;
74 delete [] m_plugin.natives;
78 struct NativeMapping {
83 static const NativeMapping sNativeMap[] = {
84 { "FloatAbs", OP_FABS },
85 { "FloatAdd", OP_FLOATADD },
86 { "FloatSub", OP_FLOATSUB },
87 { "FloatMul", OP_FLOATMUL },
88 { "FloatDiv", OP_FLOATDIV },
89 { "float", OP_FLOAT },
90 { "FloatCompare", OP_FLOATCMP },
91 { "RoundToCeil", OP_RND_TO_CEIL },
92 { "RoundToZero", OP_RND_TO_ZERO },
93 { "RoundToFloor", OP_RND_TO_FLOOR },
94 { "RoundToNearest", OP_RND_TO_NEAREST },
95 { "__FLOAT_GT__", OP_FLOAT_GT },
96 { "__FLOAT_GE__", OP_FLOAT_GE },
97 { "__FLOAT_LT__", OP_FLOAT_LT },
98 { "__FLOAT_LE__", OP_FLOAT_LE },
99 { "__FLOAT_EQ__", OP_FLOAT_EQ },
100 { "__FLOAT_NE__", OP_FLOAT_NE },
101 { "__FLOAT_NOT__", OP_FLOAT_NOT },
106 BaseRuntime::SetupFloatNativeRemapping()
108 float_table_ = new floattbl_t[m_plugin.num_natives];
109 for (size_t i = 0; i < m_plugin.num_natives; i++) {
110 const char *name = m_plugin.natives[i].name;
111 const NativeMapping *iter = sNativeMap;
113 if (strcmp(name, iter->name) == 0) {
114 float_table_[i].found = true;
115 float_table_[i].index = iter->opcode;
124 BaseRuntime::GetNativeReplacement(size_t index)
126 if (!float_table_[index].found)
128 return float_table_[index].index;
132 BaseRuntime::SetName(const char *name)
134 m_plugin.name = strdup(name);
137 static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
139 return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
142 int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base)
146 sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
148 memset(&m_plugin, 0, sizeof(m_plugin));
150 m_plugin.base = base;
151 m_plugin.base_size = hdr->imagesize;
153 if (hdr->version == 0x0101)
154 m_plugin.debug.unpacked = true;
156 /* We have to read the name section first */
157 for (sectnum = 0; sectnum < hdr->sections; sectnum++) {
158 nameptr = (char *)(base + hdr->stringtab + secptr[sectnum].nameoffs);
159 if (strcmp(nameptr, ".names") == 0) {
160 m_plugin.stringbase = (const char *)(base + secptr[sectnum].dataoffs);
167 /* Now read the rest of the sections */
168 while (sectnum < hdr->sections) {
169 nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
171 if (!(m_plugin.pcode) && !strcmp(nameptr, ".code")) {
172 sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
174 if (cod->codeversion < SP_CODEVERS_JIT1)
175 return SP_ERROR_CODE_TOO_OLD;
176 if (cod->codeversion > SP_CODEVERS_JIT2)
177 return SP_ERROR_CODE_TOO_NEW;
179 m_plugin.pcode = base + secptr->dataoffs + cod->code;
180 m_plugin.pcode_size = cod->codesize;
181 m_plugin.flags = cod->flags;
182 m_plugin.pcode_version = cod->codeversion;
183 if (!IsPointerCellAligned(m_plugin.pcode)) {
184 // The JIT requires that pcode is cell-aligned, so if it's not, we
185 // remap the code segment to a new address.
186 alt_pcode_ = new uint8_t[m_plugin.pcode_size];
187 memcpy(alt_pcode_, m_plugin.pcode, m_plugin.pcode_size);
188 assert(IsPointerCellAligned(alt_pcode_));
190 m_plugin.pcode = alt_pcode_;
192 } else if (!(m_plugin.data) && !strcmp(nameptr, ".data")) {
193 sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
194 m_plugin.data = base + secptr->dataoffs + dat->data;
195 m_plugin.data_size = dat->datasize;
196 m_plugin.mem_size = dat->memsize;
197 m_plugin.memory = new uint8_t[m_plugin.mem_size];
198 memcpy(m_plugin.memory, m_plugin.data, m_plugin.data_size);
199 } else if ((m_plugin.publics == NULL) && !strcmp(nameptr, ".publics")) {
200 sp_file_publics_t *publics;
202 publics = (sp_file_publics_t *)(base + secptr->dataoffs);
203 m_plugin.num_publics = secptr->size / sizeof(sp_file_publics_t);
205 if (m_plugin.num_publics > 0) {
206 m_plugin.publics = new sp_public_t[m_plugin.num_publics];
208 for (uint32_t i = 0; i < m_plugin.num_publics; i++) {
209 m_plugin.publics[i].code_offs = publics[i].address;
210 m_plugin.publics[i].funcid = (i << 1) | 1;
211 m_plugin.publics[i].name = m_plugin.stringbase + publics[i].name;
214 } else if ((m_plugin.pubvars == NULL) && !strcmp(nameptr, ".pubvars")) {
215 sp_file_pubvars_t *pubvars;
217 pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
218 m_plugin.num_pubvars = secptr->size / sizeof(sp_file_pubvars_t);
220 if (m_plugin.num_pubvars > 0) {
221 m_plugin.pubvars = new sp_pubvar_t[m_plugin.num_pubvars];
223 for (uint32_t i = 0; i < m_plugin.num_pubvars; i++) {
224 m_plugin.pubvars[i].name = m_plugin.stringbase + pubvars[i].name;
225 m_plugin.pubvars[i].offs = (cell_t *)(m_plugin.memory + pubvars[i].address);
228 } else if ((m_plugin.natives == NULL) && !strcmp(nameptr, ".natives")) {
229 sp_file_natives_t *natives;
231 natives = (sp_file_natives_t *)(base + secptr->dataoffs);
232 m_plugin.num_natives = secptr->size / sizeof(sp_file_natives_t);
234 if (m_plugin.num_natives > 0) {
235 m_plugin.natives = new sp_native_t[m_plugin.num_natives];
237 for (uint32_t i = 0; i < m_plugin.num_natives; i++) {
238 m_plugin.natives[i].flags = 0;
239 m_plugin.natives[i].pfn = InvalidNative;
240 m_plugin.natives[i].status = SP_NATIVE_UNBOUND;
241 m_plugin.natives[i].user = NULL;
242 m_plugin.natives[i].name = m_plugin.stringbase + natives[i].name;
245 } else if (!(m_plugin.debug.files) && !strcmp(nameptr, ".dbg.files")) {
246 m_plugin.debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
247 } else if (!(m_plugin.debug.lines) && !strcmp(nameptr, ".dbg.lines")) {
248 m_plugin.debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
249 } else if (!(m_plugin.debug.symbols) && !strcmp(nameptr, ".dbg.symbols")) {
250 m_plugin.debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
251 } else if (!(m_plugin.debug.lines_num) && !strcmp(nameptr, ".dbg.info")) {
252 sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
253 m_plugin.debug.files_num = inf->num_files;
254 m_plugin.debug.lines_num = inf->num_lines;
255 m_plugin.debug.syms_num = inf->num_syms;
256 } else if (!(m_plugin.debug.stringbase) && !strcmp(nameptr, ".dbg.strings")) {
257 m_plugin.debug.stringbase = (const char *)(base + secptr->dataoffs);
258 } else if (strcmp(nameptr, ".dbg.natives") == 0) {
259 m_plugin.debug.unpacked = false;
266 if (m_plugin.pcode == NULL || m_plugin.data == NULL)
267 return SP_ERROR_FILE_FORMAT;
269 if ((m_plugin.flags & SP_FLAG_DEBUG) && (
270 !(m_plugin.debug.files) ||
271 !(m_plugin.debug.lines) ||
272 !(m_plugin.debug.symbols) ||
273 !(m_plugin.debug.stringbase) ))
275 return SP_ERROR_FILE_FORMAT;
278 if (m_plugin.num_publics > 0) {
279 m_PubFuncs = new CFunction *[m_plugin.num_publics];
280 memset(m_PubFuncs, 0, sizeof(CFunction *) * m_plugin.num_publics);
281 m_PubJitFuncs = new JitFunction *[m_plugin.num_publics];
282 memset(m_PubJitFuncs, 0, sizeof(JitFunction *) * m_plugin.num_publics);
286 md5_pcode.update(m_plugin.pcode, m_plugin.pcode_size);
287 md5_pcode.finalize();
288 md5_pcode.raw_digest(m_CodeHash);
291 md5_data.update(m_plugin.data, m_plugin.data_size);
293 md5_data.raw_digest(m_DataHash);
295 m_plugin.profiler = g_engine2.GetProfiler();
296 m_pCtx = new BaseContext(this);
297 co_ = g_Jit.StartCompilation(this);
299 SetupFloatNativeRemapping();
300 function_map_size_ = m_plugin.pcode_size / sizeof(cell_t) + 1;
301 function_map_ = new JitFunction *[function_map_size_];
302 memset(function_map_, 0, function_map_size_ * sizeof(JitFunction *));
304 return SP_ERROR_NONE;
308 BaseRuntime::AddJittedFunction(JitFunction *fn)
310 m_JitFunctions.append(fn);
312 cell_t pcode_offset = fn->GetPCodeAddress();
313 assert(pcode_offset % 4 == 0);
315 uint32_t pcode_index = pcode_offset / 4;
316 assert(pcode_index < function_map_size_);
318 function_map_[pcode_index] = fn;
322 BaseRuntime::GetJittedFunctionByOffset(cell_t pcode_offset)
324 assert(pcode_offset % 4 == 0);
326 uint32_t pcode_index = pcode_offset / 4;
327 assert(pcode_index < function_map_size_);
329 return function_map_[pcode_index];
333 BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
335 for (uint32_t i=0; i<m_plugin.num_natives; i++) {
336 if (strcmp(m_plugin.natives[i].name, name) == 0) {
339 return SP_ERROR_NONE;
343 return SP_ERROR_NOT_FOUND;
347 BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
349 if (index >= m_plugin.num_natives)
350 return SP_ERROR_INDEX;
353 *native = &(m_plugin.natives[index]);
355 return SP_ERROR_NONE;
359 BaseRuntime::GetNativeByIndex(uint32_t index)
361 assert(index < m_plugin.num_natives);
362 return &m_plugin.natives[index];
366 BaseRuntime::GetNativesNum()
368 return m_plugin.num_natives;
372 BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
377 high = m_plugin.num_publics - 1;
380 while (low <= high) {
381 mid = (low + high) / 2;
382 diff = strcmp(m_plugin.publics[mid].name, name);
386 return SP_ERROR_NONE;
387 } else if (diff < 0) {
394 return SP_ERROR_NOT_FOUND;
398 BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
400 if (index >= m_plugin.num_publics)
401 return SP_ERROR_INDEX;
404 *pblic = &(m_plugin.publics[index]);
406 return SP_ERROR_NONE;
410 BaseRuntime::GetPublicsNum()
412 return m_plugin.num_publics;
416 BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
418 if (index >= m_plugin.num_pubvars)
419 return SP_ERROR_INDEX;
422 *pubvar = &(m_plugin.pubvars[index]);
424 return SP_ERROR_NONE;
428 BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
433 high = m_plugin.num_pubvars - 1;
436 while (low <= high) {
437 mid = (low + high) / 2;
438 diff = strcmp(m_plugin.pubvars[mid].name, name);
442 return SP_ERROR_NONE;
443 } else if (diff < 0) {
450 return SP_ERROR_NOT_FOUND;
454 BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
456 if (index >= m_plugin.num_pubvars)
457 return SP_ERROR_INDEX;
459 *local_addr = (uint8_t *)m_plugin.pubvars[index].offs - m_plugin.memory;
460 *phys_addr = m_plugin.pubvars[index].offs;
462 return SP_ERROR_NONE;
466 BaseRuntime::GetPubVarsNum()
468 return m_plugin.num_pubvars;
472 BaseRuntime::GetDefaultContext()
478 BaseRuntime::GetDebugInfo()
484 BaseRuntime::GetFunctionById(funcid_t func_id)
486 CFunction *pFunc = NULL;
490 if (func_id >= m_plugin.num_publics)
492 pFunc = m_PubFuncs[func_id];
494 m_PubFuncs[func_id] = new CFunction(this,
497 pFunc = m_PubFuncs[func_id];
505 BaseRuntime::GetFunctionByName(const char *public_name)
509 if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
512 CFunction *pFunc = m_PubFuncs[index];
514 sp_public_t *pub = NULL;
515 GetPublicByIndex(index, &pub);
517 m_PubFuncs[index] = new CFunction(this, (index << 1) | 1, index);
518 pFunc = m_PubFuncs[index];
524 bool BaseRuntime::IsDebugging()
529 void BaseRuntime::SetPauseState(bool paused)
533 m_plugin.run_flags |= SPFLAG_PLUGIN_PAUSED;
537 m_plugin.run_flags &= ~SPFLAG_PLUGIN_PAUSED;
541 bool BaseRuntime::IsPaused()
543 return ((m_plugin.run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
546 size_t BaseRuntime::GetMemUsage()
551 mem += sizeof(sp_plugin_t);
552 mem += sizeof(BaseContext);
553 mem += m_plugin.base_size;
558 unsigned char *BaseRuntime::GetCodeHash()
563 unsigned char *BaseRuntime::GetDataHash()
568 BaseContext *BaseRuntime::GetBaseContext()
574 BaseRuntime::ApplyCompilationOptions(ICompilation *co)
577 return SP_ERROR_NONE;
579 co_ = g_Jit.ApplyOptions(co_, co);
580 m_plugin.prof_flags = ((CompData *)co_)->profile;
582 return SP_ERROR_NONE;
586 BaseRuntime::CreateBlank(uint32_t heastk)
588 memset(&m_plugin, 0, sizeof(m_plugin));
590 /* Align to cell_t bytes */
591 heastk += sizeof(cell_t);
592 heastk -= heastk % sizeof(cell_t);
594 m_plugin.mem_size = heastk;
595 m_plugin.memory = new uint8_t[heastk];
597 m_plugin.profiler = g_engine2.GetProfiler();
598 m_pCtx = new BaseContext(this);
599 co_ = g_Jit.StartCompilation(this);
601 return SP_ERROR_NONE;