From fee4d6fe9a8b3d5540aa9a5cc12d284a7486d004 Mon Sep 17 00:00:00 2001 From: Artur K Date: Sun, 18 Mar 2012 11:35:13 +0100 Subject: [PATCH] A few changes to libdisasm --- 3rd_party/libdisasm/ia32_reg.cpp | 320 +++++++++---------- 3rd_party/libdisasm/libdis.h | 174 +++++------ 3rd_party/libdisasm/x86_format.cpp | 379 ++++++++++++----------- 3rd_party/libdisasm/x86_insn.cpp | 56 +++- 3rd_party/libdisasm/x86_operand_list.cpp | 253 +++++++-------- 5 files changed, 598 insertions(+), 584 deletions(-) diff --git a/3rd_party/libdisasm/ia32_reg.cpp b/3rd_party/libdisasm/ia32_reg.cpp index fa6ea52..541c7f2 100644 --- a/3rd_party/libdisasm/ia32_reg.cpp +++ b/3rd_party/libdisasm/ia32_reg.cpp @@ -31,204 +31,204 @@ * of the MMX registers, so this aliasing is not 100% accurate. * */ static struct { - unsigned char alias; /* id of register this is an alias for */ - unsigned char shift; /* # of bits register must be shifted */ + unsigned char alias; /* id of register this is an alias for */ + unsigned char shift; /* # of bits register must be shifted */ } ia32_reg_aliases[] = { - { 0,0 }, - { REG_DWORD_OFFSET, 0 }, /* al : 1 */ - { REG_DWORD_OFFSET, 8 }, /* ah : 2 */ - { REG_DWORD_OFFSET, 0 }, /* ax : 3 */ - { REG_DWORD_OFFSET + 1, 0 }, /* cl : 4 */ - { REG_DWORD_OFFSET + 1, 8 }, /* ch : 5 */ - { REG_DWORD_OFFSET + 1, 0 }, /* cx : 6 */ - { REG_DWORD_OFFSET + 2, 0 }, /* dl : 7 */ - { REG_DWORD_OFFSET + 2, 8 }, /* dh : 8 */ - { REG_DWORD_OFFSET + 2, 0 }, /* dx : 9 */ - { REG_DWORD_OFFSET + 3, 0 }, /* bl : 10 */ - { REG_DWORD_OFFSET + 3, 8 }, /* bh : 11 */ - { REG_DWORD_OFFSET + 3, 0 }, /* bx : 12 */ - { REG_DWORD_OFFSET + 4, 0 }, /* sp : 13 */ - { REG_DWORD_OFFSET + 5, 0 }, /* bp : 14 */ - { REG_DWORD_OFFSET + 6, 0 }, /* si : 15 */ - { REG_DWORD_OFFSET + 7, 0 }, /* di : 16 */ - { REG_EIP_INDEX, 0 }, /* ip : 17 */ - { REG_FPU_OFFSET, 0 }, /* mm0 : 18 */ - { REG_FPU_OFFSET + 1, 0 }, /* mm1 : 19 */ - { REG_FPU_OFFSET + 2, 0 }, /* mm2 : 20 */ - { REG_FPU_OFFSET + 3, 0 }, /* mm3 : 21 */ - { REG_FPU_OFFSET + 4, 0 }, /* mm4 : 22 */ - { REG_FPU_OFFSET + 5, 0 }, /* mm5 : 23 */ - { REG_FPU_OFFSET + 6, 0 }, /* mm6 : 24 */ - { REG_FPU_OFFSET + 7, 0 } /* mm7 : 25 */ + { 0,0 }, + { REG_DWORD_OFFSET, 0 }, /* al : 1 */ + { REG_DWORD_OFFSET, 8 }, /* ah : 2 */ + { REG_DWORD_OFFSET, 0 }, /* ax : 3 */ + { REG_DWORD_OFFSET + 1, 0 }, /* cl : 4 */ + { REG_DWORD_OFFSET + 1, 8 }, /* ch : 5 */ + { REG_DWORD_OFFSET + 1, 0 }, /* cx : 6 */ + { REG_DWORD_OFFSET + 2, 0 }, /* dl : 7 */ + { REG_DWORD_OFFSET + 2, 8 }, /* dh : 8 */ + { REG_DWORD_OFFSET + 2, 0 }, /* dx : 9 */ + { REG_DWORD_OFFSET + 3, 0 }, /* bl : 10 */ + { REG_DWORD_OFFSET + 3, 8 }, /* bh : 11 */ + { REG_DWORD_OFFSET + 3, 0 }, /* bx : 12 */ + { REG_DWORD_OFFSET + 4, 0 }, /* sp : 13 */ + { REG_DWORD_OFFSET + 5, 0 }, /* bp : 14 */ + { REG_DWORD_OFFSET + 6, 0 }, /* si : 15 */ + { REG_DWORD_OFFSET + 7, 0 }, /* di : 16 */ + { REG_EIP_INDEX, 0 }, /* ip : 17 */ + { REG_FPU_OFFSET, 0 }, /* mm0 : 18 */ + { REG_FPU_OFFSET + 1, 0 }, /* mm1 : 19 */ + { REG_FPU_OFFSET + 2, 0 }, /* mm2 : 20 */ + { REG_FPU_OFFSET + 3, 0 }, /* mm3 : 21 */ + { REG_FPU_OFFSET + 4, 0 }, /* mm4 : 22 */ + { REG_FPU_OFFSET + 5, 0 }, /* mm5 : 23 */ + { REG_FPU_OFFSET + 6, 0 }, /* mm6 : 24 */ + { REG_FPU_OFFSET + 7, 0 } /* mm7 : 25 */ }; -/* REGISTER TABLE: size, type, and name of every register in the +/* REGISTER TABLE: size, type, and name of every register in the * CPU. Does not include MSRs since the are, after all, * model specific. */ static struct { - unsigned int size; - enum x86_reg_type type; - unsigned int alias; - char mnemonic[8]; + unsigned int size; + enum x86_reg_type type; + unsigned int alias; + char mnemonic[8]; } ia32_reg_table[NUM_X86_REGS + 2] = { - { 0, reg_undef, 0, "" }, - /* REG_DWORD_OFFSET */ - { REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_ret), 0, "eax" }, + { 0, reg_undef, 0, "" }, + /* REG_DWORD_OFFSET */ + { REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_ret), 0, "eax" }, { REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_count), 0, "ecx" }, - { REG_DWORD_SIZE, reg_gen, 0, "edx" }, - { REG_DWORD_SIZE, reg_gen, 0, "ebx" }, - /* REG_ESP_INDEX */ + { REG_DWORD_SIZE, reg_gen, 0, "edx" }, + { REG_DWORD_SIZE, reg_gen, 0, "ebx" }, + /* REG_ESP_INDEX */ { REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_sp), 0, "esp" }, { REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_fp), 0, "ebp" }, { REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_src), 0, "esi" }, { REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_dest), 0, "edi" }, - /* REG_WORD_OFFSET */ + /* REG_WORD_OFFSET */ { REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_ret), 3, "ax" }, { REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_count), 6, "cx" }, - { REG_WORD_SIZE, reg_gen, 9, "dx" }, - { REG_WORD_SIZE, reg_gen, 12, "bx" }, + { REG_WORD_SIZE, reg_gen, 9, "dx" }, + { REG_WORD_SIZE, reg_gen, 12, "bx" }, { REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_sp), 13, "sp" }, { REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_fp), 14, "bp" }, { REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_src), 15, "si" }, { REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_dest), 16, "di" }, - /* REG_BYTE_OFFSET */ - { REG_BYTE_SIZE, reg_gen, 1, "al" }, - { REG_BYTE_SIZE, reg_gen, 4, "cl" }, - { REG_BYTE_SIZE, reg_gen, 7, "dl" }, - { REG_BYTE_SIZE, reg_gen, 10, "bl" }, - { REG_BYTE_SIZE, reg_gen, 2, "ah" }, - { REG_BYTE_SIZE, reg_gen, 5, "ch" }, - { REG_BYTE_SIZE, reg_gen, 8, "dh" }, - { REG_BYTE_SIZE, reg_gen, 11, "bh" }, - /* REG_MMX_OFFSET */ - { REG_MMX_SIZE, reg_simd, 18, "mm0" }, - { REG_MMX_SIZE, reg_simd, 19, "mm1" }, - { REG_MMX_SIZE, reg_simd, 20, "mm2" }, - { REG_MMX_SIZE, reg_simd, 21, "mm3" }, - { REG_MMX_SIZE, reg_simd, 22, "mm4" }, - { REG_MMX_SIZE, reg_simd, 23, "mm5" }, - { REG_MMX_SIZE, reg_simd, 24, "mm6" }, - { REG_MMX_SIZE, reg_simd, 25, "mm7" }, - /* REG_SIMD_OFFSET */ - { REG_SIMD_SIZE, reg_simd, 0, "xmm0" }, - { REG_SIMD_SIZE, reg_simd, 0, "xmm1" }, - { REG_SIMD_SIZE, reg_simd, 0, "xmm2" }, - { REG_SIMD_SIZE, reg_simd, 0, "xmm3" }, - { REG_SIMD_SIZE, reg_simd, 0, "xmm4" }, - { REG_SIMD_SIZE, reg_simd, 0, "xmm5" }, - { REG_SIMD_SIZE, reg_simd, 0, "xmm6" }, - { REG_SIMD_SIZE, reg_simd, 0, "xmm7" }, - /* REG_DEBUG_OFFSET */ - { REG_DEBUG_SIZE, reg_sys, 0, "dr0" }, - { REG_DEBUG_SIZE, reg_sys, 0, "dr1" }, - { REG_DEBUG_SIZE, reg_sys, 0, "dr2" }, - { REG_DEBUG_SIZE, reg_sys, 0, "dr3" }, - { REG_DEBUG_SIZE, reg_sys, 0, "dr4" }, - { REG_DEBUG_SIZE, reg_sys, 0, "dr5" }, - { REG_DEBUG_SIZE, reg_sys, 0, "dr6" }, - { REG_DEBUG_SIZE, reg_sys, 0, "dr7" }, - /* REG_CTRL_OFFSET */ - { REG_CTRL_SIZE, reg_sys, 0, "cr0" }, - { REG_CTRL_SIZE, reg_sys, 0, "cr1" }, - { REG_CTRL_SIZE, reg_sys, 0, "cr2" }, - { REG_CTRL_SIZE, reg_sys, 0, "cr3" }, - { REG_CTRL_SIZE, reg_sys, 0, "cr4" }, - { REG_CTRL_SIZE, reg_sys, 0, "cr5" }, - { REG_CTRL_SIZE, reg_sys, 0, "cr6" }, - { REG_CTRL_SIZE, reg_sys, 0, "cr7" }, - /* REG_TEST_OFFSET */ - { REG_TEST_SIZE, reg_sys, 0, "tr0" }, - { REG_TEST_SIZE, reg_sys, 0, "tr1" }, - { REG_TEST_SIZE, reg_sys, 0, "tr2" }, - { REG_TEST_SIZE, reg_sys, 0, "tr3" }, - { REG_TEST_SIZE, reg_sys, 0, "tr4" }, - { REG_TEST_SIZE, reg_sys, 0, "tr5" }, - { REG_TEST_SIZE, reg_sys, 0, "tr6" }, - { REG_TEST_SIZE, reg_sys, 0, "tr7" }, - /* REG_SEG_OFFSET */ - { REG_SEG_SIZE, reg_seg, 0, "es" }, - { REG_SEG_SIZE, reg_seg, 0, "cs" }, - { REG_SEG_SIZE, reg_seg, 0, "ss" }, - { REG_SEG_SIZE, reg_seg, 0, "ds" }, - { REG_SEG_SIZE, reg_seg, 0, "fs" }, - { REG_SEG_SIZE, reg_seg, 0, "gs" }, - /* REG_LDTR_INDEX */ - { REG_DWORD_SIZE, reg_sys, 0, "ldtr" }, - /* REG_GDTR_INDEX */ - { REG_DWORD_SIZE, reg_sys, 0, "gdtr" }, - /* REG_FPU_OFFSET */ - { REG_FPU_SIZE, reg_fpu, 0, "st(0)" }, - { REG_FPU_SIZE, reg_fpu, 0, "st(1)" }, - { REG_FPU_SIZE, reg_fpu, 0, "st(2)" }, - { REG_FPU_SIZE, reg_fpu, 0, "st(3)" }, - { REG_FPU_SIZE, reg_fpu, 0, "st(4)" }, - { REG_FPU_SIZE, reg_fpu, 0, "st(5)" }, - { REG_FPU_SIZE, reg_fpu, 0, "st(6)" }, - { REG_FPU_SIZE, reg_fpu, 0, "st(7)" }, - /* REG_FLAGS_INDEX : 81 */ - { REG_FLAGS_SIZE, reg_cond, 0, "eflags" }, - /* REG_FPCTRL_INDEX : 82*/ - { REG_FPCTRL_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fpctrl" }, - /* REG_FPSTATUS_INDEX : 83*/ + /* REG_BYTE_OFFSET */ + { REG_BYTE_SIZE, reg_gen, 1, "al" }, + { REG_BYTE_SIZE, reg_gen, 4, "cl" }, + { REG_BYTE_SIZE, reg_gen, 7, "dl" }, + { REG_BYTE_SIZE, reg_gen, 10, "bl" }, + { REG_BYTE_SIZE, reg_gen, 2, "ah" }, + { REG_BYTE_SIZE, reg_gen, 5, "ch" }, + { REG_BYTE_SIZE, reg_gen, 8, "dh" }, + { REG_BYTE_SIZE, reg_gen, 11, "bh" }, + /* REG_MMX_OFFSET */ + { REG_MMX_SIZE, reg_simd, 18, "mm0" }, + { REG_MMX_SIZE, reg_simd, 19, "mm1" }, + { REG_MMX_SIZE, reg_simd, 20, "mm2" }, + { REG_MMX_SIZE, reg_simd, 21, "mm3" }, + { REG_MMX_SIZE, reg_simd, 22, "mm4" }, + { REG_MMX_SIZE, reg_simd, 23, "mm5" }, + { REG_MMX_SIZE, reg_simd, 24, "mm6" }, + { REG_MMX_SIZE, reg_simd, 25, "mm7" }, + /* REG_SIMD_OFFSET */ + { REG_SIMD_SIZE, reg_simd, 0, "xmm0" }, + { REG_SIMD_SIZE, reg_simd, 0, "xmm1" }, + { REG_SIMD_SIZE, reg_simd, 0, "xmm2" }, + { REG_SIMD_SIZE, reg_simd, 0, "xmm3" }, + { REG_SIMD_SIZE, reg_simd, 0, "xmm4" }, + { REG_SIMD_SIZE, reg_simd, 0, "xmm5" }, + { REG_SIMD_SIZE, reg_simd, 0, "xmm6" }, + { REG_SIMD_SIZE, reg_simd, 0, "xmm7" }, + /* REG_DEBUG_OFFSET */ + { REG_DEBUG_SIZE, reg_sys, 0, "dr0" }, + { REG_DEBUG_SIZE, reg_sys, 0, "dr1" }, + { REG_DEBUG_SIZE, reg_sys, 0, "dr2" }, + { REG_DEBUG_SIZE, reg_sys, 0, "dr3" }, + { REG_DEBUG_SIZE, reg_sys, 0, "dr4" }, + { REG_DEBUG_SIZE, reg_sys, 0, "dr5" }, + { REG_DEBUG_SIZE, reg_sys, 0, "dr6" }, + { REG_DEBUG_SIZE, reg_sys, 0, "dr7" }, + /* REG_CTRL_OFFSET */ + { REG_CTRL_SIZE, reg_sys, 0, "cr0" }, + { REG_CTRL_SIZE, reg_sys, 0, "cr1" }, + { REG_CTRL_SIZE, reg_sys, 0, "cr2" }, + { REG_CTRL_SIZE, reg_sys, 0, "cr3" }, + { REG_CTRL_SIZE, reg_sys, 0, "cr4" }, + { REG_CTRL_SIZE, reg_sys, 0, "cr5" }, + { REG_CTRL_SIZE, reg_sys, 0, "cr6" }, + { REG_CTRL_SIZE, reg_sys, 0, "cr7" }, + /* REG_TEST_OFFSET */ + { REG_TEST_SIZE, reg_sys, 0, "tr0" }, + { REG_TEST_SIZE, reg_sys, 0, "tr1" }, + { REG_TEST_SIZE, reg_sys, 0, "tr2" }, + { REG_TEST_SIZE, reg_sys, 0, "tr3" }, + { REG_TEST_SIZE, reg_sys, 0, "tr4" }, + { REG_TEST_SIZE, reg_sys, 0, "tr5" }, + { REG_TEST_SIZE, reg_sys, 0, "tr6" }, + { REG_TEST_SIZE, reg_sys, 0, "tr7" }, + /* REG_SEG_OFFSET */ + { REG_SEG_SIZE, reg_seg, 0, "es" }, + { REG_SEG_SIZE, reg_seg, 0, "cs" }, + { REG_SEG_SIZE, reg_seg, 0, "ss" }, + { REG_SEG_SIZE, reg_seg, 0, "ds" }, + { REG_SEG_SIZE, reg_seg, 0, "fs" }, + { REG_SEG_SIZE, reg_seg, 0, "gs" }, + /* REG_LDTR_INDEX */ + { REG_DWORD_SIZE, reg_sys, 0, "ldtr" }, + /* REG_GDTR_INDEX */ + { REG_DWORD_SIZE, reg_sys, 0, "gdtr" }, + /* REG_FPU_OFFSET */ + { REG_FPU_SIZE, reg_fpu, 0, "st(0)" }, + { REG_FPU_SIZE, reg_fpu, 0, "st(1)" }, + { REG_FPU_SIZE, reg_fpu, 0, "st(2)" }, + { REG_FPU_SIZE, reg_fpu, 0, "st(3)" }, + { REG_FPU_SIZE, reg_fpu, 0, "st(4)" }, + { REG_FPU_SIZE, reg_fpu, 0, "st(5)" }, + { REG_FPU_SIZE, reg_fpu, 0, "st(6)" }, + { REG_FPU_SIZE, reg_fpu, 0, "st(7)" }, + /* REG_FLAGS_INDEX : 81 */ + { REG_FLAGS_SIZE, reg_cond, 0, "eflags" }, + /* REG_FPCTRL_INDEX : 82*/ + { REG_FPCTRL_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fpctrl" }, + /* REG_FPSTATUS_INDEX : 83*/ { REG_FPSTATUS_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fpstat" }, - /* REG_FPTAG_INDEX : 84 */ - { REG_FPTAG_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fptag" }, - /* REG_EIP_INDEX : 85 */ - { REG_EIP_SIZE, reg_pc, 0, "eip" }, - /* REG_IP_INDEX : 86 */ - { REG_IP_SIZE, reg_pc, 17, "ip" }, - /* REG_IDTR_INDEX : 87 */ - { REG_DWORD_SIZE, reg_sys, 0, "idtr" }, - /* REG_MXCSG_INDEX : SSE Control Reg : 88 */ + /* REG_FPTAG_INDEX : 84 */ + { REG_FPTAG_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fptag" }, + /* REG_EIP_INDEX : 85 */ + { REG_EIP_SIZE, reg_pc, 0, "eip" }, + /* REG_IP_INDEX : 86 */ + { REG_IP_SIZE, reg_pc, 17, "ip" }, + /* REG_IDTR_INDEX : 87 */ + { REG_DWORD_SIZE, reg_sys, 0, "idtr" }, + /* REG_MXCSG_INDEX : SSE Control Reg : 88 */ { REG_DWORD_SIZE, (x86_reg_type)(reg_sys | reg_simd), 0, "mxcsr" }, - /* REG_TR_INDEX : Task Register : 89 */ - { 16 + 64, reg_sys, 0, "tr" }, - /* REG_CSMSR_INDEX : SYSENTER_CS_MSR : 90 */ - { REG_DWORD_SIZE, reg_sys, 0, "cs_msr" }, - /* REG_ESPMSR_INDEX : SYSENTER_ESP_MSR : 91 */ - { REG_DWORD_SIZE, reg_sys, 0, "esp_msr" }, - /* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */ - { REG_DWORD_SIZE, reg_sys, 0, "eip_msr" }, - { 0 } - }; + /* REG_TR_INDEX : Task Register : 89 */ + { 16 + 64, reg_sys, 0, "tr" }, + /* REG_CSMSR_INDEX : SYSENTER_CS_MSR : 90 */ + { REG_DWORD_SIZE, reg_sys, 0, "cs_msr" }, + /* REG_ESPMSR_INDEX : SYSENTER_ESP_MSR : 91 */ + { REG_DWORD_SIZE, reg_sys, 0, "esp_msr" }, + /* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */ + { REG_DWORD_SIZE, reg_sys, 0, "eip_msr" }, + { 0 } +}; static size_t sz_regtable = NUM_X86_REGS + 1; void ia32_handle_register( x86_reg_t *reg, size_t id ) { - unsigned int alias; - if (! id || id > sz_regtable ) { - return; - } + unsigned int alias; + if (! id || id > sz_regtable ) { + return; + } - memset( reg, 0, sizeof(x86_reg_t) ); + memset( reg, 0, sizeof(x86_reg_t) ); strncpy( reg->name, ia32_reg_table[id].mnemonic, MAX_REGNAME ); reg->type = ia32_reg_table[id].type; reg->size = ia32_reg_table[id].size; - alias = ia32_reg_table[id].alias; - if ( alias ) { - reg->alias = ia32_reg_aliases[alias].alias; - reg->shift = ia32_reg_aliases[alias].shift; - } + alias = ia32_reg_table[id].alias; + if ( alias ) { + reg->alias = ia32_reg_aliases[alias].alias; + reg->shift = ia32_reg_aliases[alias].shift; + } reg->id = id; - return; + return; } size_t ia32_true_register_id( size_t id ) { - size_t reg; + size_t reg; - if (! id || id > sz_regtable ) { - return 0; - } + if (! id || id > sz_regtable ) { + return 0; + } - reg = id; - if (ia32_reg_table[reg].alias) { - reg = ia32_reg_aliases[ia32_reg_table[reg].alias].alias; - } - return reg; + reg = id; + if (ia32_reg_table[reg].alias) { + reg = ia32_reg_aliases[ia32_reg_table[reg].alias].alias; + } + return reg; } diff --git a/3rd_party/libdisasm/libdis.h b/3rd_party/libdisasm/libdis.h index 7e3589e..2c3fdae 100644 --- a/3rd_party/libdisasm/libdis.h +++ b/3rd_party/libdisasm/libdis.h @@ -133,12 +133,12 @@ enum x86_reg_type { /* NOTE: these may be ORed together */ /* x86_reg_t : an X86 CPU register */ struct x86_reg_t { - char name[MAX_REGNAME]; - enum x86_reg_type type; /* what register is used for */ - unsigned int size; /* size of register in bytes */ - unsigned int id; /* register ID #, for quick compares */ - unsigned int alias; /* ID of reg this is an alias for */ - unsigned int shift; /* amount to shift aliased reg by */ + char name[MAX_REGNAME]; + enum x86_reg_type type; /* what register is used for */ + unsigned int size; /* size of register in bytes */ + unsigned int id; /* register ID #, for quick compares */ + unsigned int alias; /* ID of reg this is an alias for */ + unsigned int shift; /* amount to shift aliased reg by */ x86_reg_t * aliased_reg( ) { x86_reg_t * reg = (x86_reg_t * )calloc( sizeof(x86_reg_t), 1 ); reg->x86_reg_from_id( id ); @@ -158,11 +158,11 @@ typedef struct { /* x86_absolute_t : an X86 segment:offset address (descriptor) */ typedef struct { - unsigned short segment; /* loaded directly into CS */ - union { - unsigned short off16; /* loaded directly into IP */ - uint32_t off32; /* loaded directly into EIP */ - } offset; + unsigned short segment; /* loaded directly into CS */ + union { + unsigned short off16; /* loaded directly into IP */ + uint32_t off32; /* loaded directly into EIP */ + } offset; } x86_absolute_t; enum x86_op_type { /* mutually exclusive */ @@ -210,7 +210,7 @@ enum x86_op_datatype { /* these use Intel's lame terminology */ op_fpustate32 = 23, /* 108 byte FPU state (env & reg stack) */ op_fpregset = 24, /* 512 bytes: register set */ op_fpreg = 25, /* FPU register */ - op_none = 0xFF, /* operand without a datatype (INVLPG) */ + op_none = 0xFF /* operand without a datatype (INVLPG) */ }; enum x86_op_access { /* ORed together */ @@ -250,49 +250,45 @@ struct x86_op_flags { /* ORed together, but segs are mutually exclusive */ /* x86_op_t : an X86 instruction operand */ struct x86_op_t{ friend struct x86_insn_t; - enum x86_op_type type; /* operand type */ - enum x86_op_datatype datatype; /* operand size */ - enum x86_op_access access; /* operand access [RWX] */ - x86_op_flags flags; /* misc flags */ - union { - /* sizeof will have to work on these union members! */ - /* immediate values */ - char sbyte; - short sword; - int32_t sdword; - qword_t sqword; - unsigned char byte; - unsigned short word; - uint32_t dword; - qword_t qword; - float sreal; - double dreal; - /* misc large/non-native types */ - unsigned char extreal[10]; - unsigned char bcd[10]; - qword_t dqword[2]; - unsigned char simd[16]; - unsigned char fpuenv[28]; - /* offset from segment */ - uint32_t offset; - /* ID of CPU register */ - x86_reg_t reg; - /* offsets from current insn */ - char relative_near; - int32_t relative_far; - /* segment:offset */ - x86_absolute_t absolute; - /* effective address [expression] */ - x86_ea_t expression; - } data; - /* this is needed to make formatting operands more sane */ - void * insn; /* pointer to x86_insn_t owning operand */ + enum x86_op_type type; /* operand type */ + enum x86_op_datatype datatype; /* operand size */ + enum x86_op_access access; /* operand access [RWX] */ + x86_op_flags flags; /* misc flags */ + union { + /* sizeof will have to work on these union members! */ + /* immediate values */ + char sbyte; + short sword; + int32_t sdword; + qword_t sqword; + unsigned char byte; + unsigned short word; + uint32_t dword; + qword_t qword; + float sreal; + double dreal; + /* misc large/non-native types */ + unsigned char extreal[10]; + unsigned char bcd[10]; + qword_t dqword[2]; + unsigned char simd[16]; + unsigned char fpuenv[28]; + /* offset from segment */ + uint32_t offset; + x86_reg_t reg; /* ID of CPU register */ + char relative_near; /* offsets from current insn */ + int32_t relative_far; + x86_absolute_t absolute; /* segment:offset */ + x86_ea_t expression; /* effective address [expression] */ + } data; + /* this is needed to make formatting operands more sane */ + void * insn; /* pointer to x86_insn_t owning operand */ size_t size() { - return x86_operand_size(); + return operand_size(); } /* get size of operand data in bytes */ - size_t x86_operand_size(); + size_t operand_size(); /* format (sprintf) an operand into 'buf' using specified syntax */ int x86_format_operand(char *buf, int len, enum x86_asm_format format ); bool is_address( ) { @@ -302,9 +298,9 @@ struct x86_op_t{ return ( type == op_relative_near || type == op_relative_far ); } char * format( enum x86_asm_format format ); - x86_op_t * copy() { + x86_op_t * copy() + { x86_op_t *op = (x86_op_t *) calloc( sizeof(x86_op_t), 1 ); - if ( op ) { memcpy( op, this, sizeof(x86_op_t) ); } @@ -524,6 +520,7 @@ enum x86_insn_prefix { /* TODO: maybe provide insn_new/free(), and have disasm return new insn_t */ + /* FOREACH types: these are used to limit the foreach results to * operands which match a certain "type" (implicit or explicit) * or which are accessed in certain ways (e.g. read or write). Note @@ -575,11 +572,11 @@ private: void x86_oplist_append(x86_oplist_t *op); public: /* information about the instruction */ - uint32_t addr; /* load address */ - uint32_t offset; /* offset into file/buffer */ - enum x86_insn_group group; /* meta-type, e.g. INS_EXEC */ - enum x86_insn_type type; /* type, e.g. INS_BRANCH */ - enum x86_insn_note note; /* note, e.g. RING0 */ + uint32_t addr; /* load address */ + uint32_t offset; /* offset into file/buffer */ + x86_insn_group group; /* meta-type, e.g. INS_EXEC */ + x86_insn_type type; /* type, e.g. INS_BRANCH */ + x86_insn_note note; /* note, e.g. RING0 */ unsigned char bytes[MAX_INSN_SIZE]; unsigned char size; /* size of insn in bytes */ /* 16/32-bit mode settings */ @@ -607,58 +604,29 @@ public: void *block; /* code block containing this insn */ void *function; /* function containing this insn */ int tag; /* tag the insn as seen/processed */ - x86_op_t *x86_operand_new(); - /* convenience routine: returns count of operands matching 'type' */ - size_t x86_operand_count( enum x86_op_foreach_type type ); + x86_op_t * x86_operand_new(); + size_t x86_operand_count( enum x86_op_foreach_type type ); /* accessor functions for the operands */ - x86_op_t * x86_operand_1st( ); - x86_op_t * x86_operand_2nd( ); - x86_op_t * x86_operand_3rd( ); - /* Get Relative Offset: return as a sign-extended int32_t the near or far - * relative offset operand, or 0 if there is none. There can be only one - * relaive offset operand in an instruction. */ - int32_t x86_get_rel_offset( ); - /* Get Branch Target: return the x86_op_t containing the target of - * a jump or call operand, or NULL if there is no branch target. - * Internally, a 'branch target' is defined as any operand with - * Execute Access set. There can be only one branch target per instruction. */ - x86_op_t * x86_get_branch_target( ); - /* Get Immediate: return the x86_op_t containing the immediate operand - * for this instruction, or NULL if there is no immediate operand. There - * can be only one immediate operand per instruction */ - x86_op_t * x86_get_imm( ); - /* Get Raw Immediate Data: returns a pointer to the immediate data encoded - * in the instruction. This is useful for large data types [>32 bits] currently - * not supported by libdisasm, or for determining if the disassembler - * screwed up the conversion of the immediate data. Note that 'imm' in this - * context refers to immediate data encoded at the end of an instruction as - * detailed in the Intel Manual Vol II Chapter 2; it does not refer to the - * 'op_imm' operand (the third operand in instructions like 'mul' */ - unsigned char * x86_get_raw_imm( ); + x86_op_t * x86_operand_1st( ); + x86_op_t * x86_operand_2nd( ); + x86_op_t * x86_operand_3rd( ); + x86_op_t * get_dest(); + int32_t x86_get_rel_offset( ); + x86_op_t * x86_get_branch_target( ); + x86_op_t * x86_get_imm( ); + uint8_t * x86_get_raw_imm( ); /* More accessor fuctions, this time for user-defined info... */ - /* set the address (usually RVA) of the insn */ - void x86_set_insn_addr( uint32_t addr ); - /* format (sprintf) an instruction mnemonic into 'buf' using specified syntax */ - int x86_format_mnemonic( char *buf, int len, enum x86_asm_format format); - /* format (sprintf) an instruction into 'buf' using specified syntax; - * this includes formatting all operands */ - int x86_format_insn( char *buf, int len, enum x86_asm_format); - /* free the operand list associated with an instruction -- useful for - * preventing memory leaks when free()ing an x86_insn_t */ - void x86_oplist_free( ); - /* returns 0 if an instruction is invalid, 1 if valid */ - int x86_insn_is_valid( ); - /* Get Address: return the value of an offset operand, or the offset of - * a segment:offset absolute address */ + void x86_set_insn_addr( uint32_t addr ); + int x86_format_mnemonic( char *buf, int len, enum x86_asm_format format); + int x86_format_insn( char *buf, int len, enum x86_asm_format); + void x86_oplist_free( ); + bool is_valid( ); uint32_t x86_get_address( ); - void make_invalid(unsigned char *buf); + void make_invalid(unsigned char *buf); /* instruction tagging: these routines allow the programmer to mark * instructions as "seen" in a DFS, for example. libdisasm does not use * the tag field.*/ - /* set insn->tag to 1 */ void x86_tag_insn( ); - - /* return insn->tag */ int x86_insn_is_tagged(); /* set insn->tag to 0 */ void x86_untag_insn(); diff --git a/3rd_party/libdisasm/x86_format.cpp b/3rd_party/libdisasm/x86_format.cpp index 515e0e5..24448f6 100644 --- a/3rd_party/libdisasm/x86_format.cpp +++ b/3rd_party/libdisasm/x86_format.cpp @@ -16,16 +16,16 @@ * only with one argument. */ #define STRNCAT( buf, str, len ) do { \ - int _i = strlen(str), _blen = strlen(buf), _len = len - 1; \ - if ( len ) { \ - strncat( buf, str, _len ); \ - if ( _len <= _i ) { \ - buf[_blen+_len] = '\0'; \ - len = 0; \ - } else { \ - len -= _i; \ - } \ - } \ + int _i = strlen(str), _blen = strlen(buf), _len = len - 1; \ + if ( len ) { \ + strncat( buf, str, _len ); \ + if ( _len <= _i ) { \ + buf[_blen+_len] = '\0'; \ + len = 0; \ + } else { \ + len -= _i; \ + } \ + } \ } while( 0 ) #define STRNCATF( buf, fmt, data, len ) do { \ @@ -47,11 +47,11 @@ } while( 0 ) static char *prefix_strings[] = { - "", /* no prefix */ - "repz ", /* the trailing spaces make it easy to prepend to mnemonic */ - "repnz ", - "lock ", - "branch delay " /* unused in x86 */ + "", /* no prefix */ + "repz ", /* the trailing spaces make it easy to prepend to mnemonic */ + "repnz ", + "lock ", + "branch delay " /* unused in x86 */ }; static int format_insn_prefix_str( enum x86_insn_prefix prefix, char *buf, @@ -163,28 +163,28 @@ static int format_expr( x86_ea_t *ea, char *buf, int len, char str[MAX_OP_STRING]; if ( format == att_syntax ) { - if (ea->base.name[0] || ea->index.name[0] || ea->scale) { - PRINT_DISPLACEMENT(ea); - STRNCAT( buf, "(", len ); + if (ea->base.name[0] || ea->index.name[0] || ea->scale) { + PRINT_DISPLACEMENT(ea); + STRNCAT( buf, "(", len ); - if ( ea->base.name[0]) { - STRNCATF( buf, "%%%s", ea->base.name, len ); - } - if ( ea->index.name[0]) { - STRNCATF( buf, ",%%%s", ea->index.name, len ); - if ( ea->scale > 1 ) { - STRNCATF( buf, ",%d", ea->scale, len ); - } - } - /* handle the syntactic exception */ - if ( ! ea->base.name[0] && - ! ea->index.name[0] ) { - STRNCATF( buf, ",%d", ea->scale, len ); - } + if ( ea->base.name[0]) { + STRNCATF( buf, "%%%s", ea->base.name, len ); + } + if ( ea->index.name[0]) { + STRNCATF( buf, ",%%%s", ea->index.name, len ); + if ( ea->scale > 1 ) { + STRNCATF( buf, ",%d", ea->scale, len ); + } + } + /* handle the syntactic exception */ + if ( ! ea->base.name[0] && + ! ea->index.name[0] ) { + STRNCATF( buf, ",%d", ea->scale, len ); + } - STRNCAT( buf, ")", len ); - } else - STRNCATF( buf, "0x%" PRIX32, ea->disp, len ); + STRNCAT( buf, ")", len ); + } else + STRNCATF( buf, "0x%" PRIX32, ea->disp, len ); } else if ( format == xml_syntax ){ @@ -270,8 +270,8 @@ static int format_expr( x86_ea_t *ea, char *buf, int len, } } - if ( ea->disp_size || (! ea->index.name[0] && - ! ea->base.name[0] ) ) + if ( ea->disp_size || (! ea->index.name[0] && + ! ea->base.name[0] ) ) { PRINT_DISPLACEMENT(ea); } @@ -341,34 +341,34 @@ static char *get_operand_datatype_str( x86_op_t *op ){ "qword", "dword", /* 8 */ "dqword", - "sreal", - "dreal", - "extreal", /* 12 */ - "bcd", - "ssimd", - "dsimd", - "sssimd", /* 16 */ - "sdsimd", - "descr32", - "descr16", - "pdescr32", /* 20 */ - "pdescr16", - "bounds16", - "bounds32", - "fpu_env16", - "fpu_env32", /* 25 */ - "fpu_state16", - "fpu_state32", - "fp_reg_set" + "sreal", + "dreal", + "extreal", /* 12 */ + "bcd", + "ssimd", + "dsimd", + "sssimd", /* 16 */ + "sdsimd", + "descr32", + "descr16", + "pdescr32", /* 20 */ + "pdescr16", + "bounds16", + "bounds32", + "fpu_env16", + "fpu_env32", /* 25 */ + "fpu_state16", + "fpu_state32", + "fp_reg_set" }; - /* handle signed values first */ + /* handle signed values first */ if ( op->flags.op_signed ) { switch (op->datatype) { case op_byte: return types[0]; case op_word: return types[1]; case op_qword: return types[2]; - case op_dqword: return types[4]; + case op_dqword: return types[4]; default: return types[3]; } } @@ -378,25 +378,25 @@ static char *get_operand_datatype_str( x86_op_t *op ){ case op_word: return types[6]; case op_qword: return types[7]; case op_dqword: return types[9]; - case op_sreal: return types[10]; - case op_dreal: return types[11]; - case op_extreal: return types[12]; - case op_bcd: return types[13]; - case op_ssimd: return types[14]; - case op_dsimd: return types[15]; - case op_sssimd: return types[16]; - case op_sdsimd: return types[17]; - case op_descr32: return types[18]; - case op_descr16: return types[19]; - case op_pdescr32: return types[20]; - case op_pdescr16: return types[21]; - case op_bounds16: return types[22]; - case op_bounds32: return types[23]; - case op_fpustate16: return types[24]; - case op_fpustate32: return types[25]; - case op_fpuenv16: return types[26]; - case op_fpuenv32: return types[27]; - case op_fpregset: return types[28]; + case op_sreal: return types[10]; + case op_dreal: return types[11]; + case op_extreal: return types[12]; + case op_bcd: return types[13]; + case op_ssimd: return types[14]; + case op_dsimd: return types[15]; + case op_sssimd: return types[16]; + case op_sdsimd: return types[17]; + case op_descr32: return types[18]; + case op_descr16: return types[19]; + case op_pdescr32: return types[20]; + case op_pdescr16: return types[21]; + case op_bounds16: return types[22]; + case op_bounds32: return types[23]; + case op_fpustate16: return types[24]; + case op_fpustate32: return types[25]; + case op_fpuenv16: return types[26]; + case op_fpuenv32: return types[27]; + case op_fpregset: return types[28]; default: return types[8]; } } @@ -608,21 +608,21 @@ static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) { }; if ( cpu <= sizeof(intel)/sizeof(intel[0]) ) { - return intel[cpu]; - } else if ( cpu == 16 ) { - return "K6"; - } else if ( cpu == 32 ) { - return "K7"; - } else if ( cpu == 48 ) { - return "Athlon"; - } + return intel[cpu]; + } else if ( cpu == 16 ) { + return "K6"; + } else if ( cpu == 32 ) { + return "K7"; + } else if ( cpu == 48 ) { + return "Athlon"; + } return ""; } static char *get_insn_isa_str( enum x86_insn_isa isa ) { static char *subset[] = { - NULL, // 0 + NULL, // 0 "General Purpose", // 1 "Floating Point", // 2 "FPU Management", // 3 @@ -636,7 +636,7 @@ static char *get_insn_isa_str( enum x86_insn_isa isa ) { if ( isa > sizeof (subset)/sizeof(subset[0]) ) { return ""; - } + } return subset[isa]; } @@ -658,35 +658,35 @@ static int format_operand_att( x86_op_t *op, x86_insn_t *insn, char *buf, STRNCATF( buf, "$%s", str, len ); break; - case op_relative_near: + case op_relative_near: STRNCATF( buf, "0x%08X", (unsigned int)(op->data.sbyte + insn->addr + insn->size), len ); break; - case op_relative_far: + case op_relative_far: if (op->datatype == op_word) { STRNCATF( buf, "0x%08X", (unsigned int)(op->data.sword + insn->addr + insn->size), len ); } else { - STRNCATF( buf, "0x%08X", - (unsigned int)(op->data.sdword + - insn->addr + insn->size), len ); - } + STRNCATF( buf, "0x%08X", + (unsigned int)(op->data.sdword + + insn->addr + insn->size), len ); + } break; case op_absolute: - /* ATT uses the syntax $section, $offset */ + /* ATT uses the syntax $section, $offset */ STRNCATF( buf, "$0x%04" PRIX16 ", ", op->data.absolute.segment, - len ); - if (op->datatype == op_descr16) { - STRNCATF( buf, "$0x%04" PRIX16, - op->data.absolute.offset.off16, len ); - } else { - STRNCATF( buf, "$0x%08" PRIX32, - op->data.absolute.offset.off32, len ); - } + len ); + if (op->datatype == op_descr16) { + STRNCATF( buf, "$0x%04" PRIX16, + op->data.absolute.offset.off16, len ); + } else { + STRNCATF( buf, "$0x%08" PRIX32, + op->data.absolute.offset.off32, len ); + } break; case op_offset: /* ATT requires a '*' before JMP/CALL ops */ @@ -743,21 +743,21 @@ static int format_operand_native( x86_op_t *op, x86_insn_t *insn, char *buf, insn->addr + insn->size), len ); break; } else { - STRNCATF( buf, "0x%08" PRIX32, op->data.sdword + - insn->addr + insn->size, len ); - } + STRNCATF( buf, "0x%08" PRIX32, op->data.sdword + + insn->addr + insn->size, len ); + } break; case op_absolute: STRNCATF( buf, "$0x%04" PRIX16 ":", op->data.absolute.segment, - len ); - if (op->datatype == op_descr16) { - STRNCATF( buf, "0x%04" PRIX16, - op->data.absolute.offset.off16, len ); - } else { - STRNCATF( buf, "0x%08" PRIX32, - op->data.absolute.offset.off32, len ); - } + len ); + if (op->datatype == op_descr16) { + STRNCATF( buf, "0x%04" PRIX16, + op->data.absolute.offset.off16, len ); + } else { + STRNCATF( buf, "0x%08" PRIX32, + op->data.absolute.offset.off32, len ); + } break; case op_offset: @@ -824,31 +824,31 @@ static int format_operand_xml( x86_op_t *op, x86_insn_t *insn, char *buf, break; } else { - STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n", + STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n", op->data.sdword + insn->addr + insn->size, len ); - } + } break; case op_absolute: - STRNCATF( buf, - "\t\tdata.absolute.segment, len ); + STRNCATF( buf, + "\t\tdata.absolute.segment, len ); - if (op->datatype == op_descr16) { - STRNCATF( buf, "offset=\"0x%04" PRIX16 "\">", - op->data.absolute.offset.off16, len ); - } else { - STRNCATF( buf, "offset=\"0x%08" PRIX32 "\">", - op->data.absolute.offset.off32, len ); - } + if (op->datatype == op_descr16) { + STRNCATF( buf, "offset=\"0x%04" PRIX16 "\">", + op->data.absolute.offset.off16, len ); + } else { + STRNCATF( buf, "offset=\"0x%08" PRIX32 "\">", + op->data.absolute.offset.off32, len ); + } STRNCAT( buf, "\t\t\n", len ); break; case op_expression: - + STRNCAT( buf, "\t\t\n", len ); @@ -884,7 +884,7 @@ static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf, int len){ char str[MAX_OP_RAW_STRING]; - char *datatype = get_operand_datatype_str(op); + char *datatype = get_operand_datatype_str(op); switch (op->type) { case op_register: @@ -909,9 +909,9 @@ static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf, break; case op_relative_near: - /* NOTE: in raw format, we print the - * relative offset, not the actual - * address of the jump target */ + /* NOTE: in raw format, we print the + * relative offset, not the actual + * address of the jump target */ STRNCAT( buf, "relative|", len ); STRNCATF( buf, "%s|", datatype, len ); @@ -927,8 +927,8 @@ static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf, STRNCATF( buf, "%" PRId16 "|", op->data.sword, len); break; } else { - STRNCATF( buf, "%" PRId32 "|", op->data.sdword, len ); - } + STRNCATF( buf, "%" PRId32 "|", op->data.sdword, len ); + } break; case op_absolute: @@ -937,14 +937,14 @@ static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf, STRNCATF( buf, "%s|", datatype, len ); STRNCATF( buf, "$0x%04" PRIX16 ":", op->data.absolute.segment, - len ); - if (op->datatype == op_descr16) { - STRNCATF( buf, "0x%04" PRIX16 "|", - op->data.absolute.offset.off16, len ); - } else { - STRNCATF( buf, "0x%08" PRIX32 "|", - op->data.absolute.offset.off32, len ); - } + len ); + if (op->datatype == op_descr16) { + STRNCATF( buf, "0x%04" PRIX16 "|", + op->data.absolute.offset.off16, len ); + } else { + STRNCATF( buf, "0x%08" PRIX32 "|", + op->data.absolute.offset.off32, len ); + } break; @@ -981,14 +981,14 @@ static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf, int x86_op_t::x86_format_operand(char *buf, int len, enum x86_asm_format format ){ - x86_insn_t *_insn; + x86_insn_t *_insn; if ( ! this || ! buf || len < 1 ) { return(0); } - /* insn is stored in x86_op_t since .21-pre3 */ - _insn = (x86_insn_t *) insn; + /* insn is stored in x86_op_t since .21-pre3 */ + _insn = (x86_insn_t *) insn; memset( buf, 0, len ); @@ -1077,10 +1077,10 @@ static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) { )) { if ( insn->x86_operand_count( op_explicit ) > 0 && is_memory_op( insn->x86_operand_1st() ) ){ - size = insn->x86_operand_1st()->x86_operand_size(); + size = insn->x86_operand_1st()->operand_size(); } else if ( insn->x86_operand_count( op_explicit ) > 1 && is_memory_op( insn->x86_operand_2nd() ) ){ - size = insn->x86_operand_2nd()->x86_operand_size(); + size = insn->x86_operand_2nd()->operand_size(); } } @@ -1094,6 +1094,7 @@ static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) { return ( strlen( buf ) ); } +/** format (sprintf) an instruction mnemonic into 'buf' using specified syntax */ int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len, enum x86_asm_format format){ char str[MAX_OP_STRING]; @@ -1113,24 +1114,24 @@ int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len, struct op_string { char *buf; size_t len; }; static void format_op_raw( x86_op_t *op, x86_insn_t *insn, void *arg ) { - struct op_string * opstr = (struct op_string *) arg; + struct op_string * opstr = (struct op_string *) arg; format_operand_raw(op, insn, opstr->buf, opstr->len); } static int format_insn_note(x86_insn_t *insn, char *buf, int len){ - char note[32] = {0}; - int len_orig = len, note_len = 32; + char note[32] = {0}; + int len_orig = len, note_len = 32; - if ( insn->note & insn_note_ring0 ) { - STRNCATF( note, "%s", "Ring0 ", note_len ); - } - if ( insn->note & insn_note_smm ) { - STRNCATF( note, "%s", "SMM ", note_len ); - } - if ( insn->note & insn_note_serial ) { - STRNCATF(note, "%s", "Serialize ", note_len ); - } + if ( insn->note & insn_note_ring0 ) { + STRNCATF( note, "%s", "Ring0 ", note_len ); + } + if ( insn->note & insn_note_smm ) { + STRNCATF( note, "%s", "SMM ", note_len ); + } + if ( insn->note & insn_note_serial ) { + STRNCATF(note, "%s", "Serialize ", note_len ); + } STRNCATF( buf, "%s|", note, len ); return( len_orig - len ); @@ -1143,9 +1144,9 @@ static int format_raw_insn( x86_insn_t *insn, char *buf, int len ){ /* RAW style: * ADDRESS|OFFSET|SIZE|BYTES| * PREFIX|PREFIX_STRING|GROUP|TYPE|NOTES| - * MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED| - * STACK_MOD|STACK_MOD_VAL - * [|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]* + * MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED| + * STACK_MOD|STACK_MOD_VAL + * [|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]* * * Register values are encoded as: * NAME:TYPE:SIZE @@ -1222,29 +1223,29 @@ static int format_xml_insn( x86_insn_t *insn, char *buf, int len ) { len -= format_insn_eflags_str( insn->flags_tested, buf, len ); STRNCAT( buf, "\"/>\n\t\n", len ); - if ( insn->x86_operand_1st() ) { - insn->x86_operand_1st()->x86_format_operand(str, + if ( insn->x86_operand_1st() ) { + insn->x86_operand_1st()->x86_format_operand(str, sizeof str, xml_syntax); - STRNCAT( buf, "\t\n", len ); - STRNCAT( buf, str, len ); - STRNCAT( buf, "\t\n", len ); - } + STRNCAT( buf, "\t\n", len ); + STRNCAT( buf, str, len ); + STRNCAT( buf, "\t\n", len ); + } - if ( insn->x86_operand_2nd() ) { - insn->x86_operand_2nd()->x86_format_operand(str,sizeof str, + if ( insn->x86_operand_2nd() ) { + insn->x86_operand_2nd()->x86_format_operand(str,sizeof str, xml_syntax); - STRNCAT( buf, "\t\n", len ); - STRNCAT( buf, str, len ); - STRNCAT( buf, "\t\n", len ); - } + STRNCAT( buf, "\t\n", len ); + STRNCAT( buf, str, len ); + STRNCAT( buf, "\t\n", len ); + } - if ( insn->x86_operand_3rd() ) { - insn->x86_operand_3rd()->x86_format_operand(str,sizeof str, + if ( insn->x86_operand_3rd() ) { + insn->x86_operand_3rd()->x86_format_operand(str,sizeof str, xml_syntax); - STRNCAT( buf, "\t\n", len ); - STRNCAT( buf, str, len ); - STRNCAT( buf, "\t\n", len ); - } + STRNCAT( buf, "\t\n", len ); + STRNCAT( buf, str, len ); + STRNCAT( buf, "\t\n", len ); + } STRNCAT( buf, "\n", len ); @@ -1266,9 +1267,9 @@ int X86_Disasm::x86_format_header( char *buf, int len, enum x86_asm_format forma case raw_syntax: snprintf( buf, len, "ADDRESS|OFFSET|SIZE|BYTES|" "PREFIX|PREFIX_STRING|GROUP|TYPE|NOTES|" - "MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED|" - "STACK_MOD|STACK_MOD_VAL" - "[|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]*" + "MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED|" + "STACK_MOD|STACK_MOD_VAL" + "[|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]*" ); break; case xml_syntax: @@ -1277,11 +1278,11 @@ int X86_Disasm::x86_format_header( char *buf, int len, enum x86_asm_format forma "
" "" "" + "cpu= isa= note= />" "" "" "" - "" + "" "" "" "" @@ -1315,16 +1316,18 @@ int X86_Disasm::x86_format_header( char *buf, int len, enum x86_asm_format forma "" ); break; - case unknown_syntax: - if ( len ) { - buf[0] = '\0'; - } - break; + case unknown_syntax: + if ( len ) { + buf[0] = '\0'; + } + break; } return( strlen(buf) ); } +/** format (sprintf) an instruction into 'buf' using specified syntax; + * this includes formatting all operands */ int x86_insn_t::x86_format_insn( char *buf, int len, enum x86_asm_format format ){ char str[MAX_OP_STRING]; diff --git a/3rd_party/libdisasm/x86_insn.cpp b/3rd_party/libdisasm/x86_insn.cpp index aa85574..2733c59 100644 --- a/3rd_party/libdisasm/x86_insn.cpp +++ b/3rd_party/libdisasm/x86_insn.cpp @@ -17,7 +17,8 @@ int x86_insn_is_valid( x86_insn_t *insn ) { return 0; } -int x86_insn_t::x86_insn_is_valid( ) +/** \returns false if an instruction is invalid, true if valid */ +bool x86_insn_t::is_valid( ) { if ( this && this->type != insn_invalid && this->size > 0 ) { @@ -26,10 +27,15 @@ int x86_insn_t::x86_insn_is_valid( ) return 0; } -uint32_t x86_insn_t::x86_get_address() { +/* Get Address: return the value of an offset operand, or the offset of + * a segment:offset absolute address */ + +uint32_t x86_insn_t::x86_get_address() +{ x86_oplist_t *op_lst; assert(this); - if (! operands ) { + if (! operands ) + { return 0; } @@ -48,6 +54,9 @@ uint32_t x86_insn_t::x86_get_address() { return 0; } +/** Get Relative Offset: return as a sign-extended int32_t the near or far + * relative offset operand, or 0 if there is none. There can be only one + * relaive offset operand in an instruction. */ int32_t x86_insn_t::x86_get_rel_offset( ) { x86_oplist_t *op_lst; assert(this); @@ -66,6 +75,10 @@ int32_t x86_insn_t::x86_get_rel_offset( ) { return 0; } +/** Get Branch Target: return the x86_op_t containing the target of + * a jump or call operand, or NULL if there is no branch target. + * Internally, a 'branch target' is defined as any operand with + * Execute Access set. There can be only one branch target per instruction. */ x86_op_t * x86_insn_t::x86_get_branch_target() { x86_oplist_t *op_lst; assert(this); @@ -81,6 +94,24 @@ x86_op_t * x86_insn_t::x86_get_branch_target() { return NULL; } +x86_op_t * x86_insn_t::get_dest() { + x86_oplist_t *op_lst; + assert(this); + if ( ! operands ) { + return NULL; + } + assert(this->x86_operand_count(op_dest)==1); + for (op_lst = operands; op_lst; op_lst = op_lst->next ) { + if ( op_lst->op.access & op_write) + return &(op_lst->op); + } + + return NULL; +} + +/** \brief Get Immediate: return the x86_op_t containing the immediate operand + for this instruction, or NULL if there is no immediate operand. There + can be only one immediate operand per instruction */ x86_op_t * x86_insn_t::x86_get_imm() { x86_oplist_t *op_lst; assert(this); @@ -101,9 +132,15 @@ x86_op_t * x86_insn_t::x86_get_imm() { x->op.type == op_immediate && ! (x->op.flags.op_hardcode) -/* if there is an immediate value in the instruction, return a pointer to - * it */ -unsigned char * x86_insn_t::x86_get_raw_imm() { +/** \brief if there is an immediate value in the instruction, return a pointer to it + * Get Raw Immediate Data: returns a pointer to the immediate data encoded + * in the instruction. This is useful for large data types [>32 bits] currently + * not supported by libdisasm, or for determining if the disassembler + * screwed up the conversion of the immediate data. Note that 'imm' in this + * context refers to immediate data encoded at the end of an instruction as + * detailed in the Intel Manual Vol II Chapter 2; it does not refer to the + * 'op_imm' operand (the third operand in instructions like 'mul' */ +uint8_t *x86_insn_t::x86_get_raw_imm() { int size, offset; x86_op_t *op = NULL; assert(this); @@ -128,13 +165,13 @@ unsigned char * x86_insn_t::x86_get_raw_imm() { } /* immediate data is at the end of the insn */ - size = op->x86_operand_size(); + size = op->operand_size(); offset = size - size; return( &bytes[offset] ); } -size_t x86_op_t::x86_operand_size() { +size_t x86_op_t::operand_size() { switch (datatype ) { case op_byte: return 1; case op_word: return 2; @@ -166,6 +203,7 @@ size_t x86_op_t::x86_operand_size() { return(4); /* default size */ } +/** set the address (usually RVA) of the insn */ void x86_insn_t::x86_set_insn_addr( uint32_t _addr ) { addr = _addr; } @@ -182,6 +220,7 @@ void x86_insn_t::x86_set_insn_block( void * _block ){ block = _block; } +/** set insn->tag to 1 */ void x86_insn_t::x86_tag_insn(){ tag = 1; } @@ -190,6 +229,7 @@ void x86_insn_t::x86_untag_insn(){ tag = 0; } +/** \return insn->tag */ int x86_insn_t::x86_insn_is_tagged(){ return tag; } diff --git a/3rd_party/libdisasm/x86_operand_list.cpp b/3rd_party/libdisasm/x86_operand_list.cpp index a9d6652..0d1cf18 100644 --- a/3rd_party/libdisasm/x86_operand_list.cpp +++ b/3rd_party/libdisasm/x86_operand_list.cpp @@ -4,31 +4,31 @@ void x86_insn_t::x86_oplist_append( x86_oplist_t *op ) { - x86_oplist_t *list; + x86_oplist_t *list; assert(this); - list = operands; - if (! list ) { - operand_count = 1; - /* Note that we have no way of knowing if this is an + list = operands; + if (! list ) { + operand_count = 1; + /* Note that we have no way of knowing if this is an * exlicit operand or not, since the caller fills * the x86_op_t after we return. We increase the * explicit count automatically, and ia32_insn_implicit_ops * decrements it */ - explicit_count = 1; - operands = op; - return; - } - - /* get to end of list */ - for ( ; list->next; list = list->next ) - ; - - operand_count = operand_count + 1; - explicit_count = explicit_count + 1; - list->next = op; - + explicit_count = 1; + operands = op; return; + } + + /* get to end of list */ + for ( ; list->next; list = list->next ) + ; + + operand_count = operand_count + 1; + explicit_count = explicit_count + 1; + list->next = op; + + return; } bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in) @@ -48,7 +48,7 @@ bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in) return (in & (insn_dir_set | insn_dir_clear))!=0; case insn_eflag_sign: return (in & (insn_sign_set | insn_sign_clear | insn_zero_set_or_sign_ne_oflow | - insn_sign_eq_oflow | insn_sign_ne_oflow))!=0; + insn_sign_eq_oflow | insn_sign_ne_oflow))!=0; case insn_eflag_parity: return (in & (insn_parity_set | insn_parity_clear))!=0; } @@ -56,151 +56,154 @@ bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in) } x86_op_t * x86_insn_t::x86_operand_new( ) { - x86_oplist_t *op; + x86_oplist_t *op; assert(this); - op = (x86_oplist_t *)calloc( sizeof(x86_oplist_t), 1 ); - op->op.insn = this; - x86_oplist_append( op ); - return( &(op->op) ); + op = (x86_oplist_t *)calloc( sizeof(x86_oplist_t), 1 ); + op->op.insn = this; + x86_oplist_append( op ); + return( &(op->op) ); } +/** free the operand list associated with an instruction -- useful for + * preventing memory leaks when free()ing an x86_insn_t */ void x86_insn_t::x86_oplist_free( ) { - x86_oplist_t *op, *list; + x86_oplist_t *op, *list; assert(this); - for ( list = operands; list; ) { - op = list; - list = list->next; - free(op); - } + for ( list = operands; list; ) { + op = list; + list = list->next; + free(op); + } - operands = NULL; - operand_count = 0; - explicit_count = 0; + operands = NULL; + operand_count = 0; + explicit_count = 0; - return; + return; } /* ================================================== LIBDISASM API */ /* these could probably just be #defines, but that means exposing the enum... yet one more confusing thing in the API */ -int x86_insn_t::x86_operand_foreach( x86_operand_fn func, void *arg, - enum x86_op_foreach_type type ){ - x86_oplist_t *list; - char _explicit = 1, implicit = 1; +int x86_insn_t::x86_operand_foreach( x86_operand_fn func, void *arg, enum x86_op_foreach_type type ) +{ + x86_oplist_t *list; + char _explicit = 1, implicit = 1; assert(this); - if ( ! func ) { - return 0; - } + if ( ! func ) { + return 0; + } - /* note: explicit and implicit can be ORed together to + /* note: explicit and implicit can be ORed together to * allow an "all" limited by access type, even though the * user is stupid to do this since it is default behavior :) */ - if ( (type & op_explicit) && ! (type & op_implicit) ) { - implicit = 0; - } - if ( (type & op_implicit) && ! (type & op_explicit) ) { - _explicit = 0; + if ( (type & op_explicit) && ! (type & op_implicit) ) { + implicit = 0; + } + if ( (type & op_implicit) && ! (type & op_explicit) ) { + _explicit = 0; + } + + type = (x86_op_foreach_type)((int)type & 0x0F); /* mask out explicit/implicit operands */ + + for ( list = operands; list; list = list->next ) { + if (! implicit && (list->op.flags.op_implied) ) { + /* operand is implicit */ + continue; } - type = (x86_op_foreach_type)((int)type & 0x0F); /* mask out explicit/implicit operands */ - - for ( list = operands; list; list = list->next ) { - if (! implicit && (list->op.flags.op_implied) ) { - /* operand is implicit */ - continue; - } - - if (! _explicit && ! (list->op.flags.op_implied) ) { - /* operand is not implicit */ - continue; - } - - switch ( type ) { - case op_any: - break; - case op_dest: - if (! (list->op.access & op_write) ) { - continue; - } - break; - case op_src: - if (! (list->op.access & op_read) ) { - continue; - } - break; - case op_ro: - if (! (list->op.access & op_read) || - (list->op.access & op_write ) ) { - continue; - } - break; - case op_wo: - if (! (list->op.access & op_write) || - (list->op.access & op_read ) ) { - continue; - } - break; - case op_xo: - if (! (list->op.access & op_execute) ) { - continue; - } - break; - case op_rw: - if (! (list->op.access & op_write) || - ! (list->op.access & op_read ) ) { - continue; - } - break; - case op_implicit: case op_explicit: /* make gcc happy */ - break; - } - /* any non-continue ends up here: invoke the callback */ - (*func)( &list->op, this, arg ); + if (! _explicit && ! (list->op.flags.op_implied) ) { + /* operand is not implicit */ + continue; } - return 1; + switch ( type ) { + case op_any: + break; + case op_dest: + if (! (list->op.access & op_write) ) { + continue; + } + break; + case op_src: + if (! (list->op.access & op_read) ) { + continue; + } + break; + case op_ro: + if (! (list->op.access & op_read) || + (list->op.access & op_write ) ) { + continue; + } + break; + case op_wo: + if (! (list->op.access & op_write) || + (list->op.access & op_read ) ) { + continue; + } + break; + case op_xo: + if (! (list->op.access & op_execute) ) { + continue; + } + break; + case op_rw: + if (! (list->op.access & op_write) || + ! (list->op.access & op_read ) ) { + continue; + } + break; + case op_implicit: case op_explicit: /* make gcc happy */ + break; + } + /* any non-continue ends up here: invoke the callback */ + (*func)( &list->op, this, arg ); + } + + return 1; } static void count_operand( x86_op_t *op, x86_insn_t *insn, void *arg ) { - size_t * count = (size_t *) arg; - *count = *count + 1; + size_t * count = (size_t *) arg; + *count = *count + 1; } +/** convenience routine: returns count of operands matching 'type' */ size_t x86_insn_t::x86_operand_count( enum x86_op_foreach_type type ) { - size_t count = 0; + size_t count = 0; - /* save us a list traversal for common counts... */ - if ( type == op_any ) { - return operand_count; - } else if ( type == op_explicit ) { - return explicit_count; - } + /* save us a list traversal for common counts... */ + if ( type == op_any ) { + return operand_count; + } else if ( type == op_explicit ) { + return explicit_count; + } - x86_operand_foreach( count_operand, &count, type ); - return count; + x86_operand_foreach( count_operand, &count, type ); + return count; } /* accessor functions */ x86_op_t * x86_insn_t::x86_operand_1st() { - if (! explicit_count ) { - return NULL; - } + if (! explicit_count ) { + return NULL; + } - return &(operands->op); + return &(operands->op); } x86_op_t * x86_insn_t::x86_operand_2nd( ) { - if ( explicit_count < 2 ) { - return NULL; - } + if ( explicit_count < 2 ) { + return NULL; + } - return &(operands->next->op); + return &(operands->next->op); } x86_op_t * x86_insn_t::x86_operand_3rd( ) { - if ( explicit_count < 3 ) { - return NULL; - } - return &(operands->next->next->op); + if ( explicit_count < 3 ) { + return NULL; + } + return &(operands->next->next->op); }