sourcepawn/jit/sp_vm_engine.cpp
author Ruben Gonzalez <drifter01620@gmail.com>
Thu May 22 09:49:27 2014 -0400 (2014-05-22)
changeset 4378 568f4497ef4a
parent 4013 6201c1180e0e
permissions -rw-r--r--
Update CS:GO team score gamedata.
     1 /**
     2  * vim: set ts=4 sw=4 tw=99 et:
     3  * =============================================================================
     4  * SourcePawn
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include <stdlib.h>
    33 #include <string.h>
    34 #include <assert.h>
    35 #include "sp_vm_types.h"
    36 #include <KeCodeAllocator.h>
    37 #include "sp_file_headers.h"
    38 #include "sp_vm_engine.h"
    39 #include "zlib/zlib.h"
    40 #include "sp_vm_basecontext.h"
    41 #include "jit_x86.h"
    42 #if defined __GNUC__
    43 #include <unistd.h>
    44 #endif
    45 
    46 SourcePawnEngine g_engine1;
    47 
    48 #if defined WIN32
    49  #define WIN32_LEAN_AND_MEAN
    50  #include <windows.h>
    51 #elif defined __GNUC__
    52  #include <sys/mman.h>
    53 #endif
    54 
    55 #if defined __linux__
    56 #include <malloc.h>
    57 #endif
    58 
    59 using namespace SourcePawn;
    60 
    61 #define ERROR_MESSAGE_MAX		30
    62 static const char *g_ErrorMsgTable[] = 
    63 {
    64 	NULL,
    65 	"Unrecognizable file format",
    66 	"Decompressor was not found",
    67 	"Not enough space on the heap",
    68 	"Invalid parameter or parameter type",
    69 	"Invalid plugin address",
    70 	"Object or index not found",
    71 	"Invalid index or index not found",
    72 	"Not enough space on the stack",
    73 	"Debug section not found or debug not enabled",
    74 	"Invalid instruction",
    75 	"Invalid memory access",
    76 	"Stack went below stack boundary",
    77 	"Heap went below heap boundary",
    78 	"Divide by zero",
    79 	"Array index is out of bounds",
    80 	"Instruction contained invalid parameter",
    81 	"Stack memory leaked by native",
    82 	"Heap memory leaked by native",
    83 	"Dynamic array is too big",
    84 	"Tracker stack is out of bounds",
    85 	"Native is not bound",
    86 	"Maximum number of parameters reached",
    87 	"Native detected error",
    88 	"Plugin not runnable",
    89 	"Call was aborted",
    90 	"Plugin format is too old",
    91 	"Plugin format is too new",
    92     "Out of memory",
    93     "Integer overflow",
    94     "Script execution timed out"
    95 };
    96 
    97 const char *SourcePawnEngine::GetErrorString(int error)
    98 {
    99 	if (error < 1 || error > ERROR_MESSAGE_MAX)
   100 	{
   101 		return NULL;
   102 	}
   103 
   104 	return g_ErrorMsgTable[error];
   105 }
   106 
   107 SourcePawnEngine::SourcePawnEngine()
   108 {
   109 	m_pDebugHook = NULL;
   110 }
   111 
   112 SourcePawnEngine::~SourcePawnEngine()
   113 {
   114 }
   115 
   116 void *SourcePawnEngine::ExecAlloc(size_t size)
   117 {
   118 #if defined WIN32
   119 	return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
   120 #elif defined __GNUC__
   121 # if defined __APPLE__
   122 	void *base = valloc(size);
   123 # else
   124 	void *base = memalign(sysconf(_SC_PAGESIZE), size);
   125 # endif
   126 	if (mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
   127 	{
   128 		free(base);
   129 		return NULL;
   130 	}
   131 	return base;
   132 #endif
   133 }
   134 
   135 void *SourcePawnEngine::AllocatePageMemory(size_t size)
   136 {
   137 	return g_Jit.AllocCode(size);
   138 }
   139 
   140 void SourcePawnEngine::SetReadExecute(void *ptr)
   141 {
   142 	/* already re */
   143 }
   144 
   145 void SourcePawnEngine::SetReadWrite(void *ptr)
   146 {
   147 	/* already rw */
   148 }
   149 
   150 void SourcePawnEngine::FreePageMemory(void *ptr)
   151 {
   152 	g_Jit.FreeCode(ptr);
   153 }
   154 
   155 void SourcePawnEngine::ExecFree(void *address)
   156 {
   157 #if defined WIN32
   158 	VirtualFree(address, 0, MEM_RELEASE);
   159 #elif defined __GNUC__
   160 	free(address);
   161 #endif
   162 }
   163 
   164 void SourcePawnEngine::SetReadWriteExecute(void *ptr)
   165 {
   166 //:TODO:	g_ExeMemory.SetRWE(ptr);
   167 	SetReadExecute(ptr);
   168 }
   169 
   170 void *SourcePawnEngine::BaseAlloc(size_t size)
   171 {
   172 	return malloc(size);
   173 }
   174 
   175 void SourcePawnEngine::BaseFree(void *memory)
   176 {
   177 	free(memory);
   178 }
   179 
   180 sp_plugin_t *SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err)
   181 {
   182 	if (err != NULL)
   183 	{
   184 		*err = SP_ERROR_ABORTED;
   185 	}
   186 
   187 	return NULL;
   188 }
   189 
   190 sp_plugin_t *SourcePawnEngine::LoadFromMemory(void *base, sp_plugin_t *plugin, int *err)
   191 {
   192 	if (err != NULL)
   193 	{
   194 		*err = SP_ERROR_ABORTED;
   195 	}
   196 
   197 	return NULL;
   198 }
   199 
   200 int SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
   201 {
   202 	return SP_ERROR_ABORTED;
   203 }
   204 
   205 IDebugListener *SourcePawnEngine::SetDebugListener(IDebugListener *pListener)
   206 {
   207 	IDebugListener *old = m_pDebugHook;
   208 
   209 	m_pDebugHook = pListener;
   210 
   211 	return old;
   212 }
   213 
   214 unsigned int SourcePawnEngine::GetEngineAPIVersion()
   215 {
   216 	return SOURCEPAWN_ENGINE_API_VERSION;
   217 }
   218 
   219 unsigned int SourcePawnEngine::GetContextCallCount()
   220 {
   221 	return 0;
   222 }
   223 
   224 void SourcePawnEngine::ReportError(BaseRuntime *runtime, int err, const char *errstr, cell_t rp_start)
   225 {
   226 	if (m_pDebugHook == NULL)
   227 	{
   228 		return;
   229 	}
   230 
   231 	CContextTrace trace(runtime, err, errstr, rp_start);
   232 
   233 	m_pDebugHook->OnContextExecuteError(runtime->GetDefaultContext(), &trace);
   234 }
   235 
   236 CContextTrace::CContextTrace(BaseRuntime *pRuntime, int err, const char *errstr, cell_t start_rp) 
   237 : m_pRuntime(pRuntime), m_Error(err), m_pMsg(errstr), m_StartRp(start_rp), m_Level(0)
   238 {
   239 	m_ctx = pRuntime->m_pCtx->GetCtx();
   240 	m_pDebug = m_pRuntime->GetDebugInfo();
   241 }
   242 
   243 bool CContextTrace::DebugInfoAvailable()
   244 {
   245 	return (m_pDebug != NULL);
   246 }
   247 
   248 const char *CContextTrace::GetCustomErrorString()
   249 {
   250 	return m_pMsg;
   251 }
   252 
   253 int CContextTrace::GetErrorCode()
   254 {
   255 	return m_Error;
   256 }
   257 
   258 const char *CContextTrace::GetErrorString()
   259 {
   260 	if (m_Error > ERROR_MESSAGE_MAX || m_Error < 1)
   261 	{
   262 		return "Invalid error code";
   263 	}
   264 	else
   265 	{
   266 		return g_ErrorMsgTable[m_Error];
   267 	}
   268 }
   269 
   270 void CContextTrace::ResetTrace()
   271 {
   272 	m_Level = 0;
   273 }
   274 
   275 bool CContextTrace::GetTraceInfo(CallStackInfo *trace)
   276 {
   277 	cell_t cip;
   278 
   279 	if (m_Level == 0)
   280 	{
   281 		cip = m_ctx->cip;
   282 	}
   283 	else if (m_ctx->rp > 0)
   284 	{
   285 		/* Entries go from ctx.rp - 1 to m_StartRp */
   286 		cell_t offs, start, end;
   287 
   288 		offs = m_Level - 1;
   289 		start = m_ctx->rp - 1;
   290 		end = m_StartRp;
   291 
   292 		if (start - offs < end)
   293 		{
   294 			return false;
   295 		}
   296 
   297 		cip = m_ctx->rstk_cips[start - offs];
   298 	}
   299 	else
   300 	{
   301 		return false;
   302 	}
   303 
   304 	if (trace == NULL)
   305 	{
   306 		m_Level++;
   307 		return true;
   308 	}
   309 
   310 	if (m_pDebug->LookupFile(cip, &(trace->filename)) != SP_ERROR_NONE)
   311 	{
   312 		trace->filename = NULL;
   313 	}
   314 
   315 	if (m_pDebug->LookupFunction(cip, &(trace->function)) != SP_ERROR_NONE)
   316 	{
   317 		trace->function = NULL;
   318 	}
   319 
   320 	if (m_pDebug->LookupLine(cip, &(trace->line)) != SP_ERROR_NONE)
   321 	{
   322 		trace->line = 0;
   323 	}
   324 
   325 	m_Level++;
   326 
   327 	return true;
   328 }
   329 
   330 const char *CContextTrace::GetLastNative(uint32_t *index)
   331 {
   332 	if (m_ctx->n_err == SP_ERROR_NONE)
   333 	{
   334 		return NULL;
   335 	}
   336 
   337 	sp_native_t *native;
   338 	if (m_pRuntime->GetNativeByIndex(m_ctx->n_idx, &native) != SP_ERROR_NONE)
   339 	{
   340 		return NULL;
   341 	}
   342 
   343 	if (index)
   344 	{
   345 		*index = m_ctx->n_idx;
   346 	}
   347 
   348 	return native->name;
   349 }
   350 
   351 IDebugListener *SourcePawnEngine::GetDebugHook()
   352 {
   353 	return m_pDebugHook;
   354 }
   355