mirror of
https://github.com/DrBeef/ioq3quest.git
synced 2024-11-10 23:02:01 +00:00
check all jumps (#4249)
This commit is contained in:
parent
12189381b5
commit
3d7d2d9f5b
1 changed files with 61 additions and 22 deletions
|
@ -228,14 +228,27 @@ void emit(const char* fmt, ...)
|
||||||
assemble_line(line, strlen(line));
|
assemble_line(line, strlen(line));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_IARG \
|
#define CHECK_INSTR_REG(reg) \
|
||||||
do { if(iarg < 0 || iarg >= header->instructionCount) { \
|
emit("cmpl $%u, %%"#reg, header->instructionCount); \
|
||||||
|
emit("jb jmp_ok_i_%08x", instruction); \
|
||||||
|
emit("movq $%lu, %%rax", (unsigned long)jmpviolation); \
|
||||||
|
emit("callq *%%rax"); \
|
||||||
|
emit("jmp_ok_i_%08x:", instruction);
|
||||||
|
|
||||||
|
#define PREPARE_JMP(reg) \
|
||||||
|
CHECK_INSTR_REG(reg) \
|
||||||
|
emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers); \
|
||||||
|
emit("movl (%%rbx, %%rax, 4), %%eax"); \
|
||||||
|
emit("addq %%r10, %%rax");
|
||||||
|
|
||||||
|
#define CHECK_INSTR(nr) \
|
||||||
|
do { if(nr < 0 || nr >= header->instructionCount) { \
|
||||||
Com_Error( ERR_DROP, \
|
Com_Error( ERR_DROP, \
|
||||||
"%s: jump target out of range at offset %d", __func__, pc ); \
|
"%s: jump target 0x%x out of range at offset %d", __func__, nr, pc ); \
|
||||||
} } while(0)
|
} } while(0)
|
||||||
|
|
||||||
#define JMPIARG \
|
#define JMPIARG \
|
||||||
CHECK_IARG; \
|
CHECK_INSTR(iarg); \
|
||||||
emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[iarg]); \
|
emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[iarg]); \
|
||||||
emit("jmpq *%%rax");
|
emit("jmpq *%%rax");
|
||||||
|
|
||||||
|
@ -371,6 +384,12 @@ static void eop(void)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void jmpviolation(void)
|
||||||
|
{
|
||||||
|
Com_Error(ERR_DROP, "program tried to execute code outside VM\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_VM
|
#ifdef DEBUG_VM
|
||||||
static void memviolation(void)
|
static void memviolation(void)
|
||||||
{
|
{
|
||||||
|
@ -490,19 +509,35 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
|
||||||
emit("ret");
|
emit("ret");
|
||||||
break;
|
break;
|
||||||
case OP_CALL:
|
case OP_CALL:
|
||||||
MAYBE_EMIT_CONST();
|
|
||||||
emit("movl 0(%%rsi), %%eax"); // get instr from stack
|
|
||||||
emit("subq $4, %%rsi");
|
|
||||||
RANGECHECK(edi, 4);
|
RANGECHECK(edi, 4);
|
||||||
emit("movl $%d, 0(%%r8, %%rdi, 1)", instruction+1); // save next instruction
|
emit("movl $%d, 0(%%r8, %%rdi, 1)", instruction+1); // save next instruction
|
||||||
emit("orl %%eax, %%eax");
|
if(got_const)
|
||||||
emit("jl callSyscall%d", instruction);
|
{
|
||||||
emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers);
|
if ((int)const_value < 0)
|
||||||
emit("movl (%%rbx, %%rax, 4), %%eax"); // load new relative jump address
|
goto emit_do_syscall;
|
||||||
emit("addq %%r10, %%rax");
|
|
||||||
emit("callq *%%rax");
|
CHECK_INSTR(const_value);
|
||||||
emit("jmp i_%08x", instruction+1);
|
emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[const_value]);
|
||||||
emit("callSyscall%d:", instruction);
|
emit("callq *%%rax");
|
||||||
|
got_const = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MAYBE_EMIT_CONST();
|
||||||
|
emit("movl 0(%%rsi), %%eax"); // get instr from stack
|
||||||
|
emit("subq $4, %%rsi");
|
||||||
|
|
||||||
|
emit("orl %%eax, %%eax");
|
||||||
|
emit("jl callSyscall%d", instruction);
|
||||||
|
|
||||||
|
PREPARE_JMP(eax);
|
||||||
|
emit("callq *%%rax");
|
||||||
|
|
||||||
|
emit("jmp i_%08x", instruction+1);
|
||||||
|
emit("callSyscall%d:", instruction);
|
||||||
|
}
|
||||||
|
emit_do_syscall:
|
||||||
// emit("fnsave 4(%%rsi)");
|
// emit("fnsave 4(%%rsi)");
|
||||||
emit("push %%rsi");
|
emit("push %%rsi");
|
||||||
emit("push %%rdi");
|
emit("push %%rdi");
|
||||||
|
@ -514,10 +549,15 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
|
||||||
emit("andq $127, %%rbx"); // |
|
emit("andq $127, %%rbx"); // |
|
||||||
emit("subq %%rbx, %%rsp"); // <-+
|
emit("subq %%rbx, %%rsp"); // <-+
|
||||||
emit("push %%rbx");
|
emit("push %%rbx");
|
||||||
emit("negl %%eax"); // convert to actual number
|
if(got_const) {
|
||||||
emit("decl %%eax");
|
got_const = 0;
|
||||||
// first argument already in rdi
|
emit("movq $%u, %%rsi", -1-const_value); // second argument in rsi
|
||||||
emit("movq %%rax, %%rsi"); // second argument in rsi
|
} else {
|
||||||
|
emit("negl %%eax"); // convert to actual number
|
||||||
|
emit("decl %%eax");
|
||||||
|
// first argument already in rdi
|
||||||
|
emit("movq %%rax, %%rsi"); // second argument in rsi
|
||||||
|
}
|
||||||
emit("movq $%lu, %%rax", (unsigned long)callAsmCall);
|
emit("movq $%lu, %%rax", (unsigned long)callAsmCall);
|
||||||
emit("callq *%%rax");
|
emit("callq *%%rax");
|
||||||
emit("pop %%rbx");
|
emit("pop %%rbx");
|
||||||
|
@ -565,9 +605,8 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
|
||||||
} else {
|
} else {
|
||||||
emit("movl 0(%%rsi), %%eax"); // get instr from stack
|
emit("movl 0(%%rsi), %%eax"); // get instr from stack
|
||||||
emit("subq $4, %%rsi");
|
emit("subq $4, %%rsi");
|
||||||
emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers);
|
|
||||||
emit("movl (%%rbx, %%rax, 4), %%eax"); // load new relative jump address
|
PREPARE_JMP(eax);
|
||||||
emit("addq %%r10, %%rax");
|
|
||||||
emit("jmp *%%rax");
|
emit("jmp *%%rax");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue