sourcepawn/vm/sp_vm_engine.cpp
author David Anderson <dvander@alliedmods.net>
Thu Oct 12 00:27:18 2006 +0000 (2006-10-12)
changeset 113 75b928da1ef1
parent 93 b00ab8fec541
child 144 ebf6e1c0143a
permissions -rw-r--r--
changed error defines to have "ERROR" instead of "ERR"
added and verified sysreq.c which is generated on -O0
dvander@67
     1
#include <malloc.h>
dvander@67
     2
#include <string.h>
dvander@67
     3
#include "sp_file_headers.h"
dvander@67
     4
#include "sp_vm_types.h"
dvander@67
     5
#include "sp_vm_engine.h"
dvander@67
     6
#include "zlib/zlib.h"
dvander@67
     7
#include "sp_vm_basecontext.h"
dvander@67
     8
dvander@93
     9
#if defined WIN32
dvander@93
    10
 #define WIN32_LEAN_AND_MEAN
dvander@93
    11
 #include <windows.h>
dvander@93
    12
#else if defined __GNUC__
dvander@93
    13
 #include <sys/mman.h>
dvander@93
    14
#endif
dvander@93
    15
dvander@67
    16
using namespace SourcePawn;
dvander@67
    17
dvander@93
    18
void *SourcePawnEngine::ExecAlloc(size_t size)
dvander@93
    19
{
dvander@93
    20
#if defined WIN32
dvander@93
    21
	return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
dvander@93
    22
#else if defined __GNUC__
dvander@93
    23
	void *base = memalign(sysconf(_SC_PAGESIZE), size);
dvander@93
    24
	if (mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
dvander@93
    25
	{
dvander@93
    26
		free(base);
dvander@93
    27
		return NULL;
dvander@93
    28
	}
dvander@93
    29
	return base;
dvander@93
    30
#endif
dvander@93
    31
}
dvander@93
    32
dvander@93
    33
void SourcePawnEngine::ExecFree(void *address)
dvander@93
    34
{
dvander@93
    35
#if defined WIN32
dvander@93
    36
	VirtualFree(address, 0, MEM_RELEASE);
dvander@93
    37
#else if defined __GNUC__
dvander@93
    38
	free(address);
dvander@93
    39
#endif
dvander@93
    40
}
dvander@93
    41
dvander@67
    42
void *SourcePawnEngine::BaseAlloc(size_t size)
dvander@67
    43
{
dvander@67
    44
	return malloc(size);
dvander@67
    45
}
dvander@67
    46
dvander@67
    47
void SourcePawnEngine::BaseFree(void *memory)
dvander@67
    48
{
dvander@67
    49
	free(memory);
dvander@67
    50
}
dvander@67
    51
dvander@67
    52
IPluginContext *SourcePawnEngine::CreateBaseContext(sp_context_t *ctx)
dvander@67
    53
{
dvander@67
    54
	return new BaseContext(ctx);
dvander@67
    55
}
dvander@67
    56
dvander@67
    57
void SourcePawnEngine::FreeBaseContext(IPluginContext *ctx)
dvander@67
    58
{
dvander@67
    59
	sp_context_t *_ctx = ctx->GetContext();
dvander@67
    60
	IVirtualMachine *vm = ctx->GetVirtualMachine();
dvander@67
    61
	
dvander@93
    62
	vm->FreeContext(_ctx);
dvander@67
    63
dvander@67
    64
	delete ctx;
dvander@67
    65
}
dvander@67
    66
dvander@67
    67
sp_plugin_t *_ReadPlugin(sp_file_hdr_t *hdr, uint8_t *base, sp_plugin_t *plugin, int *err)
dvander@67
    68
{
dvander@67
    69
	char *nameptr;
dvander@67
    70
	uint8_t sectnum = 0;
dvander@67
    71
	sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
dvander@67
    72
dvander@67
    73
	memset(plugin, 0, sizeof(sp_plugin_t));
dvander@67
    74
dvander@67
    75
	plugin->base = base;
dvander@67
    76
dvander@67
    77
	while (sectnum < hdr->sections)
dvander@67
    78
	{
dvander@67
    79
		nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
dvander@67
    80
dvander@67
    81
		if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
dvander@67
    82
		{
dvander@67
    83
			sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
dvander@67
    84
			plugin->pcode = base + secptr->dataoffs + cod->code;
dvander@67
    85
			plugin->pcode_size = cod->codesize;
dvander@67
    86
			plugin->flags = cod->flags;
dvander@67
    87
		}
dvander@67
    88
		else if (!(plugin->data) && !strcmp(nameptr, ".data"))
dvander@67
    89
		{
dvander@67
    90
			sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
dvander@67
    91
			plugin->data = base + secptr->dataoffs + dat->data;
dvander@67
    92
			plugin->data_size = dat->datasize;
dvander@67
    93
			plugin->memory = dat->memsize;
dvander@67
    94
		}
dvander@67
    95
		else if (!(plugin->info.publics) && !strcmp(nameptr, ".publics"))
dvander@67
    96
		{
dvander@67
    97
			plugin->info.publics_num = secptr->size / sizeof(sp_file_publics_t);
dvander@67
    98
			plugin->info.publics = (sp_file_publics_t *)(base + secptr->dataoffs);
dvander@67
    99
		}
dvander@67
   100
		else if (!(plugin->info.pubvars) && !strcmp(nameptr, ".pubvars"))
dvander@67
   101
		{
dvander@67
   102
			plugin->info.pubvars_num = secptr->size / sizeof(sp_file_pubvars_t);
dvander@67
   103
			plugin->info.pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
dvander@67
   104
		}
dvander@67
   105
		else if (!(plugin->info.natives) && !strcmp(nameptr, ".natives"))
dvander@67
   106
		{
dvander@67
   107
			plugin->info.natives_num = secptr->size / sizeof(sp_file_natives_t);
dvander@67
   108
			plugin->info.natives = (sp_file_natives_t *)(base + secptr->dataoffs);
dvander@67
   109
		}
dvander@67
   110
		else if (!(plugin->info.stringbase) && !strcmp(nameptr, ".names"))
dvander@67
   111
		{
dvander@67
   112
			plugin->info.stringbase = (const char *)(base + secptr->dataoffs);
dvander@67
   113
		}
dvander@67
   114
		else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
dvander@67
   115
		{
dvander@67
   116
			plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
dvander@67
   117
		}
dvander@67
   118
		else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
dvander@67
   119
		{
dvander@67
   120
			plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
dvander@67
   121
		}
dvander@67
   122
		else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
dvander@67
   123
		{
dvander@67
   124
			plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
dvander@67
   125
		}
dvander@67
   126
		else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
dvander@67
   127
		{
dvander@67
   128
			sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
dvander@67
   129
			plugin->debug.files_num = inf->num_files;
dvander@67
   130
			plugin->debug.lines_num = inf->num_lines;
dvander@67
   131
			plugin->debug.syms_num = inf->num_syms;
dvander@67
   132
		}
dvander@67
   133
		else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
dvander@67
   134
		{
dvander@67
   135
			plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
dvander@67
   136
		}
dvander@67
   137
dvander@67
   138
		secptr++;
dvander@67
   139
		sectnum++;
dvander@67
   140
	}
dvander@67
   141
dvander@67
   142
	if (!(plugin->pcode) || !(plugin->data) || !(plugin->info.stringbase))
dvander@67
   143
	{
dvander@67
   144
		goto return_error;
dvander@67
   145
	}
dvander@67
   146
dvander@67
   147
	if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
dvander@67
   148
	{
dvander@67
   149
		goto return_error;
dvander@67
   150
	}
dvander@67
   151
dvander@67
   152
	if (err)
dvander@67
   153
	{
dvander@113
   154
		*err = SP_ERROR_NONE;
dvander@67
   155
	}
dvander@67
   156
dvander@67
   157
	return plugin;
dvander@67
   158
dvander@67
   159
return_error:
dvander@67
   160
	if (err)
dvander@67
   161
	{
dvander@113
   162
		*err = SP_ERROR_FILE_FORMAT;
dvander@67
   163
	}
dvander@67
   164
dvander@67
   165
	return NULL;
dvander@67
   166
}
dvander@67
   167
dvander@67
   168
sp_plugin_t *SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err)
dvander@67
   169
{
dvander@67
   170
	sp_file_hdr_t hdr;
dvander@67
   171
	sp_plugin_t *plugin;
dvander@67
   172
	uint8_t *base;
dvander@67
   173
	int z_result;
dvander@67
   174
	int error;
dvander@67
   175
dvander@67
   176
	if (!fp)
dvander@67
   177
	{
dvander@113
   178
		error = SP_ERROR_NOT_FOUND;
dvander@67
   179
		goto return_error;
dvander@67
   180
	}
dvander@67
   181
dvander@67
   182
	/* Rewind for safety */
dvander@67
   183
	rewind(fp);
dvander@67
   184
	fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
dvander@67
   185
dvander@67
   186
	if (hdr.magic != SPFILE_MAGIC)
dvander@67
   187
	{
dvander@113
   188
		error = SP_ERROR_FILE_FORMAT;
dvander@67
   189
		goto return_error;
dvander@67
   190
	}
dvander@67
   191
dvander@67
   192
	switch (hdr.compression)
dvander@67
   193
	{
dvander@67
   194
	case SPFILE_COMPRESSION_GZ:
dvander@67
   195
		{
dvander@67
   196
			uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
dvander@67
   197
			uint32_t compsize = hdr.disksize - hdr.dataoffs;
dvander@67
   198
			uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
dvander@67
   199
			uLongf destlen = uncompsize;
dvander@67
   200
dvander@67
   201
			char *tempbuf = (char *)malloc(compsize);
dvander@67
   202
			void *uncompdata = malloc(uncompsize);
dvander@67
   203
			void *sectheader = malloc(sectsize);
dvander@67
   204
dvander@67
   205
			fread(sectheader, sectsize, 1, fp);
dvander@67
   206
			fread(tempbuf, compsize, 1, fp);
dvander@67
   207
dvander@67
   208
			z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
dvander@67
   209
			free(tempbuf);
dvander@67
   210
			if (z_result != Z_OK)
dvander@67
   211
			{
dvander@67
   212
				free(sectheader);
dvander@67
   213
				free(uncompdata);
dvander@113
   214
				error = SP_ERROR_DECOMPRESSOR;
dvander@67
   215
				goto return_error;
dvander@67
   216
			}
dvander@67
   217
dvander@67
   218
			base = (uint8_t *)malloc(hdr.imagesize);
dvander@67
   219
			memcpy(base, &hdr, sizeof(sp_file_hdr_t));
dvander@67
   220
			memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
dvander@67
   221
			free(sectheader);
dvander@67
   222
			memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
dvander@67
   223
			free(uncompdata);
dvander@67
   224
			break;
dvander@67
   225
		}
dvander@67
   226
	case SPFILE_COMPRESSION_NONE:
dvander@67
   227
		{
dvander@67
   228
			base = (uint8_t *)malloc(hdr.imagesize);
dvander@67
   229
			rewind(fp);
dvander@67
   230
			fread(base, hdr.imagesize, 1, fp);
dvander@67
   231
			break;
dvander@67
   232
		}
dvander@67
   233
	default:
dvander@67
   234
		{
dvander@113
   235
			error = SP_ERROR_DECOMPRESSOR;
dvander@67
   236
			goto return_error;
dvander@67
   237
		}
dvander@67
   238
	}
dvander@67
   239
dvander@67
   240
	plugin = (sp_plugin_t *)malloc(sizeof(sp_plugin_t));
dvander@67
   241
	if (!_ReadPlugin(&hdr, base, plugin, err))
dvander@67
   242
	{
dvander@67
   243
		free(plugin);
dvander@67
   244
		free(base);
dvander@67
   245
		return NULL;
dvander@67
   246
	}
dvander@67
   247
dvander@67
   248
	plugin->allocflags = 0;
dvander@67
   249
dvander@67
   250
	return plugin;
dvander@67
   251
dvander@67
   252
return_error:
dvander@67
   253
	if (err)
dvander@67
   254
	{
dvander@67
   255
		*err = error;
dvander@67
   256
	}
dvander@67
   257
	return NULL;
dvander@67
   258
}
dvander@67
   259
dvander@67
   260
sp_plugin_t *SourcePawnEngine::LoadFromMemory(void *base, sp_plugin_t *plugin, int *err)
dvander@67
   261
{
dvander@67
   262
	sp_file_hdr_t hdr;
dvander@67
   263
	uint8_t noptr = 0;
dvander@67
   264
dvander@67
   265
	memcpy(&hdr, base, sizeof(sp_file_hdr_t));
dvander@67
   266
dvander@67
   267
	if (!plugin)
dvander@67
   268
	{
dvander@67
   269
		plugin = (sp_plugin_t *)malloc(sizeof(sp_plugin_t));
dvander@67
   270
		noptr = 1;
dvander@67
   271
	}
dvander@67
   272
dvander@67
   273
	if (!_ReadPlugin(&hdr, (uint8_t *)base, plugin, err))
dvander@67
   274
	{
dvander@67
   275
		if (noptr)
dvander@67
   276
		{
dvander@67
   277
			free(plugin);
dvander@67
   278
		}
dvander@67
   279
		return NULL;
dvander@67
   280
	}
dvander@67
   281
dvander@67
   282
	if (!noptr)
dvander@67
   283
	{
dvander@67
   284
		plugin->allocflags |= SP_FA_SELF_EXTERNAL;
dvander@67
   285
	}
dvander@67
   286
	plugin->allocflags |= SP_FA_BASE_EXTERNAL;
dvander@67
   287
dvander@67
   288
	return plugin;
dvander@67
   289
}
dvander@67
   290
dvander@67
   291
int SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
dvander@67
   292
{
dvander@67
   293
	if (!(plugin->allocflags & SP_FA_BASE_EXTERNAL))
dvander@67
   294
	{
dvander@67
   295
		free(plugin->base);
dvander@67
   296
		plugin->base = NULL;
dvander@67
   297
	}
dvander@67
   298
	if (!(plugin->allocflags & SP_FA_SELF_EXTERNAL))
dvander@67
   299
	{
dvander@67
   300
		free(plugin);
dvander@67
   301
	}
dvander@67
   302
dvander@113
   303
	return SP_ERROR_NONE;
dvander@67
   304
}