diff options
author | tma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-10-13 14:47:00 +0000 |
---|---|---|
committer | tma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-10-13 14:47:00 +0000 |
commit | 2409247307a2fdf0266a8bd7cd39526f06bea0d3 (patch) | |
tree | 3db0f1aeac11c230a2cfeca37c911cb2fec92d04 /code | |
parent | 0ef0850cce08475bd990dd1d3e8865e48995b0ee (diff) | |
download | ioquake3-aero-2409247307a2fdf0266a8bd7cd39526f06bea0d3.tar.gz ioquake3-aero-2409247307a2fdf0266a8bd7cd39526f06bea0d3.zip |
* (Non-trivial) fix to the "opStack corrupted in compiled code" bug
git-svn-id: svn://svn.icculus.org/quake3/trunk@156 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'code')
-rw-r--r-- | code/qcommon/qfiles.h | 6 | ||||
-rw-r--r-- | code/qcommon/vm.c | 90 | ||||
-rw-r--r-- | code/qcommon/vm_local.h | 3 | ||||
-rw-r--r-- | code/qcommon/vm_x86.c | 6 | ||||
-rw-r--r-- | code/tools/asm/q3asm.c | 8 |
5 files changed, 93 insertions, 20 deletions
diff --git a/code/qcommon/qfiles.h b/code/qcommon/qfiles.h index 3fd44ed..1aab668 100644 --- a/code/qcommon/qfiles.h +++ b/code/qcommon/qfiles.h @@ -43,7 +43,8 @@ QVM files ======================================================================== */ -#define VM_MAGIC 0x12721444 +#define VM_MAGIC 0x12721444 +#define VM_MAGIC_VER2 0x12721445 typedef struct { int vmMagic; @@ -56,6 +57,9 @@ typedef struct { int dataLength; int litLength; // ( dataLength - litLength ) should be byteswapped on load int bssLength; // zero filled memory appended to datalength + + //!!! below here is VM_MAGIC_VER2 !!! + int jtrgLength; // number of jump table targets } vmHeader_t; diff --git a/code/qcommon/vm.c b/code/qcommon/vm.c index 080599d..c5f2c75 100644 --- a/code/qcommon/vm.c +++ b/code/qcommon/vm.c @@ -381,7 +381,7 @@ vm_t *VM_Restart( vm_t *vm ) { // load the image Com_Printf( "VM_Restart()\n", filename ); Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name ); - Com_Printf( "Loading vm file %s.\n", filename ); + Com_Printf( "Loading vm file %s...\n", filename ); length = FS_ReadFile( filename, (void **)&header ); if ( !header ) { Com_Error( ERR_DROP, "VM_Restart failed.\n" ); @@ -392,14 +392,28 @@ vm_t *VM_Restart( vm_t *vm ) { ((int *)header)[i] = LittleLong( ((int *)header)[i] ); } - // validate - if ( header->vmMagic != VM_MAGIC - || header->bssLength < 0 - || header->dataLength < 0 - || header->litLength < 0 - || header->codeLength <= 0 ) { - VM_Free( vm ); - Com_Error( ERR_FATAL, "%s has bad header", filename ); + if( header->vmMagic == VM_MAGIC_VER2 ) { + Com_Printf( "...which has vmMagic VM_MAGIC_VER2\n" ); + // validate + if ( header->vmMagic != VM_MAGIC_VER2 + || header->jtrgLength < 0 + || header->bssLength < 0 + || header->dataLength < 0 + || header->litLength < 0 + || header->codeLength <= 0 ) { + VM_Free( vm ); + Com_Error( ERR_FATAL, "%s has bad header", filename ); + } + } else { + // validate + if ( header->vmMagic != VM_MAGIC + || header->bssLength < 0 + || header->dataLength < 0 + || header->litLength < 0 + || header->codeLength <= 0 ) { + VM_Free( vm ); + Com_Error( ERR_FATAL, "%s has bad header", filename ); + } } // round up to next power of 2 so all data operations can @@ -420,6 +434,19 @@ vm_t *VM_Restart( vm_t *vm ) { *(int *)(vm->dataBase + i) = LittleLong( *(int *)(vm->dataBase + i ) ); } + if( header->vmMagic == VM_MAGIC_VER2 ) { + vm->numJumpTableTargets = header->jtrgLength >> 2; + Com_Printf( "Loading %d jump table targets\n", vm->numJumpTableTargets ); + Com_Memset( vm->jumpTableTargets, 0, header->jtrgLength ); + Com_Memcpy( vm->jumpTableTargets, (byte *)header + header->dataOffset + + header->dataLength + header->litLength, header->jtrgLength ); + + // byte swap the longs + for ( i = 0 ; i < header->jtrgLength ; i += 4 ) { + *(int *)(vm->jumpTableTargets + i) = LittleLong( *(int *)(vm->jumpTableTargets + i ) ); + } + } + // free the original file FS_FreeFile( header ); @@ -504,7 +531,7 @@ vm_t *VM_Create( const char *module, long (*systemCalls)(long *), // load the image Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name ); - Com_Printf( "Loading vm file %s.\n", filename ); + Com_Printf( "Loading vm file %s...\n", filename ); length = FS_ReadFile( filename, (void **)&header ); if ( !header ) { Com_Printf( "Failed.\n" ); @@ -517,14 +544,28 @@ vm_t *VM_Create( const char *module, long (*systemCalls)(long *), ((int *)header)[i] = LittleLong( ((int *)header)[i] ); } - // validate - if ( header->vmMagic != VM_MAGIC - || header->bssLength < 0 - || header->dataLength < 0 - || header->litLength < 0 - || header->codeLength <= 0 ) { - VM_Free( vm ); - Com_Error( ERR_FATAL, "%s has bad header", filename ); + if( header->vmMagic == VM_MAGIC_VER2 ) { + Com_Printf( "...which has vmMagic VM_MAGIC_VER2\n" ); + // validate + if ( header->vmMagic != VM_MAGIC_VER2 + || header->jtrgLength < 0 + || header->bssLength < 0 + || header->dataLength < 0 + || header->litLength < 0 + || header->codeLength <= 0 ) { + VM_Free( vm ); + Com_Error( ERR_FATAL, "%s has bad header", filename ); + } + } else { + // validate + if ( header->vmMagic != VM_MAGIC + || header->bssLength < 0 + || header->dataLength < 0 + || header->litLength < 0 + || header->codeLength <= 0 ) { + VM_Free( vm ); + Com_Error( ERR_FATAL, "%s has bad header", filename ); + } } // round up to next power of 2 so all data operations can @@ -546,6 +587,19 @@ vm_t *VM_Create( const char *module, long (*systemCalls)(long *), *(int *)(vm->dataBase + i) = LittleLong( *(int *)(vm->dataBase + i ) ); } + if( header->vmMagic == VM_MAGIC_VER2 ) { + vm->numJumpTableTargets = header->jtrgLength >> 2; + Com_Printf( "Loading %d jump table targets\n", vm->numJumpTableTargets ); + vm->jumpTableTargets = Hunk_Alloc( header->jtrgLength, h_high ); + Com_Memcpy( vm->jumpTableTargets, (byte *)header + header->dataOffset + + header->dataLength + header->litLength, header->jtrgLength ); + + // byte swap the longs + for ( i = 0 ; i < header->jtrgLength ; i += 4 ) { + *(int *)(vm->jumpTableTargets + i) = LittleLong( *(int *)(vm->jumpTableTargets + i ) ); + } + } + // allocate space for the jump targets, which will be filled in by the compile/prep functions vm->instructionPointersLength = header->instructionCount * 4; vm->instructionPointers = Hunk_Alloc( vm->instructionPointersLength, h_high ); diff --git a/code/qcommon/vm_local.h b/code/qcommon/vm_local.h index f6fc043..eb58fff 100644 --- a/code/qcommon/vm_local.h +++ b/code/qcommon/vm_local.h @@ -161,6 +161,9 @@ struct vm_s { // fqpath member added 7/20/02 by T.Ray char fqpath[MAX_QPATH+1] ; + + byte *jumpTableTargets; + int numJumpTableTargets; }; diff --git a/code/qcommon/vm_x86.c b/code/qcommon/vm_x86.c index a46161a..63b3e1b 100644 --- a/code/qcommon/vm_x86.c +++ b/code/qcommon/vm_x86.c @@ -419,6 +419,12 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) { Com_Memset(jused, 0, header->instructionCount+2); + // ensure that the optimisation pass knows about all the jump + // table targets + for( i = 0; i < vm->numJumpTableTargets; i++ ) { + jused[ *(int *)(vm->jumpTableTargets + ( i * sizeof( int ) ) ) ] = 1; + } + for(pass=0;pass<2;pass++) { oc0 = -23423; oc1 = -234354; diff --git a/code/tools/asm/q3asm.c b/code/tools/asm/q3asm.c index 6c529ab..7d88e73 100644 --- a/code/tools/asm/q3asm.c +++ b/code/tools/asm/q3asm.c @@ -135,6 +135,7 @@ typedef enum { DATASEG, // initialized 32 bit data, will be byte swapped LITSEG, // strings BSSSEG, // 0 filled + JTRGSEG, // psuedo-segment that contains only jump table targets NUM_SEGMENTS } segmentName_t; @@ -989,6 +990,8 @@ STAT("ADDRESS"); /* Addresses are 32 bits wide, and therefore go into data segment. */ HackToSegment( DATASEG ); EmitInt( currentSegment, v ); + if( passNumber == 1 && token[ 0 ] == '$' ) // crude test for labels + EmitInt( &segment[ JTRGSEG ], v ); return 1; } return 0; @@ -1375,7 +1378,7 @@ void WriteVmFile( void ) { return; } - header.vmMagic = VM_MAGIC; + header.vmMagic = VM_MAGIC_VER2; header.instructionCount = instructionCount; header.codeOffset = sizeof( header ); header.codeLength = segment[CODESEG].imageUsed; @@ -1383,6 +1386,7 @@ void WriteVmFile( void ) { header.dataLength = segment[DATASEG].imageUsed; header.litLength = segment[LITSEG].imageUsed; header.bssLength = segment[BSSSEG].imageUsed; + header.jtrgLength = segment[JTRGSEG].imageUsed; report( "Writing to %s\n", imageName ); @@ -1392,6 +1396,7 @@ void WriteVmFile( void ) { SafeWrite( f, &segment[CODESEG].image, segment[CODESEG].imageUsed ); SafeWrite( f, &segment[DATASEG].image, segment[DATASEG].imageUsed ); SafeWrite( f, &segment[LITSEG].image, segment[LITSEG].imageUsed ); + SafeWrite( f, &segment[JTRGSEG].image, segment[JTRGSEG].imageUsed ); fclose( f ); } @@ -1417,6 +1422,7 @@ void Assemble( void ) { for ( passNumber = 0 ; passNumber < 2 ; passNumber++ ) { segment[LITSEG].segmentBase = segment[DATASEG].imageUsed; segment[BSSSEG].segmentBase = segment[LITSEG].segmentBase + segment[LITSEG].imageUsed; + segment[JTRGSEG].segmentBase = segment[BSSSEG].segmentBase + segment[BSSSEG].imageUsed; for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) { segment[i].imageUsed = 0; } |