diff options
author | iximeow <me@iximeow.net> | 2020-05-23 21:02:32 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2020-05-23 21:02:32 -0700 |
commit | 79cd0c80a858448713aedd3d607dc363be891d8c (patch) | |
tree | 8767f8c59c11c47a7f6996d0655206fa6917b2ba /src/long_mode/mod.rs | |
parent | 9b965525afced37e99543e3a412218207a41e793 (diff) |
fix important memory decode error in long mode
add tests for modrm/sib decoding, xsave extensions
Diffstat (limited to 'src/long_mode/mod.rs')
-rw-r--r-- | src/long_mode/mod.rs | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 58d4c57..146a535 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -4906,14 +4906,28 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m OperandSpec::DispU32 } else { - let reg = RegSpec::from_parts(0b100, instr.prefixes.rex().x(), addr_width); - instr.modrm_mmm = reg; - - if disp == 0 { - OperandSpec::Deref + if instr.prefixes.rex().x() { + let reg = RegSpec::from_parts(0b100, true, addr_width); + instr.sib_index = reg; + let scale = 1u8 << (sibbyte >> 6); + instr.scale = scale; + + if disp == 0 { + OperandSpec::RegIndexBaseScale + } else { + instr.disp = disp as i64 as u64; + OperandSpec::RegIndexBaseScaleDisp + } } else { - instr.disp = disp as i64 as u64; - OperandSpec::RegDisp + let reg = RegSpec::from_parts(0b101, instr.prefixes.rex().b(), addr_width); + instr.modrm_mmm = reg; + + if disp == 0 { + OperandSpec::Deref + } else { + instr.disp = disp as i64 as u64; + OperandSpec::RegDisp + } } } } else { @@ -4952,11 +4966,25 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m }; if ((sibbyte >> 3) & 7) == 0b100 { - if disp == 0 { - OperandSpec::Deref + if instr.prefixes.rex().x() { + let reg = RegSpec::from_parts(0b100, true, addr_width); + instr.sib_index = reg; + let scale = 1u8 << (sibbyte >> 6); + instr.scale = scale; + + if disp == 0 { + OperandSpec::RegIndexBaseScale + } else { + instr.disp = disp as i64 as u64; + OperandSpec::RegIndexBaseScaleDisp + } } else { - instr.disp = disp as i64 as u64; - OperandSpec::RegDisp + if disp == 0 { + OperandSpec::Deref + } else { + instr.disp = disp as i64 as u64; + OperandSpec::RegDisp + } } } else { instr.sib_index = RegSpec::from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width); |