substrate/disasm/
hde64.rs

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}}