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

View File

@ -42,12 +42,6 @@ extern "C" {
#define AMX_NO_ALIGN #define AMX_NO_ALIGN
#endif #endif
#if defined __GNUC__
#define PACKED __attribute__((packed))
#else
#define PACKED
#endif
#if !defined AMX_NO_ALIGN #if !defined AMX_NO_ALIGN
#if defined LINUX || defined __FreeBSD__ #if defined LINUX || defined __FreeBSD__
#pragma pack(1) /* structures must be packed (byte-aligned) */ #pragma pack(1) /* structures must be packed (byte-aligned) */
@ -63,72 +57,72 @@ extern "C" {
#endif #endif
typedef struct tagAMX_DBG_HDR { typedef struct tagAMX_DBG_HDR {
int32_t size PACKED; /* size of the debug information chunk */ int32_t size ; /* size of the debug information chunk */
uint16_t magic PACKED; /* signature, must be 0xf1ef */ uint16_t magic ; /* signature, must be 0xf1ef */
char file_version PACKED; /* file format version */ char file_version ; /* file format version */
char amx_version PACKED; /* required version of the AMX */ char amx_version ; /* required version of the AMX */
int16_t flags PACKED; /* currently unused */ int16_t flags ; /* currently unused */
int16_t files PACKED; /* number of entries in the "file" table */ int16_t files ; /* number of entries in the "file" table */
int16_t lines PACKED; /* number of entries in the "line" table */ int16_t lines ; /* number of entries in the "line" table */
int16_t symbols PACKED; /* number of entries in the "symbol" table */ int16_t symbols ; /* number of entries in the "symbol" table */
int16_t tags PACKED; /* number of entries in the "tag" table */ int16_t tags ; /* number of entries in the "tag" table */
int16_t automatons PACKED; /* number of entries in the "automaton" table */ int16_t automatons ; /* number of entries in the "automaton" table */
int16_t states PACKED; /* number of entries in the "state" table */ int16_t states ; /* number of entries in the "state" table */
} PACKED AMX_DBG_HDR; } AMX_DBG_HDR;
#define AMX_DBG_MAGIC 0xf1ef #define AMX_DBG_MAGIC 0xf1ef
typedef struct tagAMX_DBG_FILE { typedef struct tagAMX_DBG_FILE {
ucell address PACKED; /* address in the code segment where generated code (for this file) starts */ ucell address ; /* address in the code segment where generated code (for this file) starts */
const char name[1] PACKED; /* ASCII string, zero-terminated */ const char name[1] ; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_FILE; } AMX_DBG_FILE;
typedef struct tagAMX_DBG_LINE { typedef struct tagAMX_DBG_LINE {
ucell address PACKED; /* address in the code segment where generated code (for this line) starts */ ucell address ; /* address in the code segment where generated code (for this line) starts */
int32_t line PACKED; /* line number */ int32_t line ; /* line number */
} PACKED AMX_DBG_LINE; } AMX_DBG_LINE;
typedef struct tagAMX_DBG_SYMBOL { typedef struct tagAMX_DBG_SYMBOL {
ucell address PACKED; /* address in the data segment or relative to the frame */ ucell address ; /* address in the data segment or relative to the frame */
int16_t tag PACKED; /* tag for the symbol */ int16_t tag ; /* tag for the symbol */
ucell codestart PACKED; /* address in the code segment from which this symbol is valid (in scope) */ ucell codestart ; /* 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) */ ucell codeend ; /* address in the code segment until which this symbol is valid (in scope) */
char ident PACKED; /* kind of symbol (function/variable) */ char ident ; /* kind of symbol (function/variable) */
char vclass PACKED; /* class of symbol (global/local) */ char vclass ; /* class of symbol (global/local) */
int16_t dim PACKED; /* number of dimensions */ int16_t dim ; /* number of dimensions */
const char name[1] PACKED; /* ASCII string, zero-terminated */ const char name[1] ; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_SYMBOL; } AMX_DBG_SYMBOL;
typedef struct tagAMX_DBG_SYMDIM { typedef struct tagAMX_DBG_SYMDIM {
int16_t tag PACKED; /* tag for the array dimension */ int16_t tag ; /* tag for the array dimension */
ucell size PACKED; /* size of the array dimension */ ucell size ; /* size of the array dimension */
} PACKED AMX_DBG_SYMDIM; } AMX_DBG_SYMDIM;
typedef struct tagAMX_DBG_TAG { typedef struct tagAMX_DBG_TAG {
int16_t tag PACKED; /* tag id */ int16_t tag ; /* tag id */
const char name[1] PACKED; /* ASCII string, zero-terminated */ const char name[1] ; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_TAG; } AMX_DBG_TAG;
typedef struct tagAMX_DBG_MACHINE { typedef struct tagAMX_DBG_MACHINE {
int16_t automaton PACKED; /* automaton id */ int16_t automaton ; /* automaton id */
ucell address PACKED; /* address of state variable */ ucell address ; /* address of state variable */
const char name[1] PACKED; /* ASCII string, zero-terminated */ const char name[1] ; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_MACHINE; } AMX_DBG_MACHINE;
typedef struct tagAMX_DBG_STATE { typedef struct tagAMX_DBG_STATE {
int16_t state PACKED; /* state id */ int16_t state ; /* state id */
int16_t automaton PACKED; /* automaton id */ int16_t automaton ; /* automaton id */
const char name[1] PACKED; /* ASCII string, zero-terminated */ const char name[1] ; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_STATE; } AMX_DBG_STATE;
typedef struct tagAMX_DBG { typedef struct tagAMX_DBG {
AMX_DBG_HDR *hdr PACKED; /* points to the AMX_DBG header */ AMX_DBG_HDR *hdr ; /* points to the AMX_DBG header */
AMX_DBG_FILE **filetbl PACKED; AMX_DBG_FILE **filetbl ;
AMX_DBG_LINE *linetbl PACKED; AMX_DBG_LINE *linetbl ;
AMX_DBG_SYMBOL **symboltbl PACKED; AMX_DBG_SYMBOL **symboltbl ;
AMX_DBG_TAG **tagtbl PACKED; AMX_DBG_TAG **tagtbl ;
AMX_DBG_MACHINE **automatontbl PACKED; AMX_DBG_MACHINE **automatontbl ;
AMX_DBG_STATE **statetbl PACKED; AMX_DBG_STATE **statetbl ;
} PACKED AMX_DBG; } AMX_DBG;
#if !defined iVARIABLE #if !defined iVARIABLE
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */ #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) void memfile_destroy(memfile_t *mf)
{ {
if (!mf)
{
return;
}
if (!mf->_static) if (!mf->_static)
{ {
free(mf->name); free(mf->name);
@ -69,7 +74,7 @@ size_t memfile_read(memfile_t *mf, void *buffer, size_t maxsize)
return 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) if (mf->offs + size > mf->size)
{ {
@ -103,3 +108,9 @@ int memfile_write(memfile_t *mf, void *buffer, size_t size)
return 1; 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; int _static;
} memfile_t; } memfile_t;
/**
* Creates a new memory file
* init is the initial size in bytes
*/
memfile_t *memfile_creat(const char *name, size_t init); memfile_t *memfile_creat(const char *name, size_t init);
/**
* Frees the memory associated.
*/
void memfile_destroy(memfile_t *mf); void memfile_destroy(memfile_t *mf);
/**
* Seeks to a given offset (always from start)
*/
void memfile_seek(memfile_t *mf, long seek); 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); 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); 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 #endif //_INCLUDE_MEMFILE_H

View File

@ -5,6 +5,7 @@
#include "memfile.h" #include "memfile.h"
#include "sp_file.h" #include "sp_file.h"
#include "amx.h" #include "amx.h"
#include "amxdbg.h"
#include "osdefs.h" #include "osdefs.h"
#include "zlib/zlib.h" #include "zlib/zlib.h"
@ -22,6 +23,7 @@ enum FileSections
FS_DbgTags, FS_DbgTags,
FS_DbgAutomaton, FS_DbgAutomaton,
FS_DbgState, FS_DbgState,
FS_DbgStrings,
/* --- */ /* --- */
FS_Number, FS_Number,
}; };
@ -38,10 +40,14 @@ int main(int argc, char *argv[])
if (pc_compile(argc,argv) == 0) if (pc_compile(argc,argv) == 0)
{ {
AMX_HEADER *hdr; AMX_HEADER *hdr;
AMX_DBG_HDR *dbg = NULL;
int err; int err;
uint32_t i; uint32_t i;
sp_file_t *spf; 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}; uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0};
FILE *fp;
if (bin_file == NULL) if (bin_file == NULL)
{ {
@ -83,6 +89,35 @@ int main(int argc, char *argv[])
spfw_add_section(spf, ".names"); 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); spfw_finalize_header(spf);
/** /**
@ -324,8 +359,6 @@ int main(int argc, char *argv[])
} }
} }
cod.codesize = (uint32_t)(tptr - tbase); cod.codesize = (uint32_t)(tptr - tbase);
cod.disksize = cod.codesize;
cod.compression = SPFILE_COMPRESSION_NONE;
sfwrite(&cod, sizeof(cod), 1, spf); sfwrite(&cod, sizeof(cod), 1, spf);
sfwrite(tbase, cod.codesize, 1, spf); sfwrite(tbase, cod.codesize, 1, spf);
free(tbase); free(tbase);
@ -336,51 +369,19 @@ int main(int argc, char *argv[])
if (sections[FS_Data]) if (sections[FS_Data])
{ {
sp_file_data_t dat; sp_file_data_t dat;
unsigned char *dbase; unsigned char *dbase = (unsigned char *)hdr + hdr->dat;
Bytef *cmp_dbase;
uLong disksize;
int err;
dat.datasize = hdr->hea - hdr->dat; dat.datasize = hdr->hea - hdr->dat;
dat.memsize = hdr->stp; dat.memsize = hdr->stp;
dat.data = sizeof(dat); dat.data = sizeof(dat);
dat.compression = SPFILE_COMPRESSION_GZ;
/* write header */
sfwrite(&dat, sizeof(dat), 1, spf);
if (dat.datasize) 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 */ /* write data */
sfwrite(&dbase, dat.datasize, 1, spf); 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);
} }
spfw_next_section(spf); spfw_next_section(spf);
@ -474,17 +475,186 @@ int main(int argc, char *argv[])
spfw_next_section(spf); 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); 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); 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; return 0;
write_error: write_error:
pc_printf("Error writing to file: %s", bin_file->name); 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); memfile_destroy(bin_file);
bin_file = NULL; memfile_destroy(dbgtab);
return 1; return 1;
} }

View File

@ -2,22 +2,23 @@
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include "sp_file.h" #include "sp_file.h"
#include "memfile.h"
void *fp_open(const char *name); void *mf_open(const char *name);
void fp_close(void *handle); void mf_close(void *handle);
size_t fp_write(const void *buf, size_t size, size_t count, void *handle); size_t mf_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 mf_read(void *buf, size_t size, size_t count, void *handle);
size_t fp_getpos(void *handle); size_t mf_getpos(void *handle);
int fp_setpos(void *handle, size_t pos); int mf_setpos(void *handle, size_t pos);
sp_writefuncs_t cstd_funcs = sp_writefuncs_t cstd_funcs =
{ {
fp_open, mf_open,
fp_close, mf_close,
fp_write, mf_write,
fp_read, mf_read,
fp_getpos, mf_getpos,
fp_setpos mf_setpos
}; };
sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs) 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.stringtab = 0;
pFile->header.version = SPFILE_VERSION; pFile->header.version = SPFILE_VERSION;
pFile->header.imagesize = 0; pFile->header.imagesize = 0;
pFile->header.disksize = 0;
pFile->header.compression = SPFILE_COMPRESSION_NONE;
pFile->header.dataoffs = 0;
pFile->lastsection = 0; pFile->lastsection = 0;
pFile->offsets = NULL; pFile->offsets = NULL;
pFile->sections = 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; size = sizeof(sp_file_section_t) * spf->header.sections;
spf->header.stringtab = sizeof(spf->header) + size; 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) if (spf->funcs.fnWrite(&spf->header, sizeof(spf->header), 1, spf->handle) != 1)
{ {
return -1; return -1;
@ -178,6 +183,7 @@ int spfw_finalize_all(sp_file_t *spf)
} }
offs = offsetof(sp_file_hdr_t, imagesize); offs = offsetof(sp_file_hdr_t, imagesize);
spf->header.disksize = spf->funcs.fnGetPos(spf->handle);
spf->header.imagesize = spf->funcs.fnGetPos(spf->handle); spf->header.imagesize = spf->funcs.fnGetPos(spf->handle);
spf->funcs.fnSetPos(spf->handle, offs); spf->funcs.fnSetPos(spf->handle, offs);
spf->funcs.fnWrite(&spf->header.imagesize, sizeof(uint32_t), 1, spf->handle); 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; 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... * Default file operations...
* Based on C standard library calls. * 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); 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. * Finalizes all sections.
* Cannot be called until all sections are used. * Cannot be called until all sections are used.
* Must be called with the file pointer at the end. * Must be called with the file pointer at the end.
* Also does compression!
*/ */
int spfw_finalize_all(sp_file_t *spf); int spfw_finalize_all(sp_file_t *spf);

View File

@ -29,6 +29,9 @@
#pragma pack(1) /* structures must be packed (byte-aligned) */ #pragma pack(1) /* structures must be packed (byte-aligned) */
#endif #endif
#define SPFILE_COMPRESSION_NONE 0
#define SPFILE_COMPRESSION_GZ 1
typedef struct sp_file_section_s typedef struct sp_file_section_s
{ {
uint32_t nameoffs; /* rel offset into global string table */ uint32_t nameoffs; /* rel offset into global string table */
@ -36,13 +39,21 @@ typedef struct sp_file_section_s
uint32_t size; uint32_t size;
} sp_file_section_t; } 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 typedef struct sp_file_hdr_s
{ {
uint32_t magic; uint32_t magic; /* magic number */
uint16_t version; uint16_t version; /* version code */
uint32_t imagesize; uint8_t compression;/* compression algorithm */
uint8_t sections; uint32_t disksize; /* size on disk */
uint32_t stringtab; 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; } sp_file_hdr_t;
typedef enum typedef enum
@ -59,21 +70,14 @@ typedef struct sp_file_code_s
uint8_t codeversion; /* version of opcodes supported */ uint8_t codeversion; /* version of opcodes supported */
uint16_t flags; /* flags */ uint16_t flags; /* flags */
uint32_t main; /* address to "main" if any */ 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 */ uint32_t code; /* rel offset to code */
} sp_file_code_t; } sp_file_code_t;
#define SPFILE_COMPRESSION_NONE 0
#define SPFILE_COMPRESSION_GZ 1
/* section is .data */ /* section is .data */
typedef struct sp_file_data_s typedef struct sp_file_data_s
{ {
uint32_t datasize; /* size of data section in memory */ uint32_t datasize; /* size of data section in memory */
uint32_t memsize; /* total mem required (includes data) */ 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) */ uint32_t data; /* file offset to data (helper) */
} sp_file_data_t; } sp_file_data_t;
@ -103,6 +107,44 @@ typedef struct sp_file_pubvars_s
#pragma pack(pop) /* reset previous packing */ #pragma pack(pop) /* reset previous packing */
#endif #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 */ /* section is .names */
typedef char * sp_file_nametab_t; typedef char * sp_file_nametab_t;