Index: vm_x86.c =================================================================== --- vm_x86.c (revision 1962) +++ vm_x86.c (working copy) @@ -107,6 +107,10 @@ static ELastCommand LastCommand; +static void ErrJump( void ) { Com_Error( ERR_DROP, "program tried to execute code outside VM\n" ); } + +static void (*const errJumpPtr)(void) = ErrJump; + /* ================= AsmCall @@ -124,13 +128,21 @@ sub edi, 4 test eax,eax jl systemCall + cmp eax, [callMask] + jae badAddr // calling another vm function shl eax,2 add eax, dword ptr [instructionPointers] call dword ptr [eax] mov eax, dword ptr [edi] - and eax, [callMask] ret +badAddr: + call ErrJump + // leave something on the opstack + //add edi, 4 + //mov dword ptr [edi], 0 + //ret + systemCall: // convert negative num to system call number @@ -212,12 +224,18 @@ "subl $4, %edi\n\t" "testl %eax, %eax\n\t" "jl 0f\n\t" + "cmpl " CMANGVAR(callMask) ", %eax\n\t" + "jae 1f\n\t" "shll $2, %eax\n\t" "addl " CMANGVAR(instructionPointers) ", %eax\n\t" "call *(%eax)\n\t" "movl (%edi), %eax\n\t" - "andl " CMANGVAR(callMask) ", %eax\n\t" "ret\n" + "1:\n\t" // bad address, leave something on the opstack + "call " CMANGFUNC(ErrJump) "\n\t" + //"addl $4, %edi\n\t" + //"movl $0, (%edi)\n\t" + //"ret\n\t" "0:\n\t" // system call "notl %eax\n\t" "pushl %ebp\n\t" @@ -249,6 +267,11 @@ return v; } +static int NextConstant4( void ) { + return (code[pc] | (code[pc+1]<<8) | (code[pc+2]<<16) | (code[pc+3]<<24)); +} + + static int Constant1( void ) { int v; @@ -424,6 +447,7 @@ */ void VM_Compile( vm_t *vm, vmHeader_t *header ) { int op; + int op1; int maxLength; int v; int i; @@ -487,7 +511,11 @@ Emit4( Constant4() ); break; case OP_CONST: - if (code[pc+4] == OP_LOAD4) { + if ( !jused[pc+4] ) + op1 = code[pc+4]; + else + op1 = OP_UNDEF; + if ( op1 == OP_LOAD4 ) { EmitAddEDI4(vm); EmitString( "BB" ); // mov ebx, 0x12345678 Emit4( (Constant4()&vm->dataMask) + (int)vm->dataBase); @@ -497,7 +525,7 @@ instruction += 1; break; } - if (code[pc+4] == OP_LOAD2) { + if ( op1 == OP_LOAD2 ) { EmitAddEDI4(vm); EmitString( "BB" ); // mov ebx, 0x12345678 Emit4( (Constant4()&vm->dataMask) + (int)vm->dataBase); @@ -507,7 +535,7 @@ instruction += 1; break; } - if (code[pc+4] == OP_LOAD1) { + if ( op1 == OP_LOAD1 ) { EmitAddEDI4(vm); EmitString( "BB" ); // mov ebx, 0x12345678 Emit4( (Constant4()&vm->dataMask) + (int)vm->dataBase); @@ -517,7 +545,7 @@ instruction += 1; break; } - if (code[pc+4] == OP_STORE4) { + if ( op1 == OP_STORE4 ) { opt = EmitMovEBXEDI(vm, (vm->dataMask & ~3)); EmitString( "B8" ); // mov eax, 0x12345678 Emit4( Constant4() ); @@ -532,7 +560,7 @@ instruction += 1; break; } - if (code[pc+4] == OP_STORE2) { + if ( op1 == OP_STORE2 ) { opt = EmitMovEBXEDI(vm, (vm->dataMask & ~1)); EmitString( "B8" ); // mov eax, 0x12345678 Emit4( Constant4() ); @@ -547,7 +575,7 @@ instruction += 1; break; } - if (code[pc+4] == OP_STORE1) { + if ( op1 == OP_STORE1 ) { opt = EmitMovEBXEDI(vm, vm->dataMask); EmitString( "B8" ); // mov eax, 0x12345678 Emit4( Constant4() ); @@ -562,20 +590,102 @@ instruction += 1; break; } - if (code[pc+4] == OP_ADD) { + if ( op1 == OP_ADD ) { + v = NextConstant4(); + if ( v == 1 ) { + EmitString( "FF 07" ); // inc dword ptr [edi] + pc += 5; // OP_CONST + OP_ADD + instruction += 1; + break; + } EmitString( "81 07" ); // add dword ptr [edi], 0x1234567 Emit4( Constant4() ); pc++; // OP_ADD instruction += 1; break; } - if (code[pc+4] == OP_SUB) { + if ( op1 == OP_SUB ) { + v = NextConstant4(); + if ( v == 1 ) { + EmitString( "FF 0F" ); // dec dword ptr [edi] + pc += 5; // OP_CONST + OP_SUB + instruction += 1; + break; + } EmitString( "81 2F" ); // sub dword ptr [edi], 0x1234567 Emit4( Constant4() ); pc++; // OP_ADD instruction += 1; break; } + if ( op1 == OP_LSH ) { + v = NextConstant4(); + if ( v >=1 && v <= 31 ) { + EmitString( "C1 27" ); // shl dword ptr [edi], 0x12 + Emit1( v ); + pc += 5; // OP_CONST + OP_LSH + instruction += 1; + break; + } + } + if ( op1 == OP_RSHI ) { + v = NextConstant4(); + if ( v >=1 && v <= 31 ) { + EmitString( "C1 3F" ); // sar dword ptr [edi], 0x12 + Emit1( v ); + pc += 5; // OP_CONST + OP_RSHI + instruction += 1; + break; + } + } + if ( op1 == OP_RSHU ) { + v = NextConstant4(); + if ( v >=1 && v <= 31 ) { + EmitString( "C1 2F" ); // shr dword ptr [edi], 0x12 + Emit1( v ); + pc += 5; // OP_CONST + OP_RSHU + instruction += 1; + break; + } + } + if ( op1 == OP_BAND ) { + v = NextConstant4(); + // try to generate shorter version + if ( v >= 0 && v <= 127 ) { + EmitString( "83 27" ); // and dword ptr[edi], 0x7F + Emit1( v ); + } else { + EmitString( "81 27" ); // and dword ptr[edi], 0x7FFFF + Emit4( v ); + } + pc += 5; // OP_CONST + OP_BAND + instruction += 1; + break; + } + if ( op1 == OP_BOR ) { + v = NextConstant4(); + // try to generate shorter version + if ( v >= 0 && v <= 127 ) { + EmitString( "83 0F" ); // or dword ptr[edi], 0x7F + Emit1( v ); + } else { + EmitString( "81 0F" ); // or dword ptr[edi], 0x7FFFF + Emit4( v ); + } + pc += 5; // OP_CONST + OP_BOR + instruction += 1; + break; + } + if ( op1 == OP_JUMP ) { + v = Constant4(); + JUSED(v); + EmitString( "FF 25" ); // jmp dword ptr [instructionPointers + 0x12345678] + Emit4( (int)vm->instructionPointers + v*4 ); + pc += 1; // OP_JUMP + instruction += 1; + break; + } + EmitAddEDI4(vm); EmitString( "C7 07" ); // mov dword ptr [edi], 0x12345678 lastConst = Constant4(); @@ -1076,11 +1186,15 @@ break; case OP_JUMP: - EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - EmitString( "8B 47 04" ); // mov eax,dword ptr [edi+4] - // FIXME: range check - EmitString( "FF 24 85" ); // jmp dword ptr [instructionPointers + eax * 4] + EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 + EmitString( "8B 47 04" ); // mov eax,dword ptr [edi+4] + EmitString( "3B 05" ); // cmp eax,[callMask] + Emit4( (int)&callMask ); + EmitString( "73 07" ); // jae +7 + EmitString( "FF 24 85" ); // jmp dword ptr [instructionPointers + eax * 4] Emit4( (int)vm->instructionPointers ); + EmitString( "FF 15" ); // call errJumpPtr + Emit4( (int)&errJumpPtr ); break; default: VMFREE_BUFFERS(); @@ -1159,8 +1273,10 @@ byte *image; void *opStack; int *oldInstructionPointers; + int oldCallMask; oldInstructionPointers = instructionPointers; + oldCallMask = callMask; currentVM = vm; instructionPointers = vm->instructionPointers; @@ -1168,7 +1284,7 @@ // interpret the code vm->currentlyInterpreting = qtrue; - callMask = vm->dataMask; + callMask = vm->instructionCount; // we might be called recursively, so this might not be the very top programStack = vm->programStack; @@ -1239,6 +1355,7 @@ // in case we were recursively called by another vm instructionPointers = oldInstructionPointers; + callMask = oldCallMask; return *(int *)opStack; }