A few changes to libdisasm
This commit is contained in:
parent
71fc8bfef7
commit
fee4d6fe9a
314
3rd_party/libdisasm/ia32_reg.cpp
vendored
314
3rd_party/libdisasm/ia32_reg.cpp
vendored
@ -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
|
||||
* 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_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_INDEX : 83*/
|
||||
{ REG_FPSTATUS_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fpstat" },
|
||||
/* REG_FPTAG_INDEX : 84 */
|
||||
/* 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_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;
|
||||
}
|
||||
|
||||
174
3rd_party/libdisasm/libdis.h
vendored
174
3rd_party/libdisasm/libdis.h
vendored
@ -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();
|
||||
|
||||
371
3rd_party/libdisasm/x86_format.cpp
vendored
371
3rd_party/libdisasm/x86_format.cpp
vendored
@ -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 ){
|
||||
|
||||
@ -271,7 +271,7 @@ static int format_expr( x86_ea_t *ea, char *buf, int len,
|
||||
}
|
||||
|
||||
if ( ea->disp_size || (! ea->index.name[0] &&
|
||||
! ea->base.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];
|
||||
}
|
||||
@ -664,29 +664,29 @@ static int format_operand_att( x86_op_t *op, x86_insn_t *insn, char *buf,
|
||||
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,25 +824,25 @@ 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\t<absolute_address segment=\"0x%04" PRIX16 "\"",
|
||||
op->data.absolute.segment, len );
|
||||
"\t\t<absolute_address segment=\"0x%04" PRIX16 "\"",
|
||||
op->data.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</absolute_address>\n", len );
|
||||
break;
|
||||
@ -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</flags>\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<operand name=dest>\n", len );
|
||||
STRNCAT( buf, str, len );
|
||||
STRNCAT( buf, "\t</operand>\n", len );
|
||||
}
|
||||
STRNCAT( buf, "\t<operand name=dest>\n", len );
|
||||
STRNCAT( buf, str, len );
|
||||
STRNCAT( buf, "\t</operand>\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<operand name=src>\n", len );
|
||||
STRNCAT( buf, str, len );
|
||||
STRNCAT( buf, "\t</operand>\n", len );
|
||||
}
|
||||
STRNCAT( buf, "\t<operand name=src>\n", len );
|
||||
STRNCAT( buf, str, len );
|
||||
STRNCAT( buf, "\t</operand>\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<operand name=imm>\n", len );
|
||||
STRNCAT( buf, str, len );
|
||||
STRNCAT( buf, "\t</operand>\n", len );
|
||||
}
|
||||
STRNCAT( buf, "\t<operand name=imm>\n", len );
|
||||
STRNCAT( buf, str, len );
|
||||
STRNCAT( buf, "\t</operand>\n", len );
|
||||
}
|
||||
|
||||
STRNCAT( buf, "</x86_insn>\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
|
||||
"<address rva= offset= size= bytes=/>"
|
||||
"<prefix type= string=/>"
|
||||
"<mnemonic group= type= string= "
|
||||
"cpu= isa= note= />"
|
||||
"cpu= isa= note= />"
|
||||
"<flags type=set>"
|
||||
"<flag name=>"
|
||||
"</flags>"
|
||||
"<stack_mod val= >"
|
||||
"<stack_mod val= >"
|
||||
"<flags type=tested>"
|
||||
"<flag name=>"
|
||||
"</flags>"
|
||||
@ -1315,16 +1316,18 @@ int X86_Disasm::x86_format_header( char *buf, int len, enum x86_asm_format forma
|
||||
"</x86_insn>"
|
||||
);
|
||||
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];
|
||||
|
||||
56
3rd_party/libdisasm/x86_insn.cpp
vendored
56
3rd_party/libdisasm/x86_insn.cpp
vendored
@ -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;
|
||||
}
|
||||
|
||||
253
3rd_party/libdisasm/x86_operand_list.cpp
vendored
253
3rd_party/libdisasm/x86_operand_list.cpp
vendored
@ -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);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user