1#![no_std]
2
3const MOD_M: u8 = 0xc0;
5const RM_M: u8 = 0x7;
7const BASE_M: u8 = 0x7;
9const REX_W: u8 = 0x8;
11const MAX_INSN_LEN_X86: usize = 15;
13
14#[cfg(target_arch = "x86")]
15const MAX_INSN_LEN_X86_32: usize = MAX_INSN_LEN_X86;
16
17const MAX_INSN_LEN_X86_64: usize = MAX_INSN_LEN_X86;
18
19#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
21pub struct Error {
22 invalidinstlen: usize,
23}
24
25
26impl Error {
27 pub fn new() -> Self {
28 Self{
29 invalidinstlen: 0,
30 }
31 }
32}
33
34#[derive(Clone, Copy, PartialEq, Eq)]
36pub enum Bits {
37 B16,
38 B32,
39 B64,
40}
41
42#[cfg(target_arch = "x86")]
43pub(crate) fn max_insn_len() -> usize {
44 MAX_INSN_LEN_X86_32
45}
46
47#[cfg(target_arch = "x86_64")]
48pub(crate) fn max_insn_len() -> usize {
49 MAX_INSN_LEN_X86_64
50}
51
52#[inline]
54pub(crate) fn insn_len_x86<T>(insn: *const T, bits: Bits) -> Option<i32> {
55 let mut len: i32 = 0;
56 let mut twobytes: i32 = 0;
57 let mut has_modrm: i32 = 0;
58 let mut operand_bits = Bits::B32;
59 let mut addr_bits = bits;
60 let mut c: *const u8 = insn as _;
61 let mut modrm: u8 = 0;
62 let opcode: u8;
63
64 match unsafe { *c } {
72 0xf0 | 0xf2 | 0xf3 | 0x2e | 0x36 |
73 0x3e | 0x26 | 0x64 | 0x65 | 0x66 | 0x67 => {
74 if unsafe { *c } == 0x66 {
75 operand_bits = Bits::B32;
76 } if unsafe { *c } == 0x67 {
78 addr_bits = if addr_bits == Bits::B32 {
79 Bits::B16
80 } else {
81 Bits::B32
82 };
83 } c = unsafe { c.add(1) };
85 len += 1;
86 },
87
88 _ => {
89
90 },
91 }
92
93
94 if bits == Bits::B64 && unsafe{*c} & 0xf0 == 0x40 { if unsafe {*c} & REX_W != 0 {
96 operand_bits = Bits::B64;
97 }
98 c = unsafe { c.add(1) };
99 len += 1;
100 }
101
102 if unsafe { *c } == 0x0f {
104 twobytes += 1;
105 c = unsafe { c.add(1) };
106 len += 1;
107 } else if (unsafe { *c } == 0x9b &&
123 ( (unsafe { *(c.add(1)) } == 0xd9 && (unsafe { *(c.add(2)) } & MOD_M) != MOD_M && (unsafe { *(c.add(2))} & 0x30) == 0x30) ||
124 (unsafe { *(c.add(1)) } == 0xdb && (unsafe {*(c.add(2)) } == 0xe2 || unsafe { *(c.add(2)) } == 0xe3)) ||
125 (unsafe { *(c.add(1)) } == 0xdd && (unsafe { *(c.add(2)) } & 0x30) == 0x30) ||
126 (unsafe { *(c.add(1)) } == 0xdf && unsafe { *(c.add(2)) } == 0xe0)
127 ))
128 {
129
130
131 c = unsafe { c.add(1) };
132 len += 1;
133 }
134
135 opcode = unsafe { *(c.add(1)) };
136 len += 1;
137
138 if twobytes == 0 &&
151 ((opcode & 0xf4) == 0 || (opcode & 0xf4) == 0x10 ||
152 (opcode & 0xf4) == 0x20 || (opcode & 0xf4) == 0x30 ||
153 opcode == 0x62 || opcode == 0x63 || opcode == 0x69 || opcode == 0x6b ||
154 (opcode & 0xf0) == 0x80 || opcode == 0xc0 || opcode == 0xc1 ||
155 (opcode & 0xfc) == 0xc4 || (opcode & 0xfc) == 0xd0 ||
156 (opcode & 0xf8) == 0xd8 || opcode == 0xf6 || opcode == 0xf7 ||
157 opcode == 0xfe || opcode == 0xff) {
158 has_modrm = 1;
159 }
160 if twobytes !=0 {
168 if !((opcode >= 0x05 && opcode <= 0x09) || opcode == 0x0b ||
169 opcode == 0x0e || (opcode & 0xf8) == 0x30 || opcode == 0x77 ||
170 (opcode & 0xf0) == 0x80 || (opcode >= 0xa0 && opcode <= 0xa2) ||
171 (opcode >= 0xa8 && opcode <= 0xaa) || (opcode & 0xf8) == 0xc8 ||
172 opcode == 0xb9) {
173 has_modrm = 1;
174 }
175 if opcode == 0x38 || opcode == 0x3a {
177 c = unsafe { c.add(1) };
178 len += 1;
179 }
180 if opcode ==0x0f {
182 len += 1;
183 }
184
185 }
186
187 if has_modrm != 0 {
188 len += 1;
189 modrm = unsafe { *(c.add(1)) };
190 assert!(true, "{}", modrm);
191 if addr_bits != Bits::B16 && (modrm & (MOD_M | RM_M)) == 5 {len += 4;
193 }
194 if addr_bits == Bits::B16 && (modrm & (MOD_M | RM_M)) == 6 {len += 2;
196 }
197 if (modrm & MOD_M) == 0x40 { len += 1;
199 }
200 if (modrm & MOD_M) == 0x80 {match addr_bits {
202 Bits::B16 => {
203 len += 2;
204 },
205 _ => {
206 len += 4;
207 },
208 }
209 }
210 if addr_bits != Bits::B16 && (modrm & MOD_M) != MOD_M && (modrm & RM_M) == 4 { len += 1;
213 if (modrm & MOD_M) == 0 && (unsafe { *c } & BASE_M) == 5 {len += 4;
215 }
216 c = unsafe { c.add(1) };
217 let _ = c;
218 }
219 }
220 if twobytes == 0 {
267 if ((opcode & 7) == 4 && (opcode & 0xf0) <= 0x30) ||
269 opcode == 0x6a || opcode == 0x6b || (opcode & 0xf0) == 0x70 ||
270 opcode == 0x80 || opcode == 0x82 || opcode == 0x83 ||
271 opcode == 0xa8 || (opcode & 0xf8) == 0xb0 || opcode == 0xc0 ||
272 opcode == 0xc1 || opcode == 0xc6 || opcode == 0xcd ||
273 opcode == 0xd4 || opcode == 0xd5 || (opcode & 0xf8) == 0xe0 ||
274 opcode == 0xeb || (opcode == 0xf6 && (modrm & 0x30) == 0) {
275 len += 1;
276 }
277
278 if opcode == 0xc2 || opcode == 0xca{
280 len += 2;
281 }
282 if ((opcode & 7) == 5 && (opcode & 0xf0) <= 0x30) ||
284 opcode == 0x68 || opcode == 0x69 || opcode == 0x81 ||
285 opcode == 0xa9 || opcode == 0xc7 || opcode == 0xe8 ||
286 opcode == 0xe9 {
287 match operand_bits {
288 Bits::B16 =>{
289 len += 2;
290 },
291 _ => {
292 len += 4;
293 },
294 }
295 }
296 if (opcode & 0xf8) == 0xb8 || (opcode == 0xf7 && (modrm & 0x30) == 0) {
298 match operand_bits {
299 Bits::B16 => {
300 len += 2;
301 },
302 Bits::B32 => {
303 len += 4;
304 },
305 _ => {
306 len += 8;
307 },
308 }
309 }
310 if (opcode & 0xfc) == 0xa0 {
312 match addr_bits {
313 Bits::B16 => {
314 len += 2;
315 },
316 Bits::B32 => {
317 len += 4;
318 },
319 _ => {
320 len += 8;
321 },
322 }
323 }
324 if opcode == 0xea || opcode == 0x9a {
326 len +=2;
327 match operand_bits {
328 Bits::B16 =>{
329 len += 2;
330 },
331 _ => {
332 len += 4;
333 },
334 }
335
336 }
337 if opcode == 0xc8{
338 len += 3;
339 }
340
341 }else { if (opcode & 0xfc) == 0x70 || opcode == 0xa4 ||
343 opcode == 0xac || opcode == 0xba || opcode == 0xc2 ||
344 (opcode >= 0xc4 && opcode <= 0xc6) {
345 len += 1;
346 }
347 if (opcode & 0xf0) == 0x80 {
349 match operand_bits {
350 Bits::B16 =>{
351 len += 2;
352 },
353 _ => {
354 len += 4;
355 },
356 }
357 }
358 if opcode == 0x3a {
360 len += 1;
361 }
362
363 }
364 if len > max_insn_len() as _ {
366 return None;
367 }
368
369 assert!(true, "{}" ,opcode);
370 Some(len)
371}
372
373
374#[cfg(target_arch = "x86")]
392pub fn arch_insn_len<T>(insn: *const T) -> Result<i32, Error> {
393 match insn_len_x86(insn, Bits::B32) {
394 Some(len) => Ok(len),
395 None => Err(Error::new()),
396 }
397}
398
399
400#[cfg(target_arch = "x86_64")]
418pub fn arch_insn_len<T>(insn: *const T) -> Result<i32, Error> {
419 match insn_len_x86(insn, Bits::B64) {
420 Some(len) => Ok(len),
421 None => Err(Error::new()),
422 }
423}
424
425
426
427#[cfg(test)]
429mod tests {
430 use super::*;
431
432 #[test]
433 fn it_works() {
434 qwb();
435 let results = [0x48, 0x83, 0xEC, 0x28, 0xE8, 0x0B, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x28, 0xE9, 0x7A, 0xFE, 0xFF, 0xFF, 0xcc, 0xcc];
436 let result = results.as_ptr() as *const u8;
438 let mut b = 0;
439 while b < 20 {
440 let len = arch_insn_len(unsafe { result.add(b as _) });
441 match len {
442 Ok(len) => {
443 b += len;
444 if b > 20 {
445 break;
446 }
447 },
448 Err(_) => {
449 b = 0;
450 break
451 },
452 }
453
454
455 }
456 assert_eq!(20, b);
457 assert_eq!(results, [0x48, 0x83, 0xEC, 0x28, 0xE8, 0x0B, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x28, 0xE9, 0x7A, 0xFE, 0xFF, 0xFF, 0xcc, 0xcc])
458 }
459}
460
461
462pub fn qwb () {
463 assert_eq!(3, "qwb".len());
464}