diff options
| author | navewindre <boneyaard@gmail.com> | 2018-08-30 22:58:37 +0200 |
|---|---|---|
| committer | navewindre <boneyaard@gmail.com> | 2018-08-30 22:58:37 +0200 |
| commit | 1f3f1ab2a20c6d90189cf1fd03cfbb08077bc02e (patch) | |
| tree | 04595c6b6bb31b43811270961668dae2f8c9ed61 /internal_rewrite/hde32.cpp | |
| parent | c4e18b4e500dc603fb7546b7bc9bc574fb09e0a8 (diff) | |
dsad
Diffstat (limited to 'internal_rewrite/hde32.cpp')
| -rw-r--r-- | internal_rewrite/hde32.cpp | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/internal_rewrite/hde32.cpp b/internal_rewrite/hde32.cpp new file mode 100644 index 0000000..8569287 --- /dev/null +++ b/internal_rewrite/hde32.cpp @@ -0,0 +1,377 @@ +/*
+* Hacker Disassembler Engine 32 C
+* Copyright (c) 2008-2009, Vyacheslav Patkov.
+* All rights reserved.
+*
+*/
+
+#include <cstring>
+#include "hde32.h"
+#include "table32.h"
+
+unsigned int hde32_disasm( const void *code, hde32s *hs )
+{
+ uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
+ uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0;
+
+ memset( (uint8_t*)hs, 0, sizeof( hde32s ) );
+
+ for ( x = 16; x; x-- )
+ switch ( c = *p++ )
+ {
+ case 0xf3:
+ hs->p_rep = c;
+ pref |= PRE_F3;
+ break;
+ case 0xf2:
+ hs->p_rep = c;
+ pref |= PRE_F2;
+ break;
+ case 0xf0:
+ hs->p_lock = c;
+ pref |= PRE_LOCK;
+ break;
+ case 0x26: case 0x2e: case 0x36:
+ case 0x3e: case 0x64: case 0x65:
+ hs->p_seg = c;
+ pref |= PRE_SEG;
+ break;
+ case 0x66:
+ hs->p_66 = c;
+ pref |= PRE_66;
+ break;
+ case 0x67:
+ hs->p_67 = c;
+ pref |= PRE_67;
+ break;
+ default:
+ goto pref_done;
+ }
+pref_done:
+
+ hs->flags = (uint32_t)pref << 23;
+
+ if ( !pref )
+ pref |= PRE_NONE;
+
+ if ( ( hs->opcode = c ) == 0x0f )
+ {
+ hs->opcode2 = c = *p++;
+ ht += DELTA_OPCODES;
+ }
+ else if ( c >= 0xa0 && c <= 0xa3 )
+ {
+ if ( pref & PRE_67 )
+ pref |= PRE_66;
+ else
+ pref &= ~PRE_66;
+ }
+
+ opcode = c;
+ cflags = ht[ht[opcode / 4] + ( opcode % 4 )];
+
+ if ( cflags == C_ERROR )
+ {
+ hs->flags |= F_ERROR | F_ERROR_OPCODE;
+ cflags = 0;
+ if ( ( opcode & -3 ) == 0x24 )
+ cflags++;
+ }
+
+ x = 0;
+ if ( cflags & C_GROUP )
+ {
+ uint16_t t;
+ t = *(uint16_t *)( ht + ( cflags & 0x7f ) );
+ cflags = (uint8_t)t;
+ x = (uint8_t)( t >> 8 );
+ }
+
+ if ( hs->opcode2 )
+ {
+ ht = hde32_table + DELTA_PREFIXES;
+ if ( ht[ht[opcode / 4] + ( opcode % 4 )] & pref )
+ hs->flags |= F_ERROR | F_ERROR_OPCODE;
+ }
+
+ if ( cflags & C_MODRM )
+ {
+ hs->flags |= F_MODRM;
+ hs->modrm = c = *p++;
+ hs->modrm_mod = m_mod = c >> 6;
+ hs->modrm_rm = m_rm = c & 7;
+ hs->modrm_reg = m_reg = ( c & 0x3f ) >> 3;
+
+ if ( x && ( ( x << m_reg ) & 0x80 ) )
+ hs->flags |= F_ERROR | F_ERROR_OPCODE;
+
+ if ( !hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf )
+ {
+ uint8_t t = opcode - 0xd9;
+ if ( m_mod == 3 )
+ {
+ ht = hde32_table + DELTA_FPU_MODRM + t * 8;
+ t = ht[m_reg] << m_rm;
+ }
+ else
+ {
+ ht = hde32_table + DELTA_FPU_REG;
+ t = ht[t] << m_reg;
+ }
+ if ( t & 0x80 )
+ hs->flags |= F_ERROR | F_ERROR_OPCODE;
+ }
+
+ if ( pref & PRE_LOCK )
+ {
+ if ( m_mod == 3 )
+ {
+ hs->flags |= F_ERROR | F_ERROR_LOCK;
+ }
+ else
+ {
+ uint8_t *table_end, op = opcode;
+ if ( hs->opcode2 )
+ {
+ ht = hde32_table + DELTA_OP2_LOCK_OK;
+ table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
+ }
+ else
+ {
+ ht = hde32_table + DELTA_OP_LOCK_OK;
+ table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
+ op &= -2;
+ }
+ for ( ; ht != table_end; ht++ )
+ if ( *ht++ == op )
+ {
+ if ( !( ( *ht << m_reg ) & 0x80 ) )
+ goto no_lock_error;
+ else
+ break;
+ }
+ hs->flags |= F_ERROR | F_ERROR_LOCK;
+ no_lock_error:
+ ;
+ }
+ }
+
+ if ( hs->opcode2 )
+ {
+ switch ( opcode )
+ {
+ case 0x20: case 0x22:
+ m_mod = 3;
+ if ( m_reg > 4 || m_reg == 1 )
+ goto error_operand;
+ else
+ goto no_error_operand;
+ case 0x21: case 0x23:
+ m_mod = 3;
+ if ( m_reg == 4 || m_reg == 5 )
+ goto error_operand;
+ else
+ goto no_error_operand;
+ }
+ }
+ else
+ {
+ switch ( opcode )
+ {
+ case 0x8c:
+ if ( m_reg > 5 )
+ goto error_operand;
+ else
+ goto no_error_operand;
+ case 0x8e:
+ if ( m_reg == 1 || m_reg > 5 )
+ goto error_operand;
+ else
+ goto no_error_operand;
+ }
+ }
+
+ if ( m_mod == 3 )
+ {
+ uint8_t *table_end;
+ if ( hs->opcode2 )
+ {
+ ht = hde32_table + DELTA_OP2_ONLY_MEM;
+ table_end = ht + sizeof( hde32_table ) - DELTA_OP2_ONLY_MEM;
+ }
+ else
+ {
+ ht = hde32_table + DELTA_OP_ONLY_MEM;
+ table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
+ }
+ for ( ; ht != table_end; ht += 2 )
+ if ( *ht++ == opcode )
+ {
+ if ( *ht++ & pref && !( ( *ht << m_reg ) & 0x80 ) )
+ goto error_operand;
+ else
+ break;
+ }
+ goto no_error_operand;
+ }
+ else if ( hs->opcode2 )
+ {
+ switch ( opcode )
+ {
+ case 0x50: case 0xd7: case 0xf7:
+ if ( pref & ( PRE_NONE | PRE_66 ) )
+ goto error_operand;
+ break;
+ case 0xd6:
+ if ( pref & ( PRE_F2 | PRE_F3 ) )
+ goto error_operand;
+ break;
+ case 0xc5:
+ goto error_operand;
+ }
+ goto no_error_operand;
+ }
+ else
+ goto no_error_operand;
+
+ error_operand:
+ hs->flags |= F_ERROR | F_ERROR_OPERAND;
+ no_error_operand:
+
+ c = *p++;
+ if ( m_reg <= 1 )
+ {
+ if ( opcode == 0xf6 )
+ cflags |= C_IMM8;
+ else if ( opcode == 0xf7 )
+ cflags |= C_IMM_P66;
+ }
+
+ switch ( m_mod )
+ {
+ case 0:
+ if ( pref & PRE_67 )
+ {
+ if ( m_rm == 6 )
+ disp_size = 2;
+ }
+ else
+ if ( m_rm == 5 )
+ disp_size = 4;
+ break;
+ case 1:
+ disp_size = 1;
+ break;
+ case 2:
+ disp_size = 2;
+ if ( !( pref & PRE_67 ) )
+ disp_size <<= 1;
+ }
+
+ if ( m_mod != 3 && m_rm == 4 && !( pref & PRE_67 ) )
+ {
+ hs->flags |= F_SIB;
+ p++;
+ hs->sib = c;
+ hs->sib_scale = c >> 6;
+ hs->sib_index = ( c & 0x3f ) >> 3;
+ if ( ( hs->sib_base = c & 7 ) == 5 && !( m_mod & 1 ) )
+ disp_size = 4;
+ }
+
+ p--;
+ switch ( disp_size )
+ {
+ case 1:
+ hs->flags |= F_DISP8;
+ hs->disp.disp8 = *p;
+ break;
+ case 2:
+ hs->flags |= F_DISP16;
+ hs->disp.disp16 = *(uint16_t *)p;
+ break;
+ case 4:
+ hs->flags |= F_DISP32;
+ hs->disp.disp32 = *(uint32_t *)p;
+ }
+ p += disp_size;
+ }
+ else if ( pref & PRE_LOCK )
+ hs->flags |= F_ERROR | F_ERROR_LOCK;
+
+ if ( cflags & C_IMM_P66 )
+ {
+ if ( cflags & C_REL32 )
+ {
+ if ( pref & PRE_66 )
+ {
+ hs->flags |= F_IMM16 | F_RELATIVE;
+ hs->imm.imm16 = *(uint16_t *)p;
+ p += 2;
+ goto disasm_done;
+ }
+ goto rel32_ok;
+ }
+ if ( pref & PRE_66 )
+ {
+ hs->flags |= F_IMM16;
+ hs->imm.imm16 = *(uint16_t *)p;
+ p += 2;
+ }
+ else
+ {
+ hs->flags |= F_IMM32;
+ hs->imm.imm32 = *(uint32_t *)p;
+ p += 4;
+ }
+ }
+
+ if ( cflags & C_IMM16 )
+ {
+ if ( hs->flags & F_IMM32 )
+ {
+ hs->flags |= F_IMM16;
+ hs->disp.disp16 = *(uint16_t *)p;
+ }
+ else if ( hs->flags & F_IMM16 )
+ {
+ hs->flags |= F_2IMM16;
+ hs->disp.disp16 = *(uint16_t *)p;
+ }
+ else
+ {
+ hs->flags |= F_IMM16;
+ hs->imm.imm16 = *(uint16_t *)p;
+ }
+ p += 2;
+ }
+ if ( cflags & C_IMM8 )
+ {
+ hs->flags |= F_IMM8;
+ hs->imm.imm8 = *p++;
+ }
+
+ if ( cflags & C_REL32 )
+ {
+ rel32_ok:
+ hs->flags |= F_IMM32 | F_RELATIVE;
+ hs->imm.imm32 = *(uint32_t *)p;
+ p += 4;
+ }
+ else if ( cflags & C_REL8 )
+ {
+ hs->flags |= F_IMM8 | F_RELATIVE;
+ hs->imm.imm8 = *p++;
+ }
+
+disasm_done:
+
+ if ( ( hs->len = (uint8_t)( p - (uint8_t *)code ) ) > 15 )
+ {
+ hs->flags |= F_ERROR | F_ERROR_LENGTH;
+ hs->len = 15;
+ }
+
+ return (unsigned int)hs->len;
+}
+
|
