aboutsummaryrefslogtreecommitdiff
path: root/src/long_mode
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-05-23 21:02:32 -0700
committeriximeow <me@iximeow.net>2020-05-23 21:02:32 -0700
commit79cd0c80a858448713aedd3d607dc363be891d8c (patch)
tree8767f8c59c11c47a7f6996d0655206fa6917b2ba /src/long_mode
parent9b965525afced37e99543e3a412218207a41e793 (diff)
fix important memory decode error in long mode
add tests for modrm/sib decoding, xsave extensions
Diffstat (limited to 'src/long_mode')
-rw-r--r--src/long_mode/mod.rs50
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);