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:
parent
5414f803a8
commit
95351749a6
@ -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
|
||||
|
@ -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) */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user