Skip to content

Commit

Permalink
machinst x64: support out-of-bounds memory accesses;
Browse files Browse the repository at this point in the history
  • Loading branch information
bnjbvr committed Jul 16, 2020
1 parent ea33ce9 commit 5a55646
Show file tree
Hide file tree
Showing 6 changed files with 598 additions and 323 deletions.
15 changes: 12 additions & 3 deletions cranelift/codegen/src/isa/x64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,13 +364,15 @@ impl ABIBody for X64ABIBody {
ext_mode,
RegMem::reg(from_reg.to_reg()),
dest_reg,
/* infallible load */ None,
));
}
(ArgumentExtension::Sext, Some(ext_mode)) => {
ret.push(Inst::movsx_rm_r(
ext_mode,
RegMem::reg(from_reg.to_reg()),
dest_reg,
/* infallible load */ None,
));
}
_ => ret.push(Inst::gen_move(dest_reg, from_reg.to_reg(), ty)),
Expand All @@ -394,13 +396,15 @@ impl ABIBody for X64ABIBody {
ext_mode,
RegMem::reg(from_reg.to_reg()),
from_reg,
/* infallible load */ None,
));
}
(ArgumentExtension::Sext, Some(ext_mode)) => {
ret.push(Inst::movsx_rm_r(
ext_mode,
RegMem::reg(from_reg.to_reg()),
from_reg,
/* infallible load */ None,
));
}
_ => {}
Expand Down Expand Up @@ -965,8 +969,13 @@ fn load_stack(mem: impl Into<SyntheticAmode>, into_reg: Writable<Reg>, ty: Type)

let mem = mem.into();
match ext_mode {
Some(ext_mode) => Inst::movsx_rm_r(ext_mode, RegMem::mem(mem), into_reg),
None => Inst::mov64_m_r(mem, into_reg),
Some(ext_mode) => Inst::movsx_rm_r(
ext_mode,
RegMem::mem(mem),
into_reg,
/* infallible load */ None,
),
None => Inst::mov64_m_r(mem, into_reg, None /* infallible */),
}
}

Expand All @@ -982,7 +991,7 @@ fn store_stack(mem: impl Into<SyntheticAmode>, from_reg: Reg, ty: Type) -> Inst
};
let mem = mem.into();
if is_int {
Inst::mov_r_m(size, from_reg, mem)
Inst::mov_r_m(size, from_reg, mem, /* infallible store */ None)
} else {
unimplemented!("f32/f64 store_stack");
}
Expand Down
5 changes: 2 additions & 3 deletions cranelift/codegen/src/isa/x64/inst/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,11 @@ impl RegMem {
pub(crate) fn mem(addr: impl Into<SyntheticAmode>) -> Self {
Self::Mem { addr: addr.into() }
}

/// Add the regs mentioned by `self` to `collector`.
pub(crate) fn get_regs_as_uses(&self, collector: &mut RegUsageCollector) {
match self {
RegMem::Reg { reg } => collector.add_use(*reg),
RegMem::Mem { addr } => addr.get_regs_as_uses(collector),
RegMem::Mem { addr, .. } => addr.get_regs_as_uses(collector),
}
}
}
Expand All @@ -252,7 +251,7 @@ impl ShowWithRRU for RegMem {
fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
match self {
RegMem::Reg { reg } => show_ireg_sized(*reg, mb_rru, size),
RegMem::Mem { addr } => addr.show_rru(mb_rru),
RegMem::Mem { addr, .. } => addr.show_rru(mb_rru),
}
}
}
Expand Down
130 changes: 96 additions & 34 deletions cranelift/codegen/src/isa/x64/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,12 @@ pub(crate) fn emit(
emit_std_reg_reg(sink, LegacyPrefix::None, 0x89, 1, *src, dst.to_reg(), rex);
}

Inst::MovZX_RM_R { ext_mode, src, dst } => {
Inst::MovZX_RM_R {
ext_mode,
src,
dst,
srcloc,
} => {
let (opcodes, num_opcodes, rex_flags) = match ext_mode {
ExtMode::BL => {
// MOVZBL is (REX.W==0) 0F B6 /r
Expand Down Expand Up @@ -849,27 +854,45 @@ pub(crate) fn emit(
*src,
rex_flags,
),
RegMem::Mem { addr: src } => emit_std_reg_mem(
sink,
LegacyPrefix::None,
opcodes,
num_opcodes,
dst.to_reg(),
&src.finalize(state),
rex_flags,
),
RegMem::Mem { addr: src } => {
let src = &src.finalize(state);

if let Some(srcloc) = *srcloc {
// Register the offset at which the actual load instruction starts.
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
}

emit_std_reg_mem(
sink,
LegacyPrefix::None,
opcodes,
num_opcodes,
dst.to_reg(),
src,
rex_flags,
)
}
}
}

Inst::Mov64_M_R { src, dst } => emit_std_reg_mem(
sink,
LegacyPrefix::None,
0x8B,
1,
dst.to_reg(),
&src.finalize(state),
RexFlags::set_w(),
),
Inst::Mov64_M_R { src, dst, srcloc } => {
let src = &src.finalize(state);

if let Some(srcloc) = *srcloc {
// Register the offset at which the actual load instruction starts.
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
}

emit_std_reg_mem(
sink,
LegacyPrefix::None,
0x8B,
1,
dst.to_reg(),
src,
RexFlags::set_w(),
)
}

Inst::LoadEffectiveAddress { addr, dst } => emit_std_reg_mem(
sink,
Expand All @@ -881,7 +904,12 @@ pub(crate) fn emit(
RexFlags::set_w(),
),

Inst::MovSX_RM_R { ext_mode, src, dst } => {
Inst::MovSX_RM_R {
ext_mode,
src,
dst,
srcloc,
} => {
let (opcodes, num_opcodes, rex_flags) = match ext_mode {
ExtMode::BL => {
// MOVSBL is (REX.W==0) 0F BE /r
Expand Down Expand Up @@ -915,21 +943,41 @@ pub(crate) fn emit(
*src,
rex_flags,
),
RegMem::Mem { addr: src } => emit_std_reg_mem(
sink,
LegacyPrefix::None,
opcodes,
num_opcodes,
dst.to_reg(),
&src.finalize(state),
rex_flags,
),

RegMem::Mem { addr: src } => {
let src = &src.finalize(state);

if let Some(srcloc) = *srcloc {
// Register the offset at which the actual load instruction starts.
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
}

emit_std_reg_mem(
sink,
LegacyPrefix::None,
opcodes,
num_opcodes,
dst.to_reg(),
src,
rex_flags,
)
}
}
}

Inst::Mov_R_M { size, src, dst } => {
Inst::Mov_R_M {
size,
src,
dst,
srcloc,
} => {
let dst = &dst.finalize(state);

if let Some(srcloc) = *srcloc {
// Register the offset at which the actual load instruction starts.
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
}

match size {
1 => {
// This is one of the few places where the presence of a
Expand Down Expand Up @@ -1350,7 +1398,7 @@ pub(crate) fn emit(
one_way_jmp(sink, CC::NB, *default_label); // idx unsigned >= jmp table size

// Copy the index (and make sure to clear the high 32-bits lane of tmp2).
let inst = Inst::movzx_rm_r(ExtMode::LQ, RegMem::reg(*idx), *tmp2);
let inst = Inst::movzx_rm_r(ExtMode::LQ, RegMem::reg(*idx), *tmp2, None);
inst.emit(sink, flags, state);

// Load base address of jump table.
Expand All @@ -1366,6 +1414,7 @@ pub(crate) fn emit(
ExtMode::LQ,
RegMem::mem(Amode::imm_reg_reg_shift(0, tmp1.to_reg(), tmp2.to_reg(), 2)),
*tmp2,
None,
);
inst.emit(sink, flags, state);

Expand Down Expand Up @@ -1418,6 +1467,7 @@ pub(crate) fn emit(
op,
src: src_e,
dst: reg_g,
srcloc,
} => {
let rex = RexFlags::clear_w();
let (prefix, opcode) = match op {
Expand All @@ -1432,9 +1482,12 @@ pub(crate) fn emit(
RegMem::Reg { reg: reg_e } => {
emit_std_reg_reg(sink, prefix, opcode, 2, reg_g.to_reg(), *reg_e, rex);
}

RegMem::Mem { addr } => {
let addr = &addr.finalize(state);
if let Some(srcloc) = *srcloc {
// Register the offset at which the actual load instruction starts.
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
}
emit_std_reg_mem(sink, prefix, opcode, 2, reg_g.to_reg(), addr, rex);
}
}
Expand Down Expand Up @@ -1462,14 +1515,19 @@ pub(crate) fn emit(
RegMem::Reg { reg: reg_e } => {
emit_std_reg_reg(sink, prefix, opcode, 2, reg_g.to_reg(), *reg_e, rex);
}

RegMem::Mem { addr } => {
let addr = &addr.finalize(state);
emit_std_reg_mem(sink, prefix, opcode, 2, reg_g.to_reg(), addr, rex);
}
}
}
Inst::XMM_Mov_R_M { op, src, dst } => {

Inst::XMM_Mov_R_M {
op,
src,
dst,
srcloc,
} => {
let rex = RexFlags::clear_w();
let (prefix, opcode) = match op {
SseOpcode::Movd => (LegacyPrefix::_66, 0x0F7E),
Expand All @@ -1478,6 +1536,10 @@ pub(crate) fn emit(
};

let dst = &dst.finalize(state);
if let Some(srcloc) = *srcloc {
// Register the offset at which the actual load instruction starts.
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
}
emit_std_reg_mem(sink, prefix, opcode, 2, *src, dst, rex);
}

Expand Down
Loading

0 comments on commit 5a55646

Please sign in to comment.