diff --git a/sourcepawn/include/sp_file_headers.h b/sourcepawn/include/sp_file_headers.h index c7bd81ae..b83fff38 100644 --- a/sourcepawn/include/sp_file_headers.h +++ b/sourcepawn/include/sp_file_headers.h @@ -52,7 +52,7 @@ typedef struct sp_file_hdr_s 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 aa*/ + uint32_t stringtab; /* offset to string table */ uint32_t dataoffs; /* offset to file proper (any compression starts here) */ } sp_file_hdr_t; diff --git a/sourcepawn/include/sp_vm_types.h b/sourcepawn/include/sp_vm_types.h index 52019b07..9569b924 100644 --- a/sourcepawn/include/sp_vm_types.h +++ b/sourcepawn/include/sp_vm_types.h @@ -12,6 +12,9 @@ typedef int32_t cell_t; #define SP_ERR_NONE 0 #define SP_ERR_FILE_FORMAT 1 /* File format unrecognized */ #define SP_ERR_DECOMPRESSOR 2 /* A decompressor was not found */ +#define SP_ERR_HEAPLOW 3 /* Not enough space left on the heap */ +#define SP_ERR_PARAM 4 /* Invalid parameter */ +#define SP_ERR_INVALID_ADDRESS 5 /* A memory address was not valid */ /********************************************** *** The following structures are reference structures. @@ -183,9 +186,10 @@ typedef struct sp_context_s SPVM_EXEC exec; /* execution base */ cell_t pri; /* PRI register */ cell_t alt; /* ALT register */ - cell_t *data; /* data chunk */ - cell_t *heap; /* pointer after data for start of heap */ - cell_t *sp; /* stack pointer */ + uint8_t *data; /* data chunk */ + cell_t heapbase; /* heap base */ + cell_t hp; /* heap pointer */ + cell_t sp; /* stack pointer */ ucell_t memory; /* total memory size; */ int32_t err; /* error code */ uint32_t pushcount; /* push count */ diff --git a/sourcepawn/vm/msvc8/vm.vcproj b/sourcepawn/vm/msvc8/vm.vcproj index c7aaedd7..66fe7b10 100644 --- a/sourcepawn/vm/msvc8/vm.vcproj +++ b/sourcepawn/vm/msvc8/vm.vcproj @@ -41,13 +41,13 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\..\include" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" UsePrecompiledHeader="0" WarningLevel="3" - Detect64BitPortabilityProblems="true" + Detect64BitPortabilityProblems="false" DebugInformationFormat="4" /> diff --git a/sourcepawn/vm/sp_vm.c b/sourcepawn/vm/sp_vm.c new file mode 100644 index 00000000..2c668530 --- /dev/null +++ b/sourcepawn/vm/sp_vm.c @@ -0,0 +1,107 @@ +#include +#include +#include "sp_vm.h" + +#define CELLBOUNDMAX (INT_MAX/sizeof(cell_t)) +#define STACKMARGIN ((cell_t)(16*sizeof(cell_t))) + +int main() +{ + /** temporary testing area */ + sp_context_t ctx; + cell_t l, *p; + + ctx.data = (uint8_t *)malloc(50000); + ctx.memory = 50000; + ctx.heapbase = 200; + ctx.hp = ctx.heapbase; + ctx.sp = 45000; + + assert(SP_HeapAlloc(&ctx, 500, &l, &p) == SP_ERR_NONE); + assert(SP_HeapPop(&ctx, l) == SP_ERR_NONE); + assert(SP_HeapRelease(&ctx, l) == SP_ERR_NONE); + assert(SP_HeapRelease(&ctx, 4) == SP_ERR_INVALID_ADDRESS); + assert(SP_HeapAlloc(&ctx, 500, &l, &p) == SP_ERR_NONE); + assert(SP_HeapRelease(&ctx, l) == SP_ERR_NONE); + + return 0; +} + +int SP_HeapAlloc(sp_context_t *ctx, unsigned int cells, cell_t *local_addr, cell_t **phys_addr) +{ + cell_t *addr; + ucell_t realmem; + +#if 0 + if (cells > CELLBOUNDMAX) + { + return SP_ERR_PARAM; + } +#else + assert(cells < CELLBOUNDMAX); +#endif + + realmem = cells * sizeof(cell_t); + + /** + * Check if the space between the heap and stack is sufficient. + */ + if ((cell_t)(ctx->sp - ctx->hp - realmem) < STACKMARGIN) + { + return SP_ERR_HEAPLOW; + } + + addr = (cell_t *)(ctx->data + ctx->hp); + /* store size of allocation in cells */ + *addr = (cell_t)cells; + addr++; + ctx->hp += sizeof(cell_t); + + *local_addr = ctx->hp; + + if (phys_addr) + { + *phys_addr = addr; + } + + ctx->hp += realmem; + + return SP_ERR_NONE; +} + +int SP_HeapPop(sp_context_t *ctx, cell_t local_addr) +{ + cell_t cellcount; + cell_t *addr; + + /* check the bounds of this address */ + local_addr -= sizeof(cell_t); + if (local_addr < ctx->heapbase || local_addr >= ctx->sp) + { + return SP_ERR_INVALID_ADDRESS; + } + + addr = (cell_t *)(ctx->data + local_addr); + cellcount = (*addr) * sizeof(cell_t); + /* check if this memory count looks valid */ + if (ctx->hp - cellcount - sizeof(cell_t) != local_addr) + { + return SP_ERR_INVALID_ADDRESS; + } + + ctx->hp = local_addr; + + return SP_ERR_NONE; +} + +int SP_HeapRelease(sp_context_t *ctx, cell_t local_addr) +{ + if (local_addr < ctx->heapbase) + { + return SP_ERR_INVALID_ADDRESS; + } + + ctx->hp = local_addr - sizeof(cell_t); + + return SP_ERR_NONE; +}