added debug information output

revised file format to make compression global

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%4035
This commit is contained in:
David Anderson 2006-07-19 09:58:18 +00:00
parent 5414f803a8
commit 95351749a6
8 changed files with 471 additions and 175 deletions

View File

@ -205,12 +205,6 @@ typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX
#define AMX_NO_ALIGN
#endif
#if defined __GNUC__
#define PACKEDENTRY __attribute__((packed))
#else
#define PACKEDENTRY
#endif
#if !defined AMX_NO_ALIGN
#if defined LINUX || defined __FreeBSD__
#pragma pack(1) /* structures must be packed (byte-aligned) */
@ -226,8 +220,8 @@ typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX
#endif
typedef struct tagAMX_NATIVE_INFO {
const char _FAR *name PACKEDENTRY;
AMX_NATIVE func PACKEDENTRY;
const char _FAR *name;
AMX_NATIVE func;
} AMX_NATIVE_INFO;
#define AMX_USERNUM 4
@ -235,48 +229,48 @@ typedef struct tagAMX_NATIVE_INFO {
#define sNAMEMAX 31 /* maximum name length of symbol name */
typedef struct tagAMX_FUNCSTUB {
ucell address PACKEDENTRY;
char name[sEXPMAX+1] PACKEDENTRY;
ucell address;
char name[sEXPMAX+1];
} AMX_FUNCSTUB;
typedef struct tagFUNCSTUBNT {
ucell address PACKEDENTRY;
uint32_t nameofs PACKEDENTRY;
ucell address;
uint32_t nameofs;
} AMX_FUNCSTUBNT;
/* The AMX structure is the internal structure for many functions. Not all
* fields are valid at all times; many fields are cached in local variables.
*/
typedef struct tagAMX {
unsigned char _FAR *base PACKEDENTRY; /* points to the AMX header plus the code, optionally also the data */
unsigned char _FAR *data PACKEDENTRY; /* points to separate data+stack+heap, may be NULL */
AMX_CALLBACK callback PACKEDENTRY;
AMX_DEBUG debug PACKEDENTRY; /* debug callback */
unsigned char _FAR *base; /* points to the AMX header plus the code, optionally also the data */
unsigned char _FAR *data; /* points to separate data+stack+heap, may be NULL */
AMX_CALLBACK callback;
AMX_DEBUG debug ; /* debug callback */
/* for external functions a few registers must be accessible from the outside */
cell cip PACKEDENTRY; /* instruction pointer: relative to base + amxhdr->cod */
cell frm PACKEDENTRY; /* stack frame base: relative to base + amxhdr->dat */
cell hea PACKEDENTRY; /* top of the heap: relative to base + amxhdr->dat */
cell hlw PACKEDENTRY; /* bottom of the heap: relative to base + amxhdr->dat */
cell stk PACKEDENTRY; /* stack pointer: relative to base + amxhdr->dat */
cell stp PACKEDENTRY; /* top of the stack: relative to base + amxhdr->dat */
int flags PACKEDENTRY; /* current status, see amx_Flags() */
cell cip ; /* instruction pointer: relative to base + amxhdr->cod */
cell frm ; /* stack frame base: relative to base + amxhdr->dat */
cell hea ; /* top of the heap: relative to base + amxhdr->dat */
cell hlw ; /* bottom of the heap: relative to base + amxhdr->dat */
cell stk ; /* stack pointer: relative to base + amxhdr->dat */
cell stp ; /* top of the stack: relative to base + amxhdr->dat */
int flags ; /* current status, see amx_Flags() */
/* user data */
long usertags[AMX_USERNUM] PACKEDENTRY;
void _FAR *userdata[AMX_USERNUM] PACKEDENTRY;
long usertags[AMX_USERNUM] ;
void _FAR *userdata[AMX_USERNUM] ;
/* native functions can raise an error */
int error PACKEDENTRY;
int error ;
/* passing parameters requires a "count" field */
int paramcount;
/* the sleep opcode needs to store the full AMX status */
cell pri PACKEDENTRY;
cell alt PACKEDENTRY;
cell reset_stk PACKEDENTRY;
cell reset_hea PACKEDENTRY;
cell sysreq_d PACKEDENTRY; /* relocated address/value for the SYSREQ.D opcode */
cell pri ;
cell alt ;
cell reset_stk ;
cell reset_hea ;
cell sysreq_d ; /* relocated address/value for the SYSREQ.D opcode */
#if defined JIT
/* support variables for the JIT */
int reloc_size PACKEDENTRY; /* required temporary buffer for relocations */
long code_size PACKEDENTRY; /* estimated memory footprint of the native code */
int reloc_size ; /* required temporary buffer for relocations */
long code_size ; /* estimated memory footprint of the native code */
#endif
} AMX;
@ -284,23 +278,23 @@ typedef struct tagAMX {
* structure is used internaly.
*/
typedef struct tagAMX_HEADER {
int32_t size PACKEDENTRY; /* size of the "file" */
uint16_t magic PACKEDENTRY; /* signature */
char file_version PACKEDENTRY; /* file format version */
char amx_version PACKEDENTRY; /* required version of the AMX */
int16_t flags PACKEDENTRY;
int16_t defsize PACKEDENTRY; /* size of a definition record */
int32_t cod PACKEDENTRY; /* initial value of COD - code block */
int32_t dat PACKEDENTRY; /* initial value of DAT - data block */
int32_t hea PACKEDENTRY; /* initial value of HEA - start of the heap */
int32_t stp PACKEDENTRY; /* initial value of STP - stack top */
int32_t cip PACKEDENTRY; /* initial value of CIP - the instruction pointer */
int32_t publics PACKEDENTRY; /* offset to the "public functions" table */
int32_t natives PACKEDENTRY; /* offset to the "native functions" table */
int32_t libraries PACKEDENTRY; /* offset to the table of libraries */
int32_t pubvars PACKEDENTRY; /* the "public variables" table */
int32_t tags PACKEDENTRY; /* the "public tagnames" table */
int32_t nametable PACKEDENTRY; /* name table */
int32_t size ; /* size of the "file" */
uint16_t magic ; /* signature */
char file_version ; /* file format version */
char amx_version ; /* required version of the AMX */
int16_t flags ;
int16_t defsize ; /* size of a definition record */
int32_t cod ; /* initial value of COD - code block */
int32_t dat ; /* initial value of DAT - data block */
int32_t hea ; /* initial value of HEA - start of the heap */
int32_t stp ; /* initial value of STP - stack top */
int32_t cip ; /* initial value of CIP - the instruction pointer */
int32_t publics ; /* offset to the "public functions" table */
int32_t natives ; /* offset to the "native functions" table */
int32_t libraries ; /* offset to the table of libraries */
int32_t pubvars ; /* the "public variables" table */
int32_t tags ; /* the "public tagnames" table */
int32_t nametable ; /* name table */
} AMX_HEADER;
#if PAWN_CELL_SIZE==16

View File

@ -42,12 +42,6 @@ extern "C" {
#define AMX_NO_ALIGN
#endif
#if defined __GNUC__
#define PACKED __attribute__((packed))
#else
#define PACKED
#endif
#if !defined AMX_NO_ALIGN
#if defined LINUX || defined __FreeBSD__
#pragma pack(1) /* structures must be packed (byte-aligned) */
@ -63,72 +57,72 @@ extern "C" {
#endif
typedef struct tagAMX_DBG_HDR {
int32_t size PACKED; /* size of the debug information chunk */
uint16_t magic PACKED; /* signature, must be 0xf1ef */
char file_version PACKED; /* file format version */
char amx_version PACKED; /* required version of the AMX */
int16_t flags PACKED; /* currently unused */
int16_t files PACKED; /* number of entries in the "file" table */
int16_t lines PACKED; /* number of entries in the "line" table */
int16_t symbols PACKED; /* number of entries in the "symbol" table */
int16_t tags PACKED; /* number of entries in the "tag" table */
int16_t automatons PACKED; /* number of entries in the "automaton" table */
int16_t states PACKED; /* number of entries in the "state" table */
} PACKED AMX_DBG_HDR;
int32_t size ; /* size of the debug information chunk */
uint16_t magic ; /* signature, must be 0xf1ef */
char file_version ; /* file format version */
char amx_version ; /* required version of the AMX */
int16_t flags ; /* currently unused */
int16_t files ; /* number of entries in the "file" table */
int16_t lines ; /* number of entries in the "line" table */
int16_t symbols ; /* number of entries in the "symbol" table */
int16_t tags ; /* number of entries in the "tag" table */
int16_t automatons ; /* number of entries in the "automaton" table */
int16_t states ; /* number of entries in the "state" table */
} AMX_DBG_HDR;
#define AMX_DBG_MAGIC 0xf1ef
typedef struct tagAMX_DBG_FILE {
ucell address PACKED; /* address in the code segment where generated code (for this file) starts */
const char name[1] PACKED; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_FILE;
ucell address ; /* address in the code segment where generated code (for this file) starts */
const char name[1] ; /* ASCII string, zero-terminated */
} AMX_DBG_FILE;
typedef struct tagAMX_DBG_LINE {
ucell address PACKED; /* address in the code segment where generated code (for this line) starts */
int32_t line PACKED; /* line number */
} PACKED AMX_DBG_LINE;
ucell address ; /* address in the code segment where generated code (for this line) starts */
int32_t line ; /* line number */
} AMX_DBG_LINE;
typedef struct tagAMX_DBG_SYMBOL {
ucell address PACKED; /* address in the data segment or relative to the frame */
int16_t tag PACKED; /* tag for the symbol */
ucell codestart PACKED; /* address in the code segment from which this symbol is valid (in scope) */
ucell codeend PACKED; /* address in the code segment until which this symbol is valid (in scope) */
char ident PACKED; /* kind of symbol (function/variable) */
char vclass PACKED; /* class of symbol (global/local) */
int16_t dim PACKED; /* number of dimensions */
const char name[1] PACKED; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_SYMBOL;
ucell address ; /* address in the data segment or relative to the frame */
int16_t tag ; /* tag for the symbol */
ucell codestart ; /* address in the code segment from which this symbol is valid (in scope) */
ucell codeend ; /* address in the code segment until which this symbol is valid (in scope) */
char ident ; /* kind of symbol (function/variable) */
char vclass ; /* class of symbol (global/local) */
int16_t dim ; /* number of dimensions */
const char name[1] ; /* ASCII string, zero-terminated */
} AMX_DBG_SYMBOL;
typedef struct tagAMX_DBG_SYMDIM {
int16_t tag PACKED; /* tag for the array dimension */
ucell size PACKED; /* size of the array dimension */
} PACKED AMX_DBG_SYMDIM;
int16_t tag ; /* tag for the array dimension */
ucell size ; /* size of the array dimension */
} AMX_DBG_SYMDIM;
typedef struct tagAMX_DBG_TAG {
int16_t tag PACKED; /* tag id */
const char name[1] PACKED; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_TAG;
int16_t tag ; /* tag id */
const char name[1] ; /* ASCII string, zero-terminated */
} AMX_DBG_TAG;
typedef struct tagAMX_DBG_MACHINE {
int16_t automaton PACKED; /* automaton id */
ucell address PACKED; /* address of state variable */
const char name[1] PACKED; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_MACHINE;
int16_t automaton ; /* automaton id */
ucell address ; /* address of state variable */
const char name[1] ; /* ASCII string, zero-terminated */
} AMX_DBG_MACHINE;
typedef struct tagAMX_DBG_STATE {
int16_t state PACKED; /* state id */
int16_t automaton PACKED; /* automaton id */
const char name[1] PACKED; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_STATE;
int16_t state ; /* state id */
int16_t automaton ; /* automaton id */
const char name[1] ; /* ASCII string, zero-terminated */
} AMX_DBG_STATE;
typedef struct tagAMX_DBG {
AMX_DBG_HDR *hdr PACKED; /* points to the AMX_DBG header */
AMX_DBG_FILE **filetbl PACKED;
AMX_DBG_LINE *linetbl PACKED;
AMX_DBG_SYMBOL **symboltbl PACKED;
AMX_DBG_TAG **tagtbl PACKED;
AMX_DBG_MACHINE **automatontbl PACKED;
AMX_DBG_STATE **statetbl PACKED;
} PACKED AMX_DBG;
AMX_DBG_HDR *hdr ; /* points to the AMX_DBG header */
AMX_DBG_FILE **filetbl ;
AMX_DBG_LINE *linetbl ;
AMX_DBG_SYMBOL **symboltbl ;
AMX_DBG_TAG **tagtbl ;
AMX_DBG_MACHINE **automatontbl ;
AMX_DBG_STATE **statetbl ;
} AMX_DBG;
#if !defined iVARIABLE
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */

View File

@ -28,6 +28,11 @@ memfile_t *memfile_creat(const char *name, size_t init)
void memfile_destroy(memfile_t *mf)
{
if (!mf)
{
return;
}
if (!mf->_static)
{
free(mf->name);
@ -69,7 +74,7 @@ size_t memfile_read(memfile_t *mf, void *buffer, size_t maxsize)
return maxsize;
}
int memfile_write(memfile_t *mf, void *buffer, size_t size)
int memfile_write(memfile_t *mf, const void *buffer, size_t size)
{
if (mf->offs + size > mf->size)
{
@ -103,3 +108,9 @@ int memfile_write(memfile_t *mf, void *buffer, size_t size)
return 1;
}
void memfile_reset(memfile_t *mf)
{
mf->usedoffs = 0;
mf->offs = 0;
}

View File

@ -13,11 +13,43 @@ typedef struct memfile_s
int _static;
} memfile_t;
/**
* Creates a new memory file
* init is the initial size in bytes
*/
memfile_t *memfile_creat(const char *name, size_t init);
/**
* Frees the memory associated.
*/
void memfile_destroy(memfile_t *mf);
/**
* Seeks to a given offset (always from start)
*/
void memfile_seek(memfile_t *mf, long seek);
int memfile_write(memfile_t *mf, void *buffer, size_t size);
/**
* Writes to a memory buffer (expands as necessary).
* Returns 1 on success, 0 on failure.
*/
int memfile_write(memfile_t *mf, const void *buffer, size_t size);
/**
* Reads a number of bytes from a memory buffer.
* Returns the number of bytes read until the end was hit.
*/
size_t memfile_read(memfile_t *mf, void *buffer, size_t maxsize);
/**
* Returns the current position from the start.
*/
long memfile_tell(memfile_t *mf);
/**
* Resets all the states of the memory buffer.
* (does not actually free or zero memory)
*/
void memfile_reset(memfile_t *mf);
#endif //_INCLUDE_MEMFILE_H

View File

@ -5,6 +5,7 @@
#include "memfile.h"
#include "sp_file.h"
#include "amx.h"
#include "amxdbg.h"
#include "osdefs.h"
#include "zlib/zlib.h"
@ -22,6 +23,7 @@ enum FileSections
FS_DbgTags,
FS_DbgAutomaton,
FS_DbgState,
FS_DbgStrings,
/* --- */
FS_Number,
};
@ -38,10 +40,14 @@ int main(int argc, char *argv[])
if (pc_compile(argc,argv) == 0)
{
AMX_HEADER *hdr;
AMX_DBG_HDR *dbg = NULL;
int err;
uint32_t i;
sp_file_t *spf;
memfile_t *dbgtab = NULL;
unsigned char *dbgptr = NULL;
uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0};
FILE *fp;
if (bin_file == NULL)
{
@ -83,6 +89,35 @@ int main(int argc, char *argv[])
spfw_add_section(spf, ".names");
if (hdr->flags & AMX_FLAG_DEBUG)
{
dbg = (AMX_DBG_HDR *)((unsigned char *)hdr + hdr->size);
if (dbg->magic != AMX_DBG_MAGIC)
{
pc_printf("Error reading AMX_DBG_HDR, debug data will not be written.");
} else {
dbgtab = memfile_creat("", 512);
dbgptr = (unsigned char *)dbg + sizeof(AMX_DBG_HDR);
if (dbg->files)
{
spfw_add_section(spf, ".dbg.files");
sections[FS_DbgFile] = dbg->files;
}
if (dbg->lines)
{
spfw_add_section(spf, ".dbg.lines");
sections[FS_DbgLine] = dbg->lines;
}
if (dbg->symbols)
{
spfw_add_section(spf, ".dbg.symbols");
sections[FS_DbgSymbol] = dbg->symbols;
}
sections[FS_DbgStrings] = 1;
spfw_add_section(spf, ".dbg.strings");
}
}
spfw_finalize_header(spf);
/**
@ -324,8 +359,6 @@ int main(int argc, char *argv[])
}
}
cod.codesize = (uint32_t)(tptr - tbase);
cod.disksize = cod.codesize;
cod.compression = SPFILE_COMPRESSION_NONE;
sfwrite(&cod, sizeof(cod), 1, spf);
sfwrite(tbase, cod.codesize, 1, spf);
free(tbase);
@ -336,51 +369,19 @@ int main(int argc, char *argv[])
if (sections[FS_Data])
{
sp_file_data_t dat;
unsigned char *dbase;
Bytef *cmp_dbase;
uLong disksize;
int err;
unsigned char *dbase = (unsigned char *)hdr + hdr->dat;
dat.datasize = hdr->hea - hdr->dat;
dat.memsize = hdr->stp;
dat.data = sizeof(dat);
dat.compression = SPFILE_COMPRESSION_GZ;
/* write header */
sfwrite(&dat, sizeof(dat), 1, spf);
if (dat.datasize)
{
dat.disksize = (uint32_t)compressBound((uLong)dat.datasize);
dbase = (unsigned char *)hdr + hdr->dat;
cmp_dbase = (Bytef *)malloc(dat.disksize);
/* compress */
err = compress2(cmp_dbase, &disksize, (Bytef *)dbase, (uLong)dat.datasize, Z_BEST_COMPRESSION);
if (err != Z_OK)
{
pc_printf("Failed to compress DAT section with error: %d\n", err);
pc_printf("Defaulting to no compression.\n");
dat.compression = SPFILE_COMPRESSION_NONE;
dat.disksize = dat.datasize;
/* write header */
sfwrite(&dat, sizeof(dat), 1, spf);
/* write data */
sfwrite(&dbase, dat.datasize, 1, spf);
} else {
dat.disksize = (uint32_t)disksize;
/* write header */
sfwrite(&dat, sizeof(dat), 1, spf);
/* write data */
sfwrite(cmp_dbase, dat.disksize, 1, spf);
}
free(cmp_dbase);
} else {
/* should be 0 */
dat.disksize = dat.datasize;
sfwrite(&dat, sizeof(dat), 1, spf);
/* write data */
sfwrite(dbase, dat.datasize, 1, spf);
}
spfw_next_section(spf);
@ -474,17 +475,186 @@ int main(int argc, char *argv[])
spfw_next_section(spf);
}
if (hdr->flags & AMX_FLAG_DEBUG)
{
if (sections[FS_DbgFile])
{
uint32_t idx;
sp_fdbg_file_t dbgfile;
AMX_DBG_FILE *_ptr;
uint32_t len;
for (idx=0; idx<sections[FS_DbgFile]; idx++)
{
/* get entry info */
_ptr = (AMX_DBG_FILE *)dbgptr;
len = strlen(_ptr->name);
/* store */
dbgfile.addr = _ptr->address;
dbgfile.name = (uint32_t)memfile_tell(dbgtab);
sfwrite(&dbgfile, sizeof(sp_fdbg_file_t), 1, spf);
/* write to tab, then move to next */
memfile_write(dbgtab, _ptr->name, len + 1);
dbgptr += sizeof(AMX_DBG_FILE) + len;
}
spfw_next_section(spf);
}
if (sections[FS_DbgLine])
{
uint32_t idx;
AMX_DBG_LINE *line;
sp_fdbg_line_t dbgline;
for (idx=0; idx<sections[FS_DbgLine]; idx++)
{
/* get entry info */
line = (AMX_DBG_LINE *)dbgptr;
/* store */
dbgline.addr = (uint32_t)line->address;
dbgline.line = (uint32_t)line->line;
sfwrite(&dbgline, sizeof(sp_fdbg_line_t), 1, spf);
/* move to next */
dbgptr += sizeof(AMX_DBG_LINE);
}
spfw_next_section(spf);
}
if (sections[FS_DbgSymbol])
{
uint32_t idx;
uint32_t dnum;
AMX_DBG_SYMBOL *sym;
AMX_DBG_SYMDIM *dim;
sp_fdbg_symbol_t dbgsym;
sp_fdbg_arraydim_t dbgdim;
uint32_t len;
for (idx=0; idx<sections[FS_DbgSymbol]; idx++)
{
/* get entry info */
sym = (AMX_DBG_SYMBOL *)dbgptr;
/* store */
dbgsym.addr = *(int32_t *)&sym->address;
dbgsym.tagid = sym->tag;
dbgsym.codestart = (uint32_t)sym->codestart;
dbgsym.codeend = (uint32_t)sym->codeend;
dbgsym.dimcount = (uint16_t)sym->dim;
dbgsym.vclass = (uint8_t)sym->vclass;
dbgsym.ident = (uint8_t)sym->ident;
dbgsym.name = (uint32_t)memfile_tell(dbgtab);
sfwrite(&dbgsym, sizeof(sp_fdbg_symbol_t), 1, spf);
/* write to tab */
len = strlen(sym->name);
memfile_write(dbgtab, sym->name, len + 1);
/* move to next */
dbgptr += sizeof(AMX_DBG_SYMBOL) + len;
/* look for any dimensions */
for (dnum=0; dnum<dbgsym.dimcount; dnum++)
{
/* get entry info */
dim = (AMX_DBG_SYMDIM *)dbgptr;
/* store */
dbgdim.size = (uint32_t)dim->size;
dbgdim.tagid = dim->tag;
sfwrite(&dbgdim, sizeof(sp_fdbg_arraydim_t), 1, spf);
/* move to next */
dbgptr += sizeof(AMX_DBG_SYMDIM);
}
}
spfw_next_section(spf);
}
if (sections[FS_DbgStrings])
{
sfwrite(dbgtab->base, sizeof(char), dbgtab->usedoffs, spf);
spfw_next_section(spf);
}
}
spfw_finalize_all(spf);
/**
* do compression
* new block for scoping only
*/
if (1)
{
memfile_t *pOrig = (memfile_t *)spf->handle;
sp_file_hdr_t *pHdr;
unsigned char *proper;
size_t size;
Bytef *zcmp;
uLong disksize;
int err = Z_OK;
/* reuse this memory block! */
memfile_reset(bin_file);
/* copy tip of header */
memfile_write(bin_file, pOrig->base, sizeof(sp_file_hdr_t));
/* get pointer to header */
pHdr = (sp_file_hdr_t *)bin_file->base;
/* copy the rest of the header */
memfile_write(bin_file,
(unsigned char *)pOrig->base + sizeof(sp_file_hdr_t),
pHdr->dataoffs - sizeof(sp_file_hdr_t));
size = pHdr->imagesize - pHdr->dataoffs;
proper = (unsigned char *)pOrig->base + pHdr->dataoffs;
/* get initial size estimate */
pHdr->disksize = (uint32_t)compressBound(pHdr->imagesize);
zcmp = (Bytef *)malloc(pHdr->disksize);
if ((err=compress2(zcmp,
&disksize,
(Bytef *)proper,
(uLong)size,
Z_BEST_COMPRESSION))
!= Z_OK)
{
free(zcmp);
pc_printf("Unable to compress (Z): error %d", err);
pc_printf("Falling back to no compression.");
memfile_write(bin_file,
proper,
size);
} else {
pHdr->disksize = (uint32_t)disksize;
pHdr->compression = SPFILE_COMPRESSION_GZ;
memfile_write(bin_file,
(unsigned char *)zcmp,
pHdr->disksize);
free(zcmp);
}
}
spfw_destroy(spf);
memfile_destroy(dbgtab);
/**
* write file
*/
if ((fp=fopen(bin_file->name, "wb")) != NULL)
{
fwrite(bin_file->base, bin_file->usedoffs, 1, fp);
fclose(fp);
} else {
pc_printf("Unable to open %s for writing!", bin_file->name);
}
memfile_destroy(bin_file);
return 0;
write_error:
pc_printf("Error writing to file: %s", bin_file->name);
unlink(bin_file->name);
spfw_destroy(spf);
unlink(bin_file->name);
memfile_destroy(bin_file);
bin_file = NULL;
memfile_destroy(dbgtab);
return 1;
}

View File

@ -2,22 +2,23 @@
#include <string.h>
#include <malloc.h>
#include "sp_file.h"
#include "memfile.h"
void *fp_open(const char *name);
void fp_close(void *handle);
size_t fp_write(const void *buf, size_t size, size_t count, void *handle);
size_t fp_read(void *buf, size_t size, size_t count, void *handle);
size_t fp_getpos(void *handle);
int fp_setpos(void *handle, size_t pos);
void *mf_open(const char *name);
void mf_close(void *handle);
size_t mf_write(const void *buf, size_t size, size_t count, void *handle);
size_t mf_read(void *buf, size_t size, size_t count, void *handle);
size_t mf_getpos(void *handle);
int mf_setpos(void *handle, size_t pos);
sp_writefuncs_t cstd_funcs =
{
fp_open,
fp_close,
fp_write,
fp_read,
fp_getpos,
fp_setpos
mf_open,
mf_close,
mf_write,
mf_read,
mf_getpos,
mf_setpos
};
sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs)
@ -46,6 +47,9 @@ sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs)
pFile->header.stringtab = 0;
pFile->header.version = SPFILE_VERSION;
pFile->header.imagesize = 0;
pFile->header.disksize = 0;
pFile->header.compression = SPFILE_COMPRESSION_NONE;
pFile->header.dataoffs = 0;
pFile->lastsection = 0;
pFile->offsets = NULL;
pFile->sections = NULL;
@ -113,6 +117,7 @@ int spfw_finalize_header(sp_file_t *spf)
size = sizeof(sp_file_section_t) * spf->header.sections;
spf->header.stringtab = sizeof(spf->header) + size;
spf->header.dataoffs = spf->header.stringtab + spf->nametab_idx;
if (spf->funcs.fnWrite(&spf->header, sizeof(spf->header), 1, spf->handle) != 1)
{
return -1;
@ -178,6 +183,7 @@ int spfw_finalize_all(sp_file_t *spf)
}
offs = offsetof(sp_file_hdr_t, imagesize);
spf->header.disksize = spf->funcs.fnGetPos(spf->handle);
spf->header.imagesize = spf->funcs.fnGetPos(spf->handle);
spf->funcs.fnSetPos(spf->handle, offs);
spf->funcs.fnWrite(&spf->header.imagesize, sizeof(uint32_t), 1, spf->handle);
@ -186,6 +192,53 @@ int spfw_finalize_all(sp_file_t *spf)
return 1;
}
/**
* More memory file operations
*/
void *mf_open(const char *name)
{
return memfile_creat(name, 1024);
}
void mf_close(void *handle)
{
memfile_destroy((memfile_t *)handle);
}
size_t mf_write(const void *buf, size_t size, size_t count, void *handle)
{
if (!count)
{
return 0;
}
if (memfile_write((memfile_t *)handle, buf, size*count))
{
return count;
}
return 0;
}
size_t mf_read(void *buf, size_t size, size_t count, void *handle)
{
return memfile_read((memfile_t *)handle, buf, size*count) / count;
}
size_t mf_getpos(void *handle)
{
return (long)memfile_tell((memfile_t *)handle);
}
int mf_setpos(void *handle, size_t pos)
{
memfile_seek((memfile_t *)handle, (long)pos);
return 1;
}
#if UNUSED_FOR_NOW
/**
* Default file operations...
* Based on C standard library calls.
@ -220,5 +273,4 @@ int fp_setpos(void *handle, size_t pos)
{
return fseek((FILE *)handle, (long)pos, SEEK_SET);
}
#endif

View File

@ -74,6 +74,7 @@ int spfw_next_section(sp_file_t *spf);
* Finalizes all sections.
* Cannot be called until all sections are used.
* Must be called with the file pointer at the end.
* Also does compression!
*/
int spfw_finalize_all(sp_file_t *spf);

View File

@ -29,6 +29,9 @@
#pragma pack(1) /* structures must be packed (byte-aligned) */
#endif
#define SPFILE_COMPRESSION_NONE 0
#define SPFILE_COMPRESSION_GZ 1
typedef struct sp_file_section_s
{
uint32_t nameoffs; /* rel offset into global string table */
@ -36,13 +39,21 @@ typedef struct sp_file_section_s
uint32_t size;
} sp_file_section_t;
/**
* If compression is 0, then
* disksize may be 0 to mean that
* only the imagesize is needed.
*/
typedef struct sp_file_hdr_s
{
uint32_t magic;
uint16_t version;
uint32_t imagesize;
uint8_t sections;
uint32_t stringtab;
uint32_t magic; /* magic number */
uint16_t version; /* version code */
uint8_t compression;/* compression algorithm */
uint32_t disksize; /* size on disk */
uint32_t imagesize; /* size in memory */
uint8_t sections; /* number of sections */
uint32_t stringtab; /* offset to string table */
uint32_t dataoffs; /* offset to file proper (any compression starts here) */
} sp_file_hdr_t;
typedef enum
@ -59,21 +70,14 @@ typedef struct sp_file_code_s
uint8_t codeversion; /* version of opcodes supported */
uint16_t flags; /* flags */
uint32_t main; /* address to "main" if any */
uint32_t disksize; /* disksize in bytes */
uint8_t compression; /* compression */
uint32_t code; /* rel offset to code */
} sp_file_code_t;
#define SPFILE_COMPRESSION_NONE 0
#define SPFILE_COMPRESSION_GZ 1
/* section is .data */
typedef struct sp_file_data_s
{
uint32_t datasize; /* size of data section in memory */
uint32_t memsize; /* total mem required (includes data) */
uint32_t disksize; /* size of data on disk (compressed) */
uint8_t compression; /* compression */
uint32_t data; /* file offset to data (helper) */
} sp_file_data_t;
@ -103,6 +107,44 @@ typedef struct sp_file_pubvars_s
#pragma pack(pop) /* reset previous packing */
#endif
/**
* Debug information structures
*/
typedef struct sp_fdbg_file_s
{
uint32_t addr; /* address into code */
uint32_t name; /* offset into debug nametable */
} sp_fdbg_file_t;
typedef struct sp_fdbg_line_s
{
uint32_t addr; /* address into code */
uint32_t line; /* line number */
} sp_fdbg_line_t;
#define SP_SYM_VARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
#define SP_SYM_REFERENCE 2 /* VARIABLE, but must be dereferenced */
#define SP_SYM_ARRAY 3
#define SP_SYM_REFARRAY 4 /* an array passed by reference (i.e. a pointer) */
#define SP_SYM_FUNCTION 9
typedef struct sp_fdbg_symbol_s
{
int32_t addr; /* address rel to DAT or stack frame */
int16_t tagid; /* tag id */
uint32_t codestart; /* start scope validity in code */
uint32_t codeend; /* end scope validity in code */
uint8_t ident; /* variable type */
uint8_t vclass; /* scope class (local vs global) */
uint16_t dimcount; /* dimension count (for arrays) */
uint32_t name; /* offset into debug nametable */
} sp_fdbg_symbol_t;
typedef struct sp_fdbg_arraydim_s
{
int16_t tagid; /* tag id */
uint32_t size; /* size of dimension */
} sp_fdbg_arraydim_t;
/* section is .names */
typedef char * sp_file_nametab_t;