- Use EmitCallDoSyscall() to call the jump violations function which guarantees 16-byte stack alignment
- Add x64 code for MSVC _asm() blocks, not tested yet.
This commit is contained in:
parent
c174143dc2
commit
71b8fe477d
1 changed files with 89 additions and 42 deletions
|
@ -105,7 +105,8 @@ typedef enum
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
VM_BLOCK_COPY = 0,
|
VM_JMP_VIOLATION = 0,
|
||||||
|
VM_BLOCK_COPY = 1
|
||||||
} ESysCallType;
|
} ESysCallType;
|
||||||
|
|
||||||
static ELastCommand LastCommand;
|
static ELastCommand LastCommand;
|
||||||
|
@ -392,17 +393,20 @@ void EmitMovEDXStack(vm_t *vm, int andit)
|
||||||
|
|
||||||
#define SET_JMPOFS(x) do { buf[(x)] = compiledOfs - ((x) + 1); } while(0)
|
#define SET_JMPOFS(x) do { buf[(x)] = compiledOfs - ((x) + 1); } while(0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
ErrJump
|
||||||
|
Error handler for jump/call to invalid instruction number
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
|
||||||
static void ErrJump(void)
|
static void ErrJump(void)
|
||||||
{
|
{
|
||||||
Com_Error(ERR_DROP, "program tried to execute code outside VM");
|
Com_Error(ERR_DROP, "program tried to execute code outside VM");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ERRJUMP() \
|
|
||||||
EmitRexString(0x48, "B8"); \
|
|
||||||
EmitPtr(ErrJump); \
|
|
||||||
EmitRexString(0x48, "FF D0")
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
DoBlockCopy
|
DoBlockCopy
|
||||||
|
@ -445,11 +449,16 @@ static void DoSyscall(void)
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
mov dword ptr syscallNum, eax
|
mov dword ptr syscallNum, eax
|
||||||
mov dword ptr programStack, esi
|
mov dword ptr programStack, esi
|
||||||
mov dword ptr opStackBase, edi
|
mov dword ptr opStackOfs, ebx
|
||||||
mov dword ptr opStackOfs, ebx
|
#ifdef idx64
|
||||||
mov dword ptr arg, ecx
|
mov qword ptr opStackBase, rdi
|
||||||
|
mov qword ptr arg, rcx
|
||||||
|
#else
|
||||||
|
mov dword ptr opStackBase, edi
|
||||||
|
mov dword ptr arg, ecx
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
|
@ -491,6 +500,9 @@ static void DoSyscall(void)
|
||||||
{
|
{
|
||||||
switch(syscallNum)
|
switch(syscallNum)
|
||||||
{
|
{
|
||||||
|
case VM_JMP_VIOLATION:
|
||||||
|
ErrJump();
|
||||||
|
break;
|
||||||
case VM_BLOCK_COPY:
|
case VM_BLOCK_COPY:
|
||||||
if(opStackOfs < 1)
|
if(opStackOfs < 1)
|
||||||
Com_Error(ERR_DROP, "VM_BLOCK_COPY failed due to corrupted opStack");
|
Com_Error(ERR_DROP, "VM_BLOCK_COPY failed due to corrupted opStack");
|
||||||
|
@ -504,6 +516,19 @@ static void DoSyscall(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
EmitCallRel
|
||||||
|
Relative call to vm->codeBase + callOfs
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
|
||||||
|
void EmitCallRel(vm_t *vm, int callOfs)
|
||||||
|
{
|
||||||
|
EmitString("E8"); // call 0x12345678
|
||||||
|
Emit4(callOfs - compiledOfs - 4);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
EmitCallDoSyscall
|
EmitCallDoSyscall
|
||||||
|
@ -532,7 +557,7 @@ int EmitCallDoSyscall(vm_t *vm)
|
||||||
EmitRexString(0x48, "89 E5"); // mov ebp, esp
|
EmitRexString(0x48, "89 E5"); // mov ebp, esp
|
||||||
EmitRexString(0x48, "83 E4 F0"); // and esp, 0xFFFFFFF0
|
EmitRexString(0x48, "83 E4 F0"); // and esp, 0xFFFFFFF0
|
||||||
|
|
||||||
// call the syscall wrapper function
|
// call the syscall wrapper function DoSyscall()
|
||||||
|
|
||||||
EmitString("FF D2"); // call edx
|
EmitString("FF D2"); // call edx
|
||||||
|
|
||||||
|
@ -555,15 +580,17 @@ int EmitCallDoSyscall(vm_t *vm)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
EmitCallRel
|
EmitCallErrJump
|
||||||
Relative call to vm->codeBase + callOfs
|
Emit the code that triggers execution of the jump violation handler
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void EmitCallRel(vm_t *vm, int callOfs)
|
static void EmitCallErrJump(vm_t *vm, int sysCallOfs)
|
||||||
{
|
{
|
||||||
EmitString("E8"); // call 0x12345678
|
EmitString("B8"); // mov eax, 0x12345678
|
||||||
Emit4(callOfs - compiledOfs - 4);
|
Emit4(VM_JMP_VIOLATION);
|
||||||
|
|
||||||
|
EmitCallRel(vm, sysCallOfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -582,7 +609,7 @@ int EmitCallProcedure(vm_t *vm, int sysCallOfs)
|
||||||
STACK_POP(1); // sub bl, 1
|
STACK_POP(1); // sub bl, 1
|
||||||
EmitString("85 C0"); // test eax, eax
|
EmitString("85 C0"); // test eax, eax
|
||||||
|
|
||||||
// Jump to syscall code
|
// Jump to syscall code, 1 byte offset should suffice
|
||||||
EmitString("7C"); // jl systemCall
|
EmitString("7C"); // jl systemCall
|
||||||
jmpSystemCall = compiledOfs++;
|
jmpSystemCall = compiledOfs++;
|
||||||
|
|
||||||
|
@ -606,7 +633,7 @@ int EmitCallProcedure(vm_t *vm, int sysCallOfs)
|
||||||
|
|
||||||
// badAddr:
|
// badAddr:
|
||||||
SET_JMPOFS(jmpBadAddr);
|
SET_JMPOFS(jmpBadAddr);
|
||||||
ERRJUMP();
|
EmitCallErrJump(vm, sysCallOfs);
|
||||||
|
|
||||||
/************ System Call ************/
|
/************ System Call ************/
|
||||||
|
|
||||||
|
@ -657,7 +684,7 @@ void EmitCallIns(vm_t *vm, int cdest)
|
||||||
EmitString("E8"); // call 0x12345678
|
EmitString("E8"); // call 0x12345678
|
||||||
|
|
||||||
// we only know all the jump addresses in the third pass
|
// we only know all the jump addresses in the third pass
|
||||||
if(pass)
|
if(pass == 2)
|
||||||
Emit4(vm->instructionPointers[cdest] - compiledOfs - 4);
|
Emit4(vm->instructionPointers[cdest] - compiledOfs - 4);
|
||||||
else
|
else
|
||||||
compiledOfs += 4;
|
compiledOfs += 4;
|
||||||
|
@ -1081,7 +1108,7 @@ void VM_Compile(vm_t *vm, vmHeader_t *header)
|
||||||
int maxLength;
|
int maxLength;
|
||||||
int v;
|
int v;
|
||||||
int i;
|
int i;
|
||||||
int callProcOfsSyscall, callProcOfs;
|
int callProcOfsSyscall, callProcOfs, callDoSyscallOfs;
|
||||||
|
|
||||||
jusedSize = header->instructionCount + 2;
|
jusedSize = header->instructionCount + 2;
|
||||||
|
|
||||||
|
@ -1108,8 +1135,10 @@ void VM_Compile(vm_t *vm, vmHeader_t *header)
|
||||||
|
|
||||||
// Start buffer with x86-VM specific procedures
|
// Start buffer with x86-VM specific procedures
|
||||||
compiledOfs = 0;
|
compiledOfs = 0;
|
||||||
|
|
||||||
|
callDoSyscallOfs = compiledOfs;
|
||||||
callProcOfs = EmitCallDoSyscall(vm);
|
callProcOfs = EmitCallDoSyscall(vm);
|
||||||
callProcOfsSyscall = EmitCallProcedure(vm, 0);
|
callProcOfsSyscall = EmitCallProcedure(vm, callDoSyscallOfs);
|
||||||
vm->entryOfs = compiledOfs;
|
vm->entryOfs = compiledOfs;
|
||||||
|
|
||||||
for(pass=0; pass < 3; pass++) {
|
for(pass=0; pass < 3; pass++) {
|
||||||
|
@ -1622,7 +1651,7 @@ void VM_Compile(vm_t *vm, vmHeader_t *header)
|
||||||
EmitString("B9"); // mov ecx, 0x12345678
|
EmitString("B9"); // mov ecx, 0x12345678
|
||||||
Emit4(Constant4());
|
Emit4(Constant4());
|
||||||
|
|
||||||
EmitCallRel(vm, 0);
|
EmitCallRel(vm, callDoSyscallOfs);
|
||||||
|
|
||||||
EmitCommand(LAST_COMMAND_SUB_BL_2); // sub bl, 2
|
EmitCommand(LAST_COMMAND_SUB_BL_2); // sub bl, 2
|
||||||
break;
|
break;
|
||||||
|
@ -1640,7 +1669,7 @@ void VM_Compile(vm_t *vm, vmHeader_t *header)
|
||||||
EmitString("FF 24 85"); // jmp dword ptr [instructionPointers + eax * 4]
|
EmitString("FF 24 85"); // jmp dword ptr [instructionPointers + eax * 4]
|
||||||
Emit4((intptr_t) vm->instructionPointers);
|
Emit4((intptr_t) vm->instructionPointers);
|
||||||
#endif
|
#endif
|
||||||
ERRJUMP();
|
EmitCallErrJump(vm, callDoSyscallOfs);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
VMFREE_BUFFERS();
|
VMFREE_BUFFERS();
|
||||||
|
@ -1720,7 +1749,7 @@ int VM_CallCompiled(vm_t *vm, int *args)
|
||||||
int stack[OPSTACK_SIZE + 7];
|
int stack[OPSTACK_SIZE + 7];
|
||||||
void *entryPoint;
|
void *entryPoint;
|
||||||
int programCounter;
|
int programCounter;
|
||||||
intptr_t programStack, stackOnEntry;
|
int programStack, stackOnEntry;
|
||||||
byte *image;
|
byte *image;
|
||||||
int *opStack, *opStackOnEntry;
|
int *opStack, *opStackOnEntry;
|
||||||
int opStackOfs;
|
int opStackOfs;
|
||||||
|
@ -1762,22 +1791,40 @@ int VM_CallCompiled(vm_t *vm, int *args)
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
#ifndef idx64
|
|
||||||
pushad
|
|
||||||
#endif
|
|
||||||
mov esi, programStack
|
|
||||||
mov edi, opStack
|
|
||||||
mov ebx, opStackOfs
|
|
||||||
#ifdef idx64
|
#ifdef idx64
|
||||||
#warning look up calling conventions and push/pop if necessary
|
// non-volatile registers according to x64 calling convention
|
||||||
mov r8, vm->instructionPointers
|
push rsi
|
||||||
mov r9, vm->dataBase
|
push rdi
|
||||||
#endif
|
push rbx
|
||||||
call entryPoint
|
|
||||||
mov opStackOfs, ebx
|
mov esi, dword ptr programStack
|
||||||
mov opStack, edi
|
mov rdi, qword ptr opStack
|
||||||
mov programStack, esi
|
mov ebx, dword ptr opStackOfs
|
||||||
#ifndef idx64
|
mov r8, qword ptr vm->instructionPointers
|
||||||
|
mov r9, qword ptr vm->dataBase
|
||||||
|
|
||||||
|
call entryPoint
|
||||||
|
|
||||||
|
mov dword ptr opStackOfs, ebx
|
||||||
|
mov qword ptr opStack, rdi
|
||||||
|
mov dword ptr programStack, esi
|
||||||
|
|
||||||
|
pop rbx
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
#else
|
||||||
|
pushad
|
||||||
|
|
||||||
|
mov esi, dword ptr programStack
|
||||||
|
mov edi, dword ptr opStack
|
||||||
|
mov ebx, dword ptr opStackOfs
|
||||||
|
|
||||||
|
call entryPoint
|
||||||
|
|
||||||
|
mov dword ptr opStackOfs, ebx
|
||||||
|
mov dword ptr opStack, edi
|
||||||
|
mov dword ptr programStack, esi
|
||||||
|
|
||||||
popad
|
popad
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1797,7 +1844,7 @@ int VM_CallCompiled(vm_t *vm, int *args)
|
||||||
"pop %%r15\r\n"
|
"pop %%r15\r\n"
|
||||||
: "+S" (programStack), "+D" (opStack), "+b" (opStackOfs)
|
: "+S" (programStack), "+D" (opStack), "+b" (opStackOfs)
|
||||||
: "g" (vm->instructionPointers), "g" (vm->dataBase), "g" (entryPoint)
|
: "g" (vm->instructionPointers), "g" (vm->dataBase), "g" (entryPoint)
|
||||||
: "cc", "memory", "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%xmm0"
|
: "cc", "memory", "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11"
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue