dvander@2320: #include dvander@2320: #include dvander@2320: #include dvander@2320: #include "zlib.h" dvander@2320: #include "file_format.h" dvander@2320: dvander@2320: void Sp_FreePlugin(sp_file_t *plugin) dvander@2320: { dvander@2320: if (plugin == NULL) dvander@2320: { dvander@2320: return; dvander@2320: } dvander@2320: dvander@2320: free(plugin->base); dvander@2320: delete [] plugin->publics; dvander@2320: delete [] plugin->pubvars; dvander@2320: delete [] plugin->natives; dvander@2320: delete plugin; dvander@2320: } dvander@2320: dvander@2320: sp_file_t *Sp_ReadPlugin(const char *file, int *err) dvander@2320: { dvander@2320: sp_file_t *plugin; dvander@2320: sp_file_hdr_t hdr; dvander@2320: uint8_t *base; dvander@2320: int z_result; dvander@2320: int error; dvander@2320: dvander@2320: FILE *fp = fopen(file, "rb"); dvander@2320: dvander@2320: plugin = NULL; dvander@2320: dvander@2320: if (!fp) dvander@2320: { dvander@2320: error = SP_ERROR_NOT_FOUND; dvander@2320: goto return_error; dvander@2320: } dvander@2320: dvander@2320: /* Rewind for safety */ dvander@2320: fread(&hdr, sizeof(sp_file_hdr_t), 1, fp); dvander@2320: dvander@2320: if (hdr.magic != SPFILE_MAGIC) dvander@2320: { dvander@2320: error = SP_ERROR_FILE_FORMAT; dvander@2320: goto return_error; dvander@2320: } dvander@2320: dvander@2320: switch (hdr.compression) dvander@2320: { dvander@2320: case SPFILE_COMPRESSION_GZ: dvander@2320: { dvander@2320: uint32_t uncompsize = hdr.imagesize - hdr.dataoffs; dvander@2320: uint32_t compsize = hdr.disksize - hdr.dataoffs; dvander@2320: uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t); dvander@2320: uLongf destlen = uncompsize; dvander@2320: dvander@2320: char *tempbuf = (char *)malloc(compsize); dvander@2320: void *uncompdata = malloc(uncompsize); dvander@2320: void *sectheader = malloc(sectsize); dvander@2320: dvander@2320: fread(sectheader, sectsize, 1, fp); dvander@2320: fread(tempbuf, compsize, 1, fp); dvander@2320: dvander@2320: z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize); dvander@2320: free(tempbuf); dvander@2320: if (z_result != Z_OK) dvander@2320: { dvander@2320: free(sectheader); dvander@2320: free(uncompdata); dvander@2320: error = SP_ERROR_DECOMPRESSOR; dvander@2320: goto return_error; dvander@2320: } dvander@2320: dvander@2320: base = (uint8_t *)malloc(hdr.imagesize); dvander@2320: memcpy(base, &hdr, sizeof(sp_file_hdr_t)); dvander@2320: memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize); dvander@2320: free(sectheader); dvander@2320: memcpy(base + hdr.dataoffs, uncompdata, uncompsize); dvander@2320: free(uncompdata); dvander@2320: break; dvander@2320: } dvander@2320: case SPFILE_COMPRESSION_NONE: dvander@2320: { dvander@2320: base = (uint8_t *)malloc(hdr.imagesize); dvander@2320: rewind(fp); dvander@2320: fread(base, hdr.imagesize, 1, fp); dvander@2320: break; dvander@2320: } dvander@2320: default: dvander@2320: { dvander@2320: error = SP_ERROR_DECOMPRESSOR; dvander@2320: goto return_error; dvander@2320: } dvander@2320: } dvander@2320: dvander@2320: plugin = new sp_file_t; dvander@2320: memset(plugin, 0, sizeof(sp_file_t)); dvander@2320: plugin->base = base; dvander@2320: dvander@2320: { dvander@2320: int set_err; dvander@2320: char *nameptr; dvander@2320: uint8_t sectnum = 0; dvander@2320: sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t)); dvander@2320: dvander@2320: plugin->base_size = hdr.imagesize; dvander@2320: set_err = SP_ERROR_NONE; dvander@2320: dvander@2320: /* We have to read the name section first */ dvander@2320: for (sectnum = 0; sectnum < hdr.sections; sectnum++) dvander@2320: { dvander@2320: nameptr = (char *)(base + hdr.stringtab + secptr[sectnum].nameoffs); dvander@2320: if (strcmp(nameptr, ".names") == 0) dvander@2320: { dvander@2320: plugin->stringbase = (const char *)(base + secptr[sectnum].dataoffs); dvander@2320: break; dvander@2320: } dvander@2320: } dvander@2320: dvander@2320: sectnum = 0; dvander@2320: dvander@2320: /* Now read the rest of the sections */ dvander@2320: while (sectnum < hdr.sections) dvander@2320: { dvander@2320: nameptr = (char *)(base + hdr.stringtab + secptr->nameoffs); dvander@2320: dvander@2320: if (!(plugin->pcode) && !strcmp(nameptr, ".code")) dvander@2320: { dvander@2320: sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs); dvander@2320: dvander@2320: if (cod->codeversion < SP_CODEVERS_JIT1) dvander@2320: { dvander@2320: error = SP_ERROR_CODE_TOO_OLD; dvander@2320: goto return_error; dvander@2320: } dvander@2320: else if (cod->codeversion > SP_CODEVERS_JIT2) dvander@2320: { dvander@2320: error = SP_ERROR_CODE_TOO_NEW; dvander@2320: goto return_error; dvander@2320: } dvander@2320: dvander@2320: plugin->pcode = base + secptr->dataoffs + cod->code; dvander@2320: plugin->pcode_size = cod->codesize; dvander@2320: plugin->flags = cod->flags; dvander@2320: plugin->pcode_version = cod->codeversion; dvander@2320: } dvander@2320: else if (!(plugin->data) && !strcmp(nameptr, ".data")) dvander@2320: { dvander@2320: sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs); dvander@2320: plugin->data = base + secptr->dataoffs + dat->data; dvander@2320: plugin->data_size = dat->datasize; dvander@2320: plugin->mem_size = dat->memsize; dvander@2320: } dvander@2320: else if ((plugin->publics == NULL) && !strcmp(nameptr, ".publics")) dvander@2320: { dvander@2320: sp_file_publics_t *publics; dvander@2320: dvander@2320: publics = (sp_file_publics_t *)(base + secptr->dataoffs); dvander@2320: plugin->num_publics = secptr->size / sizeof(sp_file_publics_t); dvander@2320: dvander@2320: if (plugin->num_publics > 0) dvander@2320: { dvander@2320: plugin->publics = new sp_public_t[plugin->num_publics]; dvander@2320: dvander@2320: for (uint32_t i = 0; i < plugin->num_publics; i++) dvander@2320: { dvander@2320: plugin->publics[i].code_offs = publics[i].address; dvander@2320: plugin->publics[i].funcid = (i << 1) | 1; dvander@2320: plugin->publics[i].name = plugin->stringbase + publics[i].name; dvander@2320: } dvander@2320: } dvander@2320: } dvander@2320: else if ((plugin->pubvars == NULL) && !strcmp(nameptr, ".pubvars")) dvander@2320: { dvander@2320: sp_file_pubvars_t *pubvars; dvander@2320: dvander@2320: pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs); dvander@2320: plugin->num_pubvars = secptr->size / sizeof(sp_file_pubvars_t); dvander@2320: dvander@2320: if (plugin->num_pubvars > 0) dvander@2320: { dvander@2320: plugin->pubvars = new sp_pubvar_t[plugin->num_pubvars]; dvander@2320: dvander@2320: for (uint32_t i = 0; i < plugin->num_pubvars; i++) dvander@2320: { dvander@2320: plugin->pubvars[i].name = plugin->stringbase + pubvars[i].name; dvander@2320: plugin->pubvars[i].offs = (cell_t *)(plugin->data + pubvars[i].address); dvander@2320: } dvander@2320: } dvander@2320: } dvander@2320: else if ((plugin->natives == NULL) && !strcmp(nameptr, ".natives")) dvander@2320: { dvander@2320: sp_file_natives_t *natives; dvander@2320: dvander@2320: natives = (sp_file_natives_t *)(base + secptr->dataoffs); dvander@2320: plugin->num_natives = secptr->size / sizeof(sp_file_natives_t); dvander@2320: dvander@2320: if (plugin->num_natives > 0) dvander@2320: { dvander@2320: plugin->natives = new sp_native_t[plugin->num_natives]; dvander@2320: dvander@2320: for (uint32_t i = 0; i < plugin->num_natives; i++) dvander@2320: { dvander@2320: plugin->natives[i].flags = 0; dvander@2320: plugin->natives[i].pfn = NULL; dvander@2320: plugin->natives[i].status = SP_NATIVE_UNBOUND; dvander@2320: plugin->natives[i].user = NULL; dvander@2320: plugin->natives[i].name = plugin->stringbase + natives[i].name; dvander@2320: } dvander@2320: } dvander@2320: } dvander@2320: else if ((plugin->tags == NULL) && !strcmp(nameptr, ".tags")) dvander@2320: { dvander@2320: sp_file_tag_s *tags; dvander@2320: dvander@2320: tags = (sp_file_tag_s *)(base + secptr->dataoffs); dvander@2320: plugin->num_tags = secptr->size / sizeof(sp_file_tag_s); dvander@2320: dvander@2320: if (plugin->num_tags > 0) dvander@2320: { dvander@2320: plugin->tags = new sp_tag_t[plugin->num_tags]; dvander@2320: dvander@2320: for (uint32_t i = 0; i < plugin->num_tags; i++) dvander@2320: { dvander@2320: plugin->tags[i].id = tags[i].tag_id; dvander@2320: plugin->tags[i].name = plugin->stringbase + tags[i].name; dvander@2320: } dvander@2320: } dvander@2320: } dvander@2320: else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files")) dvander@2320: { dvander@2320: plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs); dvander@2320: } dvander@2320: else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines")) dvander@2320: { dvander@2320: plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs); dvander@2320: } dvander@2320: else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols")) dvander@2320: { dvander@2320: plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs); dvander@2320: } dvander@2320: else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info")) dvander@2320: { dvander@2320: sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs); dvander@2320: plugin->debug.files_num = inf->num_files; dvander@2320: plugin->debug.lines_num = inf->num_lines; dvander@2320: plugin->debug.syms_num = inf->num_syms; dvander@2320: } dvander@2325: else if (plugin->debug.ntv == NULL && !strcmp(nameptr, ".dbg.natives")) dvander@2325: { dvander@2325: plugin->debug.ntv = (sp_fdbg_ntvtab_s *)(base + secptr->dataoffs); dvander@2325: } dvander@2320: else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings")) dvander@2320: { dvander@2320: plugin->debug.stringbase = (const char *)(base + secptr->dataoffs); dvander@2320: } dvander@2320: dvander@2320: secptr++; dvander@2320: sectnum++; dvander@2320: } dvander@2320: dvander@2320: if (plugin->pcode == NULL || plugin->data == NULL) dvander@2320: { dvander@2320: error = SP_ERROR_FILE_FORMAT; dvander@2320: goto return_error; dvander@2320: } dvander@2320: dvander@2320: if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols))) dvander@2320: { dvander@2320: error = SP_ERROR_FILE_FORMAT; dvander@2320: goto return_error; dvander@2320: } dvander@2320: } dvander@2320: dvander@2320: fclose(fp); dvander@2320: dvander@2320: return plugin; dvander@2320: dvander@2320: return_error: dvander@2320: Sp_FreePlugin(plugin); dvander@2320: *err = error; dvander@2320: fclose(fp); dvander@2320: dvander@2320: return NULL; dvander@2320: } dvander@2320: dvander@2320: sp_fdbg_symbol_t *Sp_FindFunctionSym(sp_file_t *plugin, ucell_t addr) dvander@2320: { dvander@2320: uint32_t iter; dvander@2320: sp_fdbg_symbol_t *sym; dvander@2320: uint8_t *cursor = (uint8_t *)(plugin->debug.symbols); dvander@2320: dvander@2320: for (iter = 0; iter < plugin->debug.syms_num; iter++) dvander@2320: { dvander@2320: sym = (sp_fdbg_symbol_t *)cursor; dvander@2320: dvander@2320: if (sym->ident == SP_SYM_FUNCTION dvander@2320: && sym->codestart <= addr dvander@2320: && sym->codeend > addr) dvander@2320: { dvander@2320: return sym; dvander@2320: } dvander@2320: dvander@2320: cursor += sizeof(sp_fdbg_symbol_t); dvander@2320: dvander@2320: if (sym->dimcount > 0) dvander@2320: { dvander@2320: cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount; dvander@2320: } dvander@2320: } dvander@2320: dvander@2320: return NULL; dvander@2320: } dvander@2320: dvander@2320: sp_tag_t *Sp_FindTag(sp_file_t *plugin, uint32_t tag_id) dvander@2320: { dvander@2320: for (uint32_t i = 0; i < plugin->num_tags; i++) dvander@2320: { dvander@2320: if ((plugin->tags[i].id & 0xFFFF) == tag_id) dvander@2320: { dvander@2320: return &plugin->tags[i]; dvander@2320: } dvander@2320: } dvander@2320: dvander@2320: return NULL; dvander@2320: }