check all jumps (#4249)

This commit is contained in:
Ludwig Nussel 2009-11-01 19:58:27 +00:00
parent 12189381b5
commit 3d7d2d9f5b

View file

@ -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;