sourcepawn/decompiler/file_format.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Thu Jul 18 21:07:14 2013 -0400 (2013-07-18)
changeset 3957 fe91589c0458
parent 2325 7a24ee5557fb
permissions -rw-r--r--
Synced gdc-psyfork symbols.txt with live version (NPOTB).
dvander@2320
     1
#include <stdio.h>
dvander@2320
     2
#include <string.h>
dvander@2320
     3
#include <stdlib.h>
dvander@2320
     4
#include "zlib.h"
dvander@2320
     5
#include "file_format.h"
dvander@2320
     6
dvander@2320
     7
void Sp_FreePlugin(sp_file_t *plugin)
dvander@2320
     8
{
dvander@2320
     9
	if (plugin == NULL)
dvander@2320
    10
	{
dvander@2320
    11
		return;
dvander@2320
    12
	}
dvander@2320
    13
dvander@2320
    14
	free(plugin->base);
dvander@2320
    15
	delete [] plugin->publics;
dvander@2320
    16
	delete [] plugin->pubvars;
dvander@2320
    17
	delete [] plugin->natives;
dvander@2320
    18
	delete plugin;
dvander@2320
    19
}
dvander@2320
    20
dvander@2320
    21
sp_file_t *Sp_ReadPlugin(const char *file, int *err)
dvander@2320
    22
{
dvander@2320
    23
	sp_file_t *plugin;
dvander@2320
    24
	sp_file_hdr_t hdr;
dvander@2320
    25
	uint8_t *base;
dvander@2320
    26
	int z_result;
dvander@2320
    27
	int error;
dvander@2320
    28
dvander@2320
    29
	FILE *fp = fopen(file, "rb");
dvander@2320
    30
dvander@2320
    31
	plugin = NULL;
dvander@2320
    32
dvander@2320
    33
	if (!fp)
dvander@2320
    34
	{
dvander@2320
    35
		error = SP_ERROR_NOT_FOUND;
dvander@2320
    36
		goto return_error;
dvander@2320
    37
	}
dvander@2320
    38
dvander@2320
    39
	/* Rewind for safety */
dvander@2320
    40
	fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
dvander@2320
    41
dvander@2320
    42
	if (hdr.magic != SPFILE_MAGIC)
dvander@2320
    43
	{
dvander@2320
    44
		error = SP_ERROR_FILE_FORMAT;
dvander@2320
    45
		goto return_error;
dvander@2320
    46
	}
dvander@2320
    47
dvander@2320
    48
	switch (hdr.compression)
dvander@2320
    49
	{
dvander@2320
    50
	case SPFILE_COMPRESSION_GZ:
dvander@2320
    51
		{
dvander@2320
    52
			uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
dvander@2320
    53
			uint32_t compsize = hdr.disksize - hdr.dataoffs;
dvander@2320
    54
			uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
dvander@2320
    55
			uLongf destlen = uncompsize;
dvander@2320
    56
dvander@2320
    57
			char *tempbuf = (char *)malloc(compsize);
dvander@2320
    58
			void *uncompdata = malloc(uncompsize);
dvander@2320
    59
			void *sectheader = malloc(sectsize);
dvander@2320
    60
dvander@2320
    61
			fread(sectheader, sectsize, 1, fp);
dvander@2320
    62
			fread(tempbuf, compsize, 1, fp);
dvander@2320
    63
dvander@2320
    64
			z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
dvander@2320
    65
			free(tempbuf);
dvander@2320
    66
			if (z_result != Z_OK)
dvander@2320
    67
			{
dvander@2320
    68
				free(sectheader);
dvander@2320
    69
				free(uncompdata);
dvander@2320
    70
				error = SP_ERROR_DECOMPRESSOR;
dvander@2320
    71
				goto return_error;
dvander@2320
    72
			}
dvander@2320
    73
dvander@2320
    74
			base = (uint8_t *)malloc(hdr.imagesize);
dvander@2320
    75
			memcpy(base, &hdr, sizeof(sp_file_hdr_t));
dvander@2320
    76
			memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
dvander@2320
    77
			free(sectheader);
dvander@2320
    78
			memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
dvander@2320
    79
			free(uncompdata);
dvander@2320
    80
			break;
dvander@2320
    81
		}
dvander@2320
    82
	case SPFILE_COMPRESSION_NONE:
dvander@2320
    83
		{
dvander@2320
    84
			base = (uint8_t *)malloc(hdr.imagesize);
dvander@2320
    85
			rewind(fp);
dvander@2320
    86
			fread(base, hdr.imagesize, 1, fp);
dvander@2320
    87
			break;
dvander@2320
    88
		}
dvander@2320
    89
	default:
dvander@2320
    90
		{
dvander@2320
    91
			error = SP_ERROR_DECOMPRESSOR;
dvander@2320
    92
			goto return_error;
dvander@2320
    93
		}
dvander@2320
    94
	}
dvander@2320
    95
dvander@2320
    96
	plugin = new sp_file_t;
dvander@2320
    97
	memset(plugin, 0, sizeof(sp_file_t));
dvander@2320
    98
	plugin->base = base;
dvander@2320
    99
dvander@2320
   100
	{
dvander@2320
   101
		int set_err;
dvander@2320
   102
		char *nameptr;
dvander@2320
   103
		uint8_t sectnum = 0;
dvander@2320
   104
		sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
dvander@2320
   105
dvander@2320
   106
		plugin->base_size = hdr.imagesize;
dvander@2320
   107
		set_err = SP_ERROR_NONE;
dvander@2320
   108
dvander@2320
   109
		/* We have to read the name section first */
dvander@2320
   110
		for (sectnum = 0; sectnum < hdr.sections; sectnum++)
dvander@2320
   111
		{
dvander@2320
   112
			nameptr = (char *)(base + hdr.stringtab + secptr[sectnum].nameoffs);
dvander@2320
   113
			if (strcmp(nameptr, ".names") == 0)
dvander@2320
   114
			{
dvander@2320
   115
				plugin->stringbase = (const char *)(base + secptr[sectnum].dataoffs);
dvander@2320
   116
				break;
dvander@2320
   117
			}
dvander@2320
   118
		}
dvander@2320
   119
dvander@2320
   120
		sectnum = 0;
dvander@2320
   121
dvander@2320
   122
		/* Now read the rest of the sections */
dvander@2320
   123
		while (sectnum < hdr.sections)
dvander@2320
   124
		{
dvander@2320
   125
			nameptr = (char *)(base + hdr.stringtab + secptr->nameoffs);
dvander@2320
   126
dvander@2320
   127
			if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
dvander@2320
   128
			{
dvander@2320
   129
				sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
dvander@2320
   130
dvander@2320
   131
				if (cod->codeversion < SP_CODEVERS_JIT1)
dvander@2320
   132
				{
dvander@2320
   133
					error = SP_ERROR_CODE_TOO_OLD;
dvander@2320
   134
					goto return_error;
dvander@2320
   135
				}
dvander@2320
   136
				else if (cod->codeversion > SP_CODEVERS_JIT2)
dvander@2320
   137
				{
dvander@2320
   138
					error = SP_ERROR_CODE_TOO_NEW;
dvander@2320
   139
					goto return_error;
dvander@2320
   140
				}
dvander@2320
   141
dvander@2320
   142
				plugin->pcode = base + secptr->dataoffs + cod->code;
dvander@2320
   143
				plugin->pcode_size = cod->codesize;
dvander@2320
   144
				plugin->flags = cod->flags;
dvander@2320
   145
				plugin->pcode_version = cod->codeversion;
dvander@2320
   146
			}
dvander@2320
   147
			else if (!(plugin->data) && !strcmp(nameptr, ".data"))
dvander@2320
   148
			{
dvander@2320
   149
				sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
dvander@2320
   150
				plugin->data = base + secptr->dataoffs + dat->data;
dvander@2320
   151
				plugin->data_size = dat->datasize;
dvander@2320
   152
				plugin->mem_size = dat->memsize;
dvander@2320
   153
			}
dvander@2320
   154
			else if ((plugin->publics == NULL) && !strcmp(nameptr, ".publics"))
dvander@2320
   155
			{
dvander@2320
   156
				sp_file_publics_t *publics;
dvander@2320
   157
dvander@2320
   158
				publics = (sp_file_publics_t *)(base + secptr->dataoffs);
dvander@2320
   159
				plugin->num_publics = secptr->size / sizeof(sp_file_publics_t);
dvander@2320
   160
dvander@2320
   161
				if (plugin->num_publics > 0)
dvander@2320
   162
				{
dvander@2320
   163
					plugin->publics = new sp_public_t[plugin->num_publics];
dvander@2320
   164
dvander@2320
   165
					for (uint32_t i = 0; i < plugin->num_publics; i++)
dvander@2320
   166
					{
dvander@2320
   167
						plugin->publics[i].code_offs = publics[i].address;
dvander@2320
   168
						plugin->publics[i].funcid = (i << 1) | 1;
dvander@2320
   169
						plugin->publics[i].name = plugin->stringbase + publics[i].name;
dvander@2320
   170
					}
dvander@2320
   171
				}
dvander@2320
   172
			}
dvander@2320
   173
			else if ((plugin->pubvars == NULL) && !strcmp(nameptr, ".pubvars"))
dvander@2320
   174
			{
dvander@2320
   175
				sp_file_pubvars_t *pubvars;
dvander@2320
   176
dvander@2320
   177
				pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
dvander@2320
   178
				plugin->num_pubvars = secptr->size / sizeof(sp_file_pubvars_t);
dvander@2320
   179
dvander@2320
   180
				if (plugin->num_pubvars > 0)
dvander@2320
   181
				{
dvander@2320
   182
					plugin->pubvars = new sp_pubvar_t[plugin->num_pubvars];
dvander@2320
   183
dvander@2320
   184
					for (uint32_t i = 0; i < plugin->num_pubvars; i++)
dvander@2320
   185
					{
dvander@2320
   186
						plugin->pubvars[i].name = plugin->stringbase + pubvars[i].name;
dvander@2320
   187
						plugin->pubvars[i].offs = (cell_t *)(plugin->data + pubvars[i].address);
dvander@2320
   188
					}
dvander@2320
   189
				}
dvander@2320
   190
			}
dvander@2320
   191
			else if ((plugin->natives == NULL) && !strcmp(nameptr, ".natives"))
dvander@2320
   192
			{
dvander@2320
   193
				sp_file_natives_t *natives;
dvander@2320
   194
dvander@2320
   195
				natives = (sp_file_natives_t *)(base + secptr->dataoffs);
dvander@2320
   196
				plugin->num_natives = secptr->size / sizeof(sp_file_natives_t);
dvander@2320
   197
dvander@2320
   198
				if (plugin->num_natives > 0)
dvander@2320
   199
				{
dvander@2320
   200
					plugin->natives = new sp_native_t[plugin->num_natives];
dvander@2320
   201
dvander@2320
   202
					for (uint32_t i = 0; i < plugin->num_natives; i++)
dvander@2320
   203
					{
dvander@2320
   204
						plugin->natives[i].flags = 0;
dvander@2320
   205
						plugin->natives[i].pfn = NULL;
dvander@2320
   206
						plugin->natives[i].status = SP_NATIVE_UNBOUND;
dvander@2320
   207
						plugin->natives[i].user = NULL;
dvander@2320
   208
						plugin->natives[i].name = plugin->stringbase + natives[i].name;
dvander@2320
   209
					}
dvander@2320
   210
				}
dvander@2320
   211
			}
dvander@2320
   212
			else if ((plugin->tags == NULL) && !strcmp(nameptr, ".tags"))
dvander@2320
   213
			{
dvander@2320
   214
				sp_file_tag_s *tags;
dvander@2320
   215
dvander@2320
   216
				tags = (sp_file_tag_s *)(base + secptr->dataoffs);
dvander@2320
   217
				plugin->num_tags = secptr->size / sizeof(sp_file_tag_s);
dvander@2320
   218
dvander@2320
   219
				if (plugin->num_tags > 0)
dvander@2320
   220
				{
dvander@2320
   221
					plugin->tags = new sp_tag_t[plugin->num_tags];
dvander@2320
   222
dvander@2320
   223
					for (uint32_t i = 0; i < plugin->num_tags; i++)
dvander@2320
   224
					{
dvander@2320
   225
						plugin->tags[i].id = tags[i].tag_id;
dvander@2320
   226
						plugin->tags[i].name = plugin->stringbase + tags[i].name;
dvander@2320
   227
					}
dvander@2320
   228
				}
dvander@2320
   229
			}
dvander@2320
   230
			else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
dvander@2320
   231
			{
dvander@2320
   232
				plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
dvander@2320
   233
			}
dvander@2320
   234
			else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
dvander@2320
   235
			{
dvander@2320
   236
				plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
dvander@2320
   237
			}
dvander@2320
   238
			else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
dvander@2320
   239
			{
dvander@2320
   240
				plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
dvander@2320
   241
			}
dvander@2320
   242
			else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
dvander@2320
   243
			{
dvander@2320
   244
				sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
dvander@2320
   245
				plugin->debug.files_num = inf->num_files;
dvander@2320
   246
				plugin->debug.lines_num = inf->num_lines;
dvander@2320
   247
				plugin->debug.syms_num = inf->num_syms;
dvander@2320
   248
			}
dvander@2325
   249
			else if (plugin->debug.ntv == NULL && !strcmp(nameptr, ".dbg.natives"))
dvander@2325
   250
			{
dvander@2325
   251
				plugin->debug.ntv = (sp_fdbg_ntvtab_s *)(base + secptr->dataoffs);
dvander@2325
   252
			}
dvander@2320
   253
			else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
dvander@2320
   254
			{
dvander@2320
   255
				plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
dvander@2320
   256
			}
dvander@2320
   257
dvander@2320
   258
			secptr++;
dvander@2320
   259
			sectnum++;
dvander@2320
   260
		}
dvander@2320
   261
dvander@2320
   262
		if (plugin->pcode == NULL || plugin->data == NULL)
dvander@2320
   263
		{
dvander@2320
   264
			error = SP_ERROR_FILE_FORMAT;
dvander@2320
   265
			goto return_error;
dvander@2320
   266
		}
dvander@2320
   267
dvander@2320
   268
		if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
dvander@2320
   269
		{
dvander@2320
   270
			error = SP_ERROR_FILE_FORMAT;
dvander@2320
   271
			goto return_error;
dvander@2320
   272
		}
dvander@2320
   273
	}
dvander@2320
   274
dvander@2320
   275
	fclose(fp);
dvander@2320
   276
dvander@2320
   277
	return plugin;
dvander@2320
   278
dvander@2320
   279
return_error:
dvander@2320
   280
	Sp_FreePlugin(plugin);
dvander@2320
   281
	*err = error;
dvander@2320
   282
	fclose(fp);
dvander@2320
   283
dvander@2320
   284
	return NULL;
dvander@2320
   285
}
dvander@2320
   286
dvander@2320
   287
sp_fdbg_symbol_t *Sp_FindFunctionSym(sp_file_t *plugin, ucell_t addr)
dvander@2320
   288
{
dvander@2320
   289
	uint32_t iter;
dvander@2320
   290
	sp_fdbg_symbol_t *sym;
dvander@2320
   291
	uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
dvander@2320
   292
dvander@2320
   293
	for (iter = 0; iter < plugin->debug.syms_num; iter++)
dvander@2320
   294
	{
dvander@2320
   295
		sym = (sp_fdbg_symbol_t *)cursor;
dvander@2320
   296
dvander@2320
   297
		if (sym->ident == SP_SYM_FUNCTION
dvander@2320
   298
			&& sym->codestart <= addr
dvander@2320
   299
			&& sym->codeend > addr)
dvander@2320
   300
		{
dvander@2320
   301
			return sym;
dvander@2320
   302
		}
dvander@2320
   303
dvander@2320
   304
		cursor += sizeof(sp_fdbg_symbol_t);
dvander@2320
   305
dvander@2320
   306
		if (sym->dimcount > 0)
dvander@2320
   307
		{
dvander@2320
   308
			cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
dvander@2320
   309
		}
dvander@2320
   310
	}
dvander@2320
   311
dvander@2320
   312
	return NULL;
dvander@2320
   313
}
dvander@2320
   314
dvander@2320
   315
sp_tag_t *Sp_FindTag(sp_file_t *plugin, uint32_t tag_id)
dvander@2320
   316
{
dvander@2320
   317
	for (uint32_t i = 0; i < plugin->num_tags; i++)
dvander@2320
   318
	{
dvander@2320
   319
		if ((plugin->tags[i].id & 0xFFFF) == tag_id)
dvander@2320
   320
		{
dvander@2320
   321
			return &plugin->tags[i];
dvander@2320
   322
		}
dvander@2320
   323
	}
dvander@2320
   324
dvander@2320
   325
	return NULL;
dvander@2320
   326
}