1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/sourcepawn/jit/sp_vm_basecontext.cpp Fri Jul 11 08:18:43 2008 +0000
1.3 @@ -0,0 +1,810 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourcePawn
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include <string.h>
1.36 +#include <stdarg.h>
1.37 +#include <assert.h>
1.38 +#include <limits.h>
1.39 +#include "sp_vm_api.h"
1.40 +#include "sp_vm_basecontext.h"
1.41 +#include "sp_vm_engine.h"
1.42 +#include "x86/jit_x86.h"
1.43 +
1.44 +using namespace SourcePawn;
1.45 +
1.46 +#define CELLBOUNDMAX (INT_MAX/sizeof(cell_t))
1.47 +#define STACKMARGIN ((cell_t)(16*sizeof(cell_t)))
1.48 +
1.49 +BaseContext::BaseContext(BaseRuntime *pRuntime)
1.50 +{
1.51 + m_pRuntime = pRuntime;
1.52 + m_pPlugin = m_pRuntime->m_pPlugin;
1.53 +
1.54 + m_InExec = false;
1.55 + m_CustomMsg = false;
1.56 +
1.57 + m_pNullVec = NULL;
1.58 + m_pNullString = NULL;
1.59 +}
1.60 +
1.61 +BaseContext::~BaseContext()
1.62 +{
1.63 +}
1.64 +
1.65 +IVirtualMachine *BaseContext::GetVirtualMachine()
1.66 +{
1.67 + return NULL;
1.68 +}
1.69 +
1.70 +sp_context_t *BaseContext::GetContext()
1.71 +{
1.72 + return reinterpret_cast<sp_context_t *>((IPluginContext * )this);
1.73 +}
1.74 +
1.75 +sp_context_t *BaseContext::GetCtx()
1.76 +{
1.77 + return &m_ctx;
1.78 +}
1.79 +
1.80 +bool BaseContext::IsDebugging()
1.81 +{
1.82 + return m_pRuntime->IsDebugging();
1.83 +}
1.84 +
1.85 +int BaseContext::SetDebugBreak(void *newpfn, void *oldpfn)
1.86 +{
1.87 + return SP_ERROR_ABORTED;
1.88 +}
1.89 +
1.90 +IPluginDebugInfo *BaseContext::GetDebugInfo()
1.91 +{
1.92 + return NULL;
1.93 +}
1.94 +
1.95 +int BaseContext::Execute(uint32_t code_addr, cell_t *result)
1.96 +{
1.97 + return SP_ERROR_ABORTED;
1.98 +}
1.99 +
1.100 +void BaseContext::SetErrorMessage(const char *msg, va_list ap)
1.101 +{
1.102 + m_CustomMsg = true;
1.103 +
1.104 + vsnprintf(m_MsgCache, sizeof(m_MsgCache), msg, ap);
1.105 +}
1.106 +
1.107 +void BaseContext::_SetErrorMessage(const char *msg, ...)
1.108 +{
1.109 + va_list ap;
1.110 + va_start(ap, msg);
1.111 + SetErrorMessage(msg, ap);
1.112 + va_end(ap);
1.113 +}
1.114 +
1.115 +cell_t BaseContext::ThrowNativeErrorEx(int error, const char *msg, ...)
1.116 +{
1.117 + if (!m_InExec)
1.118 + {
1.119 + return 0;
1.120 + }
1.121 +
1.122 + m_ctx.n_err = error;
1.123 +
1.124 + if (msg)
1.125 + {
1.126 + va_list ap;
1.127 + va_start(ap, msg);
1.128 + SetErrorMessage(msg, ap);
1.129 + va_end(ap);
1.130 + }
1.131 +
1.132 + return 0;
1.133 +}
1.134 +
1.135 +cell_t BaseContext::ThrowNativeError(const char *msg, ...)
1.136 +{
1.137 + if (!m_InExec)
1.138 + {
1.139 + return 0;
1.140 + }
1.141 +
1.142 + m_ctx.n_err = SP_ERROR_NATIVE;
1.143 +
1.144 + if (msg)
1.145 + {
1.146 + va_list ap;
1.147 + va_start(ap, msg);
1.148 + SetErrorMessage(msg, ap);
1.149 + va_end(ap);
1.150 + }
1.151 +
1.152 + return 0;
1.153 +}
1.154 +
1.155 +int BaseContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr)
1.156 +{
1.157 + cell_t *addr;
1.158 + ucell_t realmem;
1.159 +
1.160 +#if 0
1.161 + if (cells > CELLBOUNDMAX)
1.162 + {
1.163 + return SP_ERROR_ARAM;
1.164 + }
1.165 +#else
1.166 + assert(cells < CELLBOUNDMAX);
1.167 +#endif
1.168 +
1.169 + realmem = cells * sizeof(cell_t);
1.170 +
1.171 + /**
1.172 + * Check if the space between the heap and stack is sufficient.
1.173 + */
1.174 + if ((cell_t)(m_ctx.sp - m_ctx.hp - realmem) < STACKMARGIN)
1.175 + {
1.176 + return SP_ERROR_HEAPLOW;
1.177 + }
1.178 +
1.179 + addr = (cell_t *)(m_pPlugin->memory + m_ctx.hp);
1.180 + /* store size of allocation in cells */
1.181 + *addr = (cell_t)cells;
1.182 + addr++;
1.183 + m_ctx.hp += sizeof(cell_t);
1.184 +
1.185 + *local_addr = m_ctx.hp;
1.186 +
1.187 + if (phys_addr)
1.188 + {
1.189 + *phys_addr = addr;
1.190 + }
1.191 +
1.192 + m_ctx.hp += realmem;
1.193 +
1.194 + return SP_ERROR_NONE;
1.195 +}
1.196 +
1.197 +int BaseContext::HeapPop(cell_t local_addr)
1.198 +{
1.199 + cell_t cellcount;
1.200 + cell_t *addr;
1.201 +
1.202 + /* check the bounds of this address */
1.203 + local_addr -= sizeof(cell_t);
1.204 + if (local_addr < (cell_t)m_pPlugin->data_size || local_addr >= m_ctx.sp)
1.205 + {
1.206 + return SP_ERROR_INVALID_ADDRESS;
1.207 + }
1.208 +
1.209 + addr = (cell_t *)(m_pPlugin->memory + local_addr);
1.210 + cellcount = (*addr) * sizeof(cell_t);
1.211 + /* check if this memory count looks valid */
1.212 + if ((signed)(m_ctx.hp - cellcount - sizeof(cell_t)) != local_addr)
1.213 + {
1.214 + return SP_ERROR_INVALID_ADDRESS;
1.215 + }
1.216 +
1.217 + m_ctx.hp = local_addr;
1.218 +
1.219 + return SP_ERROR_NONE;
1.220 +}
1.221 +
1.222 +
1.223 +int BaseContext::HeapRelease(cell_t local_addr)
1.224 +{
1.225 + if (local_addr < (cell_t)m_pPlugin->data_size)
1.226 + {
1.227 + return SP_ERROR_INVALID_ADDRESS;
1.228 + }
1.229 +
1.230 + m_ctx.hp = local_addr - sizeof(cell_t);
1.231 +
1.232 + return SP_ERROR_NONE;
1.233 +}
1.234 +
1.235 +int BaseContext::FindNativeByName(const char *name, uint32_t *index)
1.236 +{
1.237 + return m_pRuntime->FindNativeByName(name, index);
1.238 +}
1.239 +
1.240 +int BaseContext::GetNativeByIndex(uint32_t index, sp_native_t **native)
1.241 +{
1.242 + return m_pRuntime->GetNativeByIndex(index, native);
1.243 +}
1.244 +
1.245 +
1.246 +uint32_t BaseContext::GetNativesNum()
1.247 +{
1.248 + return m_pRuntime->GetNativesNum();
1.249 +}
1.250 +
1.251 +int BaseContext::FindPublicByName(const char *name, uint32_t *index)
1.252 +{
1.253 + return m_pRuntime->FindPublicByName(name, index);
1.254 +}
1.255 +
1.256 +int BaseContext::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
1.257 +{
1.258 + return m_pRuntime->GetPublicByIndex(index, pblic);
1.259 +}
1.260 +
1.261 +uint32_t BaseContext::GetPublicsNum()
1.262 +{
1.263 + return m_pRuntime->GetPublicsNum();
1.264 +}
1.265 +
1.266 +int BaseContext::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
1.267 +{
1.268 + return m_pRuntime->GetPubvarByIndex(index, pubvar);
1.269 +}
1.270 +
1.271 +int BaseContext::FindPubvarByName(const char *name, uint32_t *index)
1.272 +{
1.273 + return m_pRuntime->FindPubvarByName(name, index);
1.274 +}
1.275 +
1.276 +int BaseContext::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
1.277 +{
1.278 + return m_pRuntime->GetPubvarAddrs(index, local_addr, phys_addr);
1.279 +}
1.280 +
1.281 +uint32_t BaseContext::GetPubVarsNum()
1.282 +{
1.283 + return m_pRuntime->GetPubVarsNum();
1.284 +}
1.285 +
1.286 +int BaseContext::BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite)
1.287 +{
1.288 + return SP_ERROR_ABORTED;
1.289 +}
1.290 +
1.291 +int BaseContext::BindNative(const sp_nativeinfo_t *native)
1.292 +{
1.293 + return SP_ERROR_ABORTED;
1.294 +}
1.295 +
1.296 +int BaseContext::BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC func)
1.297 +{
1.298 + return SP_ERROR_ABORTED;
1.299 +}
1.300 +
1.301 +int BaseContext::BindNativeToAny(SPVM_NATIVE_FUNC native)
1.302 +{
1.303 + return SP_ERROR_ABORTED;
1.304 +}
1.305 +
1.306 +int BaseContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr)
1.307 +{
1.308 + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
1.309 + || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
1.310 + {
1.311 + return SP_ERROR_INVALID_ADDRESS;
1.312 + }
1.313 +
1.314 + if (phys_addr)
1.315 + {
1.316 + *phys_addr = (cell_t *)(m_pPlugin->memory + local_addr);
1.317 + }
1.318 +
1.319 + return SP_ERROR_NONE;
1.320 +}
1.321 +
1.322 +int BaseContext::PushCell(cell_t value)
1.323 +{
1.324 + return SP_ERROR_ABORTED;
1.325 +}
1.326 +
1.327 +int BaseContext::PushCellsFromArray(cell_t array[], unsigned int numcells)
1.328 +{
1.329 + return SP_ERROR_ABORTED;
1.330 +}
1.331 +
1.332 +int BaseContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells)
1.333 +{
1.334 + return SP_ERROR_ABORTED;
1.335 +}
1.336 +
1.337 +int BaseContext::LocalToString(cell_t local_addr, char **addr)
1.338 +{
1.339 + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
1.340 + || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
1.341 + {
1.342 + return SP_ERROR_INVALID_ADDRESS;
1.343 + }
1.344 + *addr = (char *)(m_pPlugin->memory + local_addr);
1.345 +
1.346 + return SP_ERROR_NONE;
1.347 +}
1.348 +
1.349 +int BaseContext::PushString(cell_t *local_addr, char **phys_addr, const char *string)
1.350 +{
1.351 + return SP_ERROR_ABORTED;
1.352 +}
1.353 +
1.354 +int BaseContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source)
1.355 +{
1.356 + char *dest;
1.357 + size_t len;
1.358 +
1.359 + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
1.360 + || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
1.361 + {
1.362 + return SP_ERROR_INVALID_ADDRESS;
1.363 + }
1.364 +
1.365 + if (bytes == 0)
1.366 + {
1.367 + return SP_ERROR_NONE;
1.368 + }
1.369 +
1.370 + len = strlen(source);
1.371 + dest = (char *)(m_pPlugin->memory + local_addr);
1.372 +
1.373 + if (len >= bytes)
1.374 + {
1.375 + len = bytes - 1;
1.376 + }
1.377 +
1.378 + memmove(dest, source, len);
1.379 + dest[len] = '\0';
1.380 +
1.381 + return SP_ERROR_NONE;
1.382 +}
1.383 +
1.384 +inline int __CheckValidChar(char *c)
1.385 +{
1.386 + int count;
1.387 + int bytecount = 0;
1.388 +
1.389 + for (count=1; (*c & 0xC0) == 0x80; count++)
1.390 + {
1.391 + c--;
1.392 + }
1.393 +
1.394 + switch (*c & 0xF0)
1.395 + {
1.396 + case 0xC0:
1.397 + case 0xD0:
1.398 + {
1.399 + bytecount = 2;
1.400 + break;
1.401 + }
1.402 + case 0xE0:
1.403 + {
1.404 + bytecount = 3;
1.405 + break;
1.406 + }
1.407 + case 0xF0:
1.408 + {
1.409 + bytecount = 4;
1.410 + break;
1.411 + }
1.412 + }
1.413 +
1.414 + if (bytecount != count)
1.415 + {
1.416 + return count;
1.417 + }
1.418 +
1.419 + return 0;
1.420 +}
1.421 +
1.422 +int BaseContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes)
1.423 +{
1.424 + char *dest;
1.425 + size_t len;
1.426 + bool needtocheck = false;
1.427 +
1.428 + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
1.429 + || (local_addr < 0)
1.430 + || ((ucell_t)local_addr >= m_pPlugin->mem_size))
1.431 + {
1.432 + return SP_ERROR_INVALID_ADDRESS;
1.433 + }
1.434 +
1.435 + if (maxbytes == 0)
1.436 + {
1.437 + return SP_ERROR_NONE;
1.438 + }
1.439 +
1.440 + len = strlen(source);
1.441 + dest = (char *)(m_pPlugin->memory + local_addr);
1.442 +
1.443 + if ((size_t)len >= maxbytes)
1.444 + {
1.445 + len = maxbytes - 1;
1.446 + needtocheck = true;
1.447 + }
1.448 +
1.449 + memmove(dest, source, len);
1.450 + if ((dest[len-1] & 1<<7) && needtocheck)
1.451 + {
1.452 + len -= __CheckValidChar(dest+len-1);
1.453 + }
1.454 + dest[len] = '\0';
1.455 +
1.456 + if (wrtnbytes)
1.457 + {
1.458 + *wrtnbytes = len;
1.459 + }
1.460 +
1.461 + return SP_ERROR_NONE;
1.462 +}
1.463 +
1.464 +IPluginFunction *BaseContext::GetFunctionById(funcid_t func_id)
1.465 +{
1.466 + return m_pRuntime->GetFunctionById(func_id);
1.467 +}
1.468 +
1.469 +IPluginFunction *BaseContext::GetFunctionByName(const char *public_name)
1.470 +{
1.471 + return m_pRuntime->GetFunctionByName(public_name);
1.472 +}
1.473 +
1.474 +int BaseContext::LocalToStringNULL(cell_t local_addr, char **addr)
1.475 +{
1.476 + int err;
1.477 + if ((err = LocalToString(local_addr, addr)) != SP_ERROR_NONE)
1.478 + {
1.479 + return err;
1.480 + }
1.481 +
1.482 + if ((cell_t *)*addr == m_pNullString)
1.483 + {
1.484 + *addr = NULL;
1.485 + }
1.486 +
1.487 + return SP_ERROR_NONE;
1.488 +}
1.489 +
1.490 +SourceMod::IdentityToken_t *BaseContext::GetIdentity()
1.491 +{
1.492 + SourceMod::IdentityToken_t *tok;
1.493 +
1.494 + if (GetKey(1, (void **)&tok))
1.495 + {
1.496 + return tok;
1.497 + }
1.498 +
1.499 + return NULL;
1.500 +}
1.501 +
1.502 +cell_t *BaseContext::GetNullRef(SP_NULL_TYPE type)
1.503 +{
1.504 + if (type == SP_NULL_VECTOR)
1.505 + {
1.506 + return m_pNullVec;
1.507 + }
1.508 +
1.509 + return NULL;
1.510 +}
1.511 +
1.512 +bool BaseContext::IsInExec()
1.513 +{
1.514 + return m_InExec;
1.515 +}
1.516 +
1.517 +int BaseContext::Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result)
1.518 +{
1.519 + int ir;
1.520 + int serial;
1.521 + cell_t *sp;
1.522 + funcid_t fnid;
1.523 + sp_public_t *pubfunc;
1.524 + cell_t _ignore_result;
1.525 +
1.526 + fnid = function->GetFunctionID();
1.527 +
1.528 + if (fnid & 1)
1.529 + {
1.530 + unsigned int public_id;
1.531 +
1.532 + public_id = fnid >> 1;
1.533 +
1.534 + if (m_pRuntime->GetPublicByIndex(public_id, &pubfunc) != SP_ERROR_NONE)
1.535 + {
1.536 + return SP_ERROR_NOT_FOUND;
1.537 + }
1.538 + }
1.539 + else
1.540 + {
1.541 + return SP_ERROR_INVALID_ADDRESS;
1.542 + }
1.543 +
1.544 + if (m_pRuntime->IsPaused())
1.545 + {
1.546 + return SP_ERROR_NOT_RUNNABLE;
1.547 + }
1.548 +
1.549 + if ((cell_t)(m_ctx.hp + 16*sizeof(cell_t)) > (cell_t)(m_ctx.sp - (sizeof(cell_t) * (num_params + 1))))
1.550 + {
1.551 + return SP_ERROR_STACKLOW;
1.552 + }
1.553 +
1.554 + if (result == NULL)
1.555 + {
1.556 + result = &_ignore_result;
1.557 + }
1.558 +
1.559 + /* We got this far. It's time to start profiling. */
1.560 +
1.561 + if ((m_pPlugin->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS)
1.562 + {
1.563 + serial = m_pPlugin->profiler->OnCallbackBegin(this, pubfunc);
1.564 + }
1.565 +
1.566 + /* Save our previous state. */
1.567 +
1.568 + bool save_exec;
1.569 + uint32_t save_n_idx;
1.570 + cell_t save_sp, save_hp;
1.571 +
1.572 + save_sp = m_ctx.sp;
1.573 + save_hp = m_ctx.hp;
1.574 + save_exec = m_InExec;
1.575 + save_n_idx = m_ctx.n_idx;
1.576 +
1.577 + /* Push parameters */
1.578 +
1.579 + m_ctx.sp -= sizeof(cell_t) * (num_params + 1);
1.580 + sp = (cell_t *)(m_pPlugin->memory + m_ctx.sp);
1.581 +
1.582 + sp[0] = num_params;
1.583 + for (unsigned int i = 0; i < num_params; i++)
1.584 + {
1.585 + sp[i + 1] = params[i];
1.586 + }
1.587 +
1.588 + /* Clear internal state */
1.589 + m_ctx.n_err = SP_ERROR_NONE;
1.590 + m_ctx.n_idx = 0;
1.591 + m_MsgCache[0] = '\0';
1.592 + m_CustomMsg = false;
1.593 + m_InExec = false;
1.594 +
1.595 + /* Start the tracer */
1.596 +
1.597 + g_engine1.PushTracer(this);
1.598 +
1.599 + /* Execute the function */
1.600 +
1.601 + ir = g_Jit1.ContextExecute(m_pPlugin, &m_ctx, pubfunc->code_offs, result);
1.602 +
1.603 + /* Restore some states, stop tracing */
1.604 +
1.605 + m_InExec = save_exec;
1.606 +
1.607 + if (ir == SP_ERROR_NONE)
1.608 + {
1.609 + m_ctx.n_err = SP_ERROR_NONE;
1.610 + if (m_ctx.sp != save_sp)
1.611 + {
1.612 + ir = SP_ERROR_STACKLEAK;
1.613 + _SetErrorMessage("Stack leak detected: sp:%d should be %d!",
1.614 + m_ctx.sp,
1.615 + save_sp);
1.616 + }
1.617 + if (m_ctx.hp != save_hp)
1.618 + {
1.619 + ir = SP_ERROR_HEAPLEAK;
1.620 + _SetErrorMessage("Heap leak detected: hp:%d should be %d!",
1.621 + m_ctx.hp,
1.622 + save_hp);
1.623 + }
1.624 + }
1.625 +
1.626 + m_ctx.sp = save_sp;
1.627 + m_ctx.hp = save_hp;
1.628 +
1.629 + g_engine1.PopTracer(ir, m_CustomMsg ? m_MsgCache : NULL);
1.630 +
1.631 + if ((m_pPlugin->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS)
1.632 + {
1.633 + m_pPlugin->profiler->OnCallbackEnd(serial);
1.634 + }
1.635 +
1.636 + m_ctx.n_idx = save_n_idx;
1.637 + m_ctx.n_err = SP_ERROR_NONE;
1.638 + m_MsgCache[0] = '\0';
1.639 + m_CustomMsg = false;
1.640 +
1.641 + return ir;
1.642 +}
1.643 +
1.644 +IPluginRuntime *BaseContext::GetRuntime()
1.645 +{
1.646 + return m_pRuntime;
1.647 +}
1.648 +
1.649 +int BaseRuntime::ApplyCompilationOptions(ICompilation *co)
1.650 +{
1.651 + int err;
1.652 +
1.653 + /* The JIT does not destroy anything until it is guaranteed to succeed. */
1.654 + if (!g_Jit1.Compile(co, this, &err))
1.655 + {
1.656 + return err;
1.657 + }
1.658 +
1.659 + RefreshFunctionCache();
1.660 +
1.661 + m_pCtx->Refresh();
1.662 +
1.663 + return SP_ERROR_NONE;
1.664 +}
1.665 +
1.666 +DebugInfo::DebugInfo(sp_plugin_t *plugin) : m_pPlugin(plugin)
1.667 +{
1.668 +}
1.669 +
1.670 +#define USHR(x) ((unsigned int)(x)>>1)
1.671 +
1.672 +int DebugInfo::LookupFile(ucell_t addr, const char **filename)
1.673 +{
1.674 + int high, low, mid;
1.675 +
1.676 + high = m_pPlugin->debug.files_num;
1.677 + low = -1;
1.678 +
1.679 + while (high - low > 1)
1.680 + {
1.681 + mid = USHR(low + high);
1.682 + if (m_pPlugin->files[mid].addr <= addr)
1.683 + {
1.684 + low = mid;
1.685 + } else {
1.686 + high = mid;
1.687 + }
1.688 + }
1.689 +
1.690 + if (low == -1)
1.691 + {
1.692 + return SP_ERROR_NOT_FOUND;
1.693 + }
1.694 +
1.695 + *filename = m_pPlugin->files[low].name;
1.696 +
1.697 + return SP_ERROR_NONE;
1.698 +}
1.699 +
1.700 +int DebugInfo::LookupFunction(ucell_t addr, const char **name)
1.701 +{
1.702 + uint32_t iter, max = m_pPlugin->debug.syms_num;
1.703 +
1.704 + for (iter=0; iter<max; iter++)
1.705 + {
1.706 + if ((m_pPlugin->symbols[iter].sym->ident == SP_SYM_FUNCTION)
1.707 + && (m_pPlugin->symbols[iter].codestart <= addr)
1.708 + && (m_pPlugin->symbols[iter].codeend > addr))
1.709 + {
1.710 + break;
1.711 + }
1.712 + }
1.713 +
1.714 + if (iter >= max)
1.715 + {
1.716 + return SP_ERROR_NOT_FOUND;
1.717 + }
1.718 +
1.719 + *name = m_pPlugin->symbols[iter].name;
1.720 +
1.721 + return SP_ERROR_NONE;
1.722 +}
1.723 +
1.724 +int DebugInfo::LookupLine(ucell_t addr, uint32_t *line)
1.725 +{
1.726 + int high, low, mid;
1.727 +
1.728 + high = m_pPlugin->debug.lines_num;
1.729 + low = -1;
1.730 +
1.731 + while (high - low > 1)
1.732 + {
1.733 + mid = USHR(low + high);
1.734 + if (m_pPlugin->lines[mid].addr <= addr)
1.735 + {
1.736 + low = mid;
1.737 + } else {
1.738 + high = mid;
1.739 + }
1.740 + }
1.741 +
1.742 + if (low == -1)
1.743 + {
1.744 + return SP_ERROR_NOT_FOUND;
1.745 + }
1.746 +
1.747 + /* Since the CIP occurs BEFORE the line, we have to add one */
1.748 + *line = m_pPlugin->lines[low].line + 1;
1.749 +
1.750 + return SP_ERROR_NONE;
1.751 +}
1.752 +
1.753 +#undef USHR
1.754 +
1.755 +int BaseContext::GetLastNativeError()
1.756 +{
1.757 + return m_ctx.n_err;
1.758 +}
1.759 +
1.760 +cell_t *BaseContext::GetLocalParams()
1.761 +{
1.762 + return (cell_t *)(m_pPlugin->memory + m_ctx.frm + (2 * sizeof(cell_t)));
1.763 +}
1.764 +
1.765 +void BaseContext::SetKey(int k, void *value)
1.766 +{
1.767 + if (k < 1 || k > 4)
1.768 + {
1.769 + return;
1.770 + }
1.771 +
1.772 + m_keys[k - 1] = value;
1.773 + m_keys_set[k - 1] = true;
1.774 +}
1.775 +
1.776 +bool BaseContext::GetKey(int k, void **value)
1.777 +{
1.778 + if (k < 1 || k > 4 || m_keys_set[k - 1] == false)
1.779 + {
1.780 + return false;
1.781 + }
1.782 +
1.783 + *value = m_keys[k - 1];
1.784 +
1.785 + return true;
1.786 +}
1.787 +
1.788 +void BaseContext::Refresh()
1.789 +{
1.790 + /* Initialize the null references */
1.791 + uint32_t index;
1.792 + if (FindPubvarByName("NULL_VECTOR", &index) == SP_ERROR_NONE)
1.793 + {
1.794 + sp_pubvar_t *pubvar;
1.795 + GetPubvarByIndex(index, &pubvar);
1.796 + m_pNullVec = pubvar->offs;
1.797 + }
1.798 + else
1.799 + {
1.800 + m_pNullVec = NULL;
1.801 + }
1.802 +
1.803 + if (FindPubvarByName("NULL_STRING", &index) == SP_ERROR_NONE)
1.804 + {
1.805 + sp_pubvar_t *pubvar;
1.806 + GetPubvarByIndex(index, &pubvar);
1.807 + m_pNullString = pubvar->offs;
1.808 + }
1.809 + else
1.810 + {
1.811 + m_pNullString = NULL;
1.812 + }
1.813 +}