x86_table: Mark state-altering instructions as JIT block boundaries
These instructions, if included within a compiled JIT block, may alter the state_flags of a block entry (such as whether flat segmentation is used or not), which may invalidate the block that is running - this caused bugs in OpenBSD because of a block like this being compiled: 0xF81F2: 8E DB mov ds, bx 0xF81F4: 8E D3 mov ss, bx 0xF81F6: 66 8B 26 B8 F5 mov esp, dword ptr [0xf5b8] <-- 0xF81FB: 66 89 36 B8 F5 mov dword ptr [0xf5b8], esi <-- The memory accesses implicitly use DS. If we include flat-segmenetation as a flag within state_flags and optimize calls to get_seg based on it, this behavior would cause issues (and did, in OpenBSD). By marking these instructions as block boundaries, we remediate that issue.
This commit is contained in:
parent
4d87bebee9
commit
41c8241d5e
|
@ -19,9 +19,9 @@ const encodings = [
|
|||
{ opcode: 0x0E, os: 1, skip: 1, },
|
||||
{ opcode: 0x0F, os: 1, prefix: 1, },
|
||||
{ opcode: 0x16, os: 1, skip: 1, },
|
||||
{ opcode: 0x17, os: 1, skip: 1, },
|
||||
{ opcode: 0x17, block_boundary: 1, os: 1, skip: 1, },
|
||||
{ opcode: 0x1E, os: 1, skip: 1, },
|
||||
{ opcode: 0x1F, os: 1, skip: 1, },
|
||||
{ opcode: 0x1F, block_boundary: 1, os: 1, skip: 1, },
|
||||
{ opcode: 0x26, prefix: 1, },
|
||||
{ opcode: 0x27, nonfaulting: 1, mask_flags: of, },
|
||||
{ opcode: 0x2E, prefix: 1, },
|
||||
|
@ -97,7 +97,7 @@ const encodings = [
|
|||
|
||||
{ opcode: 0x8C, os: 1, e: 1, skip: 1, },
|
||||
{ opcode: 0x8D, nonfaulting: 1, os: 1, e: 1, only_mem: 1, requires_prefix_call: 1, custom: 1, }, // lea
|
||||
{ opcode: 0x8E, e: 1, skip: 1, },
|
||||
{ opcode: 0x8E, block_boundary: 1, e: 1, skip: 1, },
|
||||
{ opcode: 0x8F, os: 1, e: 1, fixed_g: 0, requires_prefix_call: 1, }, // pop r/m
|
||||
|
||||
{ opcode: 0x90, nonfaulting: 1, },
|
||||
|
@ -144,7 +144,7 @@ const encodings = [
|
|||
{ opcode: 0xC3, block_boundary: 1, os: 1, skip: 1, },
|
||||
|
||||
{ opcode: 0xC4, os: 1, e: 1, skip: 1, },
|
||||
{ opcode: 0xC5, os: 1, e: 1, skip: 1, },
|
||||
{ opcode: 0xC5, block_boundary: 1, os: 1, e: 1, skip: 1, },
|
||||
|
||||
{ opcode: 0xC6, e: 1, fixed_g: 0, nonfaulting: 1, imm8: 1, },
|
||||
{ opcode: 0xC7, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, imm1632: 1, },
|
||||
|
@ -367,7 +367,7 @@ const encodings = [
|
|||
{ opcode: 0x0FC7, e: 1, fixed_g: 1, only_mem: 1, }, // cmpxchg8b (memory)
|
||||
{ opcode: 0x0FC7, e: 1, fixed_g: 6, only_reg: 1, skip: 1, }, // rdrand
|
||||
|
||||
{ opcode: 0x0FB2, os: 1, e: 1, skip: 1, }, // lss, lfs, lgs
|
||||
{ opcode: 0x0FB2, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lss, lfs, lgs
|
||||
{ opcode: 0x0FB4, os: 1, e: 1, skip: 1, },
|
||||
{ opcode: 0x0FB5, os: 1, e: 1, skip: 1, },
|
||||
|
||||
|
|
|
@ -89,12 +89,14 @@ void instr16_17() {
|
|||
adjust_stack_reg(2);
|
||||
//clear_prefixes();
|
||||
//cycle_internal();
|
||||
altered_state();
|
||||
}
|
||||
void instr32_17() {
|
||||
switch_seg(SS, safe_read32s(get_stack_pointer(0)) & 0xFFFF);
|
||||
adjust_stack_reg(4);
|
||||
//clear_prefixes();
|
||||
//cycle_internal();
|
||||
altered_state();
|
||||
}
|
||||
|
||||
DEFINE_MODRM_INSTR_READ_WRITE_8(instr_18, sbb8(___, read_reg8(r)))
|
||||
|
@ -113,10 +115,12 @@ void instr32_1E() { push32(sreg[DS]); }
|
|||
void instr16_1F() {
|
||||
switch_seg(DS, safe_read16(get_stack_pointer(0)));
|
||||
adjust_stack_reg(2);
|
||||
altered_state();
|
||||
}
|
||||
void instr32_1F() {
|
||||
switch_seg(DS, safe_read32s(get_stack_pointer(0)) & 0xFFFF);
|
||||
adjust_stack_reg(4);
|
||||
altered_state();
|
||||
}
|
||||
|
||||
DEFINE_MODRM_INSTR_READ_WRITE_8(instr_20, and8(___, read_reg8(r)))
|
||||
|
@ -567,6 +571,7 @@ void instr_8E_helper(int32_t data, int32_t mod)
|
|||
{
|
||||
dbg_log("mov sreg #ud");
|
||||
}
|
||||
altered_state();
|
||||
}
|
||||
DEFINE_MODRM_INSTR_READ16(instr_8E, instr_8E_helper(___, r))
|
||||
|
||||
|
@ -899,10 +904,12 @@ void instr32_C4_mem(int32_t addr, int32_t r) {
|
|||
void instr16_C5_reg(int32_t _unused1, int32_t _unused2) { trigger_ud(); }
|
||||
void instr16_C5_mem(int32_t addr, int32_t r) {
|
||||
lss16(addr, get_reg16_index(r), DS);
|
||||
altered_state();
|
||||
}
|
||||
void instr32_C5_reg(int32_t _unused1, int32_t _unused2) { trigger_ud(); }
|
||||
void instr32_C5_mem(int32_t addr, int32_t r) {
|
||||
lss32(addr, r, DS);
|
||||
altered_state();
|
||||
}
|
||||
|
||||
void instr_C6_0_reg(int32_t r, int32_t imm) { write_reg8(r, imm); }
|
||||
|
|
|
@ -2241,10 +2241,12 @@ void instr32_0FB1_mem(int32_t addr, int32_t r) {
|
|||
void instr16_0FB2_reg(int32_t unused, int32_t unused2) { trigger_ud(); }
|
||||
void instr16_0FB2_mem(int32_t addr, int32_t r) {
|
||||
lss16(addr, get_reg16_index(r), SS);
|
||||
altered_state();
|
||||
}
|
||||
void instr32_0FB2_reg(int32_t unused, int32_t unused2) { trigger_ud(); }
|
||||
void instr32_0FB2_mem(int32_t addr, int32_t r) {
|
||||
lss32(addr, r, SS);
|
||||
altered_state();
|
||||
}
|
||||
|
||||
void instr16_0FB3_reg(int32_t r1, int32_t r2) { write_reg16(r1, btr_reg(read_reg16(r1), read_reg16(r2) & 15)); }
|
||||
|
|
Loading…
Reference in a new issue