1const C_MODRM: u8 = 0x01;
2const C_IMM8: u8 = 0x02;
3const C_IMM16: u8 = 0x04;
4const C_IMM_P66: u8 = 0x10;
5const C_REL8: u8 = 0x20;
6const C_REL32: u8 = 0x40;
7const C_GROUP: u8 = 0x80;
8const C_ERROR: u8 = 0xff;
9
10const PRE_NONE: u8 = 0x01;
11const PRE_F2: u8 = 0x02;
12const PRE_F3: u8 = 0x04;
13const PRE_66: u8 = 0x08;
14const PRE_67: u8 = 0x10;
15const PRE_LOCK: u8 = 0x20;
16const PRE_SEG: u8 = 0x40;
17
18const DELTA_OPCODES: usize = 0x4a;
19const DELTA_FPU_REG: usize = 0xfd;
20const DELTA_FPU_MODRM: usize = 0x104;
21const DELTA_PREFIXES: usize = 0x13c;
22const DELTA_OP_LOCK_OK: usize = 0x1ae;
23const DELTA_OP2_LOCK_OK: usize = 0x1c6;
24const DELTA_OP_ONLY_MEM: usize = 0x1d8;
25const DELTA_OP2_ONLY_MEM: usize = 0x1e7;
26
27const HDE64_TABLE: &[u8] = &[
28 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5,
29 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1,
30 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea,
31 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0,
32 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab,
33 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92,
34 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90,
35 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b,
36 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,
37 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc,
38 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20,
39 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff,
40 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00,
41 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01,
42 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10,
43 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00,
44 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00,
45 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00,
46 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00,
47 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
48 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,
49 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40,
50 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43,
51 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
52 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40,
53 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06,
54 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07,
55 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
56 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10,
57 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00,
58 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb,
59 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff,
60 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09,
61 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff,
62 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08,
63 0x00,0xf0,0x02,0x00
64];
65
66pub const F_MODRM: u32 = 0x00000001;
67pub const F_SIB: u32 = 0x00000002;
68pub const F_IMM8: u32 = 0x00000004;
69pub const F_IMM16: u32 = 0x00000008;
70pub const F_IMM32: u32 = 0x00000010;
71pub const F_IMM64: u32 = 0x00000020;
72pub const F_DISP8: u32 = 0x00000040;
73pub const F_DISP16: u32 = 0x00000080;
74pub const F_DISP32: u32 = 0x00000100;
75pub const F_RELATIVE: u32 = 0x00000200;
76pub const F_ERROR: u32 = 0x00001000;
77pub const F_ERROR_OPCODE: u32 = 0x00002000;
78pub const F_ERROR_LENGTH: u32 = 0x00004000;
79pub const F_ERROR_LOCK: u32 = 0x00008000;
80pub const F_ERROR_OPERAND: u32 = 0x00010000;
81pub const F_PREFIX_REPNZ: u32 = 0x01000000;
82pub const F_PREFIX_REPX: u32 = 0x02000000;
83pub const F_PREFIX_REP: u32 = 0x03000000;
84pub const F_PREFIX_66: u32 = 0x04000000;
85pub const F_PREFIX_67: u32 = 0x08000000;
86pub const F_PREFIX_LOCK: u32 = 0x10000000;
87pub const F_PREFIX_SEG: u32 = 0x20000000;
88pub const F_PREFIX_REX: u32 = 0x40000000;
89
90#[repr(C)]
91#[derive(Debug, Clone, Copy)]
92pub struct Hde64s {
93 pub len: u8,
94 pub p_rep: u8,
95 pub p_lock: u8,
96 pub p_seg: u8,
97 pub p_66: u8,
98 pub p_67: u8,
99 pub rex: u8,
100 pub rex_w: u8,
101 pub rex_r: u8,
102 pub rex_x: u8,
103 pub rex_b: u8,
104 pub opcode: u8,
105 pub opcode2: u8,
106 pub modrm: u8,
107 pub modrm_mod: u8,
108 pub modrm_reg: u8,
109 pub modrm_rm: u8,
110 pub sib: u8,
111 pub sib_scale: u8,
112 pub sib_index: u8,
113 pub sib_base: u8,
114 pub imm: ImmUnion,
115 pub disp: DispUnion,
116 pub flags: u32,
117}
118
119#[repr(C)]
120#[derive(Clone, Copy)]
121pub union ImmUnion {
122 pub imm8: u8,
123 pub imm16: u16,
124 pub imm32: u32,
125 pub imm64: u64,
126}
127
128impl std::fmt::Debug for ImmUnion {
129 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
130 write!(f, "ImmUnion")
131 }
132}
133
134#[repr(C)]
135#[derive(Clone, Copy)]
136pub union DispUnion {
137 pub disp8: u8,
138 pub disp16: u16,
139 pub disp32: u32,
140}
141
142impl std::fmt::Debug for DispUnion {
143 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
144 write!(f, "DispUnion")
145 }
146}
147
148pub unsafe fn hde64_disasm(code: *const u8, hs: *mut Hde64s) -> u32 { unsafe {
149 let mut p = code;
150 std::ptr::write_bytes(hs, 0, 1);
151
152 let mut pref: u8 = 0;
153 let mut cflags: u8;
154 let opcode: u8;
155 let mut c: u8;
156 let mut x: u8;
157 let mut op64: u8 = 0;
158 let mut m_mod: u8;
159 let m_reg: u8;
160 let m_rm: u8;
161 let mut disp_size: u8 = 0;
162 let mut _ht: usize = 0;
163
164 for _ in 0..16 {
165 c = *p;
166 p = p.add(1);
167 match c {
168 0xf3 => {
169 (*hs).p_rep = c;
170 pref |= PRE_F3;
171 }
172 0xf2 => {
173 (*hs).p_rep = c;
174 pref |= PRE_F2;
175 }
176 0xf0 => {
177 (*hs).p_lock = c;
178 pref |= PRE_LOCK;
179 }
180 0x26 | 0x2e | 0x36 | 0x3e | 0x64 | 0x65 => {
181 (*hs).p_seg = c;
182 pref |= PRE_SEG;
183 }
184 0x66 => {
185 (*hs).p_66 = c;
186 pref |= PRE_66;
187 }
188 0x67 => {
189 (*hs).p_67 = c;
190 pref |= PRE_67;
191 }
192 _ => break,
193 }
194 }
195
196 (*hs).flags = (pref as u32) << 23;
197
198 if pref == 0 {
199 pref |= PRE_NONE;
200 }
201
202 c = *p.sub(1);
203 if (c & 0xf0) == 0x40 {
204 (*hs).flags |= F_PREFIX_REX;
205 (*hs).rex_w = (c & 0xf) >> 3;
206 if (*hs).rex_w != 0 && (*p & 0xf8) == 0xb8 {
207 op64 += 1;
208 }
209 (*hs).rex_r = (c & 7) >> 2;
210 (*hs).rex_x = (c & 3) >> 1;
211 (*hs).rex_b = c & 1;
212 c = *p;
213 p = p.add(1);
214 if (c & 0xf0) == 0x40 {
215 opcode = c;
216 (*hs).flags |= F_ERROR | F_ERROR_OPCODE;
217 (*hs).opcode = opcode;
218 (*hs).len = (p as usize - code as usize) as u8;
219 return (*hs).len as u32;
220 }
221 }
222
223 (*hs).opcode = c;
224 if c == 0x0f {
225 (*hs).opcode2 = *p;
226 p = p.add(1);
227 _ht = DELTA_OPCODES;
228 c = (*hs).opcode2;
229 } else if c >= 0xa0 && c <= 0xa3 {
230 op64 += 1;
231 if (pref & PRE_67) != 0 {
232 pref |= PRE_66;
233 } else {
234 pref &= !PRE_66;
235 }
236 }
237
238 opcode = c;
239 cflags = HDE64_TABLE[HDE64_TABLE[(opcode / 4) as usize] as usize + (opcode % 4) as usize];
240
241 if cflags == C_ERROR {
242 (*hs).flags |= F_ERROR | F_ERROR_OPCODE;
243 cflags = 0;
244 if (opcode & 0xfd) == 0x24 {
245 cflags += 1;
246 }
247 }
248
249 x = 0;
250 if (cflags & C_GROUP) != 0 {
251 let t_offset = (cflags & 0x7f) as usize;
252 let t = u16::from_le_bytes([
253 HDE64_TABLE[t_offset],
254 HDE64_TABLE[t_offset + 1]
255 ]);
256 cflags = t as u8;
257 x = (t >> 8) as u8;
258 }
259
260 if (*hs).opcode2 != 0 {
261 let ht_base = DELTA_PREFIXES;
262 let ht_val = HDE64_TABLE[ht_base + HDE64_TABLE[ht_base + (opcode / 4) as usize] as usize + (opcode % 4) as usize];
263 if (ht_val & pref) != 0 {
264 (*hs).flags |= F_ERROR | F_ERROR_OPCODE;
265 }
266 }
267
268 if (cflags & C_MODRM) != 0 {
269 (*hs).flags |= F_MODRM;
270 (*hs).modrm = *p;
271 p = p.add(1);
272 c = (*hs).modrm;
273 (*hs).modrm_mod = c >> 6;
274 (*hs).modrm_rm = c & 7;
275 (*hs).modrm_reg = (c & 0x3f) >> 3;
276 m_mod = (*hs).modrm_mod;
277 m_rm = (*hs).modrm_rm;
278 m_reg = (*hs).modrm_reg;
279
280 if x != 0 && ((x << m_reg) & 0x80) != 0 {
281 (*hs).flags |= F_ERROR | F_ERROR_OPCODE;
282 }
283
284 if (*hs).opcode2 == 0 && opcode >= 0xd9 && opcode <= 0xdf {
285 let t = opcode - 0xd9;
286 let ht_val = if m_mod == 3 {
287 let ht_base = DELTA_FPU_MODRM + (t as usize) * 8;
288 HDE64_TABLE[ht_base + m_reg as usize] << m_rm
289 } else {
290 let ht_base = DELTA_FPU_REG;
291 HDE64_TABLE[ht_base + t as usize] << m_reg
292 };
293 if (ht_val & 0x80) != 0 {
294 (*hs).flags |= F_ERROR | F_ERROR_OPCODE;
295 }
296 }
297
298 if (pref & PRE_LOCK) != 0 {
299 if m_mod == 3 {
300 (*hs).flags |= F_ERROR | F_ERROR_LOCK;
301 } else {
302 let (ht_start, ht_end, op) = if (*hs).opcode2 != 0 {
303 (DELTA_OP2_LOCK_OK, DELTA_OP_ONLY_MEM, opcode)
304 } else {
305 (DELTA_OP_LOCK_OK, DELTA_OP2_LOCK_OK, opcode & 0xfe)
306 };
307
308 let mut found = false;
309 let mut ht_idx = ht_start;
310 while ht_idx < ht_end {
311 if HDE64_TABLE[ht_idx] == op {
312 ht_idx += 1;
313 if ((HDE64_TABLE[ht_idx] << m_reg) & 0x80) == 0 {
314 found = true;
315 break;
316 }
317 break;
318 }
319 ht_idx += 2;
320 }
321 if !found {
322 (*hs).flags |= F_ERROR | F_ERROR_LOCK;
323 }
324 }
325 }
326
327 if (*hs).opcode2 != 0 {
328 match opcode {
329 0x20 | 0x22 => {
330 m_mod = 3;
331 if m_reg > 4 || m_reg == 1 {
332 (*hs).flags |= F_ERROR | F_ERROR_OPERAND;
333 }
334 }
335 0x21 | 0x23 => {
336 m_mod = 3;
337 if m_reg == 4 || m_reg == 5 {
338 (*hs).flags |= F_ERROR | F_ERROR_OPERAND;
339 }
340 }
341 _ => {}
342 }
343 } else {
344 match opcode {
345 0x8c => {
346 if m_reg > 5 {
347 (*hs).flags |= F_ERROR | F_ERROR_OPERAND;
348 }
349 }
350 0x8e => {
351 if m_reg == 1 || m_reg > 5 {
352 (*hs).flags |= F_ERROR | F_ERROR_OPERAND;
353 }
354 }
355 _ => {}
356 }
357 }
358
359 if m_mod == 3 {
360 let (ht_start, ht_end) = if (*hs).opcode2 != 0 {
361 (DELTA_OP2_ONLY_MEM, HDE64_TABLE.len())
362 } else {
363 (DELTA_OP_ONLY_MEM, DELTA_OP2_ONLY_MEM)
364 };
365
366 let mut ht_idx = ht_start;
367 while ht_idx < ht_end {
368 if HDE64_TABLE[ht_idx] == opcode {
369 ht_idx += 1;
370 if (HDE64_TABLE[ht_idx] & pref) != 0 && ((HDE64_TABLE[ht_idx + 1] << m_reg) & 0x80) == 0 {
371 (*hs).flags |= F_ERROR | F_ERROR_OPERAND;
372 }
373 break;
374 }
375 ht_idx += 3;
376 }
377 }
378
379 if (cflags & C_MODRM) != 0 {
380 if m_mod != 3 {
381 if m_rm == 4 {
382 (*hs).flags |= F_SIB;
383 (*hs).sib = *p;
384 p = p.add(1);
385 (*hs).sib_scale = (*hs).sib >> 6;
386 (*hs).sib_index = ((*hs).sib & 0x3f) >> 3;
387 (*hs).sib_base = (*hs).sib & 7;
388 if (*hs).sib_base == 5 && m_mod == 0 {
389 disp_size = 4;
390 }
391 } else if m_rm == 5 && m_mod == 0 {
392 disp_size = 4;
393 }
394
395 if m_mod == 1 {
396 disp_size = 1;
397 } else if m_mod == 2 {
398 disp_size = 4;
399 }
400 }
401 }
402 }
403
404 if (cflags & C_IMM_P66) != 0 {
405 if (cflags & C_REL32) != 0 {
406 if (pref & PRE_66) != 0 {
407 (*hs).flags |= F_IMM16 | F_RELATIVE;
408 (*hs).imm.imm16 = u16::from_le_bytes([*p, *p.add(1)]);
409 p = p.add(2);
410 (*hs).len = (p as usize - code as usize) as u8;
411 if (*hs).len > 0x0f {
412 (*hs).flags |= F_ERROR | F_ERROR_LENGTH;
413 }
414 return (*hs).len as u32;
415 }
416 (*hs).flags |= F_IMM32 | F_RELATIVE;
417 (*hs).imm.imm32 = u32::from_le_bytes([*p, *p.add(1), *p.add(2), *p.add(3)]);
418 p = p.add(4);
419 } else {
420 if op64 != 0 {
421 (*hs).flags |= F_IMM64;
422 (*hs).imm.imm64 = u64::from_le_bytes([
423 *p, *p.add(1), *p.add(2), *p.add(3),
424 *p.add(4), *p.add(5), *p.add(6), *p.add(7)
425 ]);
426 p = p.add(8);
427 } else if (pref & PRE_66) != 0 {
428 (*hs).flags |= F_IMM16;
429 (*hs).imm.imm16 = u16::from_le_bytes([*p, *p.add(1)]);
430 p = p.add(2);
431 } else {
432 (*hs).flags |= F_IMM32;
433 (*hs).imm.imm32 = u32::from_le_bytes([*p, *p.add(1), *p.add(2), *p.add(3)]);
434 p = p.add(4);
435 }
436 }
437 }
438
439 if (cflags & C_IMM16) != 0 {
440 if ((*hs).flags & F_IMM32) != 0 {
441 (*hs).flags |= F_IMM16;
442 (*hs).imm.imm16 = u16::from_le_bytes([*p, *p.add(1)]);
443 p = p.add(2);
444 }
445 }
446
447 if (cflags & C_IMM8) != 0 {
448 (*hs).flags |= F_IMM8;
449 (*hs).imm.imm8 = *p;
450 p = p.add(1);
451 }
452
453 if (cflags & C_REL32) != 0 {
454 (*hs).flags |= F_IMM32 | F_RELATIVE;
455 (*hs).imm.imm32 = u32::from_le_bytes([*p, *p.add(1), *p.add(2), *p.add(3)]);
456 p = p.add(4);
457 } else if (cflags & C_REL8) != 0 {
458 (*hs).flags |= F_IMM8 | F_RELATIVE;
459 (*hs).imm.imm8 = *p;
460 p = p.add(1);
461 }
462
463 if disp_size != 0 {
464 if disp_size == 1 {
465 (*hs).flags |= F_DISP8;
466 (*hs).disp.disp8 = *p;
467 p = p.add(1);
468 } else {
469 (*hs).flags |= F_DISP32;
470 (*hs).disp.disp32 = u32::from_le_bytes([*p, *p.add(1), *p.add(2), *p.add(3)]);
471 p = p.add(4);
472 }
473 }
474
475 (*hs).len = (p as usize - code as usize) as u8;
476 if (*hs).len > 0x0f {
477 (*hs).flags |= F_ERROR | F_ERROR_LENGTH;
478 }
479
480 (*hs).len as u32
481}}