removed most of clang warnings / errors
This commit is contained in:
666
3rd_party/libdisasm/ia32_implicit.cpp
vendored
666
3rd_party/libdisasm/ia32_implicit.cpp
vendored
@@ -5,7 +5,7 @@
|
||||
#include "ia32_reg.h"
|
||||
#include "x86_operand_list.h"
|
||||
|
||||
/* Conventions: Register operands which are aliases of another register
|
||||
/* Conventions: Register operands which are aliases of another register
|
||||
* operand (e.g. AX in one operand and AL in another) assume that the
|
||||
* operands are different registers and that alias tracking will resolve
|
||||
* data flow. This means that something like
|
||||
@@ -13,412 +13,412 @@
|
||||
* would have 'write only' access for AX and 'read only' access for AL,
|
||||
* even though both AL and AX are read and written */
|
||||
typedef struct {
|
||||
uint32_t type;
|
||||
uint32_t operand;
|
||||
uint32_t type;
|
||||
uint32_t operand;
|
||||
} op_implicit_list_t;
|
||||
|
||||
static op_implicit_list_t list_aaa[] =
|
||||
/* 37 : AAA : rw AL */
|
||||
/* 3F : AAS : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* aaa */
|
||||
static op_implicit_list_t list_aaa[] =
|
||||
/* 37 : AAA : rw AL */
|
||||
/* 3F : AAS : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* aaa */
|
||||
|
||||
static op_implicit_list_t list_aad[] =
|
||||
/* D5 0A, D5 (ib) : AAD : rw AX */
|
||||
/* D4 0A, D4 (ib) : AAM : rw AX */
|
||||
{{ OP_R | OP_W, REG_WORD_OFFSET }, {0}}; /* aad */
|
||||
static op_implicit_list_t list_aad[] =
|
||||
/* D5 0A, D5 (ib) : AAD : rw AX */
|
||||
/* D4 0A, D4 (ib) : AAM : rw AX */
|
||||
{{ OP_R | OP_W, REG_WORD_OFFSET }, {0,0}}; /* aad */
|
||||
|
||||
static op_implicit_list_t list_call[] =
|
||||
/* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
|
||||
/* C2, C3, CA, CB : RET : rw ESP, rw EIP */
|
||||
{{ OP_R | OP_W, REG_EIP_INDEX },
|
||||
{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* call, ret */
|
||||
static op_implicit_list_t list_call[] =
|
||||
/* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
|
||||
/* C2, C3, CA, CB : RET : rw ESP, rw EIP */
|
||||
{{ OP_R | OP_W, REG_EIP_INDEX },
|
||||
{ OP_R | OP_W, REG_ESP_INDEX }, {0,0}}; /* call, ret */
|
||||
|
||||
static op_implicit_list_t list_cbw[] =
|
||||
/* 98 : CBW : r AL, rw AX */
|
||||
{{ OP_R | OP_W, REG_WORD_OFFSET },
|
||||
{ OP_R, REG_BYTE_OFFSET}, {0}}; /* cbw */
|
||||
static op_implicit_list_t list_cbw[] =
|
||||
/* 98 : CBW : r AL, rw AX */
|
||||
{{ OP_R | OP_W, REG_WORD_OFFSET },
|
||||
{ OP_R, REG_BYTE_OFFSET}, {0,0}}; /* cbw */
|
||||
|
||||
static op_implicit_list_t list_cwde[] =
|
||||
/* 98 : CWDE : r AX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_R, REG_WORD_OFFSET }, {0}}; /* cwde */
|
||||
static op_implicit_list_t list_cwde[] =
|
||||
/* 98 : CWDE : r AX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_R, REG_WORD_OFFSET }, {0,0}}; /* cwde */
|
||||
|
||||
static op_implicit_list_t list_clts[] =
|
||||
/* 0F 06 : CLTS : rw CR0 */
|
||||
{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0}}; /* clts */
|
||||
static op_implicit_list_t list_clts[] =
|
||||
/* 0F 06 : CLTS : rw CR0 */
|
||||
{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0,0}}; /* clts */
|
||||
|
||||
static op_implicit_list_t list_cmpxchg[] =
|
||||
/* 0F B0 : CMPXCHG : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* cmpxchg */
|
||||
static op_implicit_list_t list_cmpxchg[] =
|
||||
/* 0F B0 : CMPXCHG : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* cmpxchg */
|
||||
|
||||
static op_implicit_list_t list_cmpxchgb[] =
|
||||
/* 0F B1 : CMPXCHG : rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* cmpxchg */
|
||||
static op_implicit_list_t list_cmpxchgb[] =
|
||||
/* 0F B1 : CMPXCHG : rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* cmpxchg */
|
||||
|
||||
static op_implicit_list_t list_cmpxchg8b[] =
|
||||
/* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 3 }, {0}}; /* cmpxchg8b */
|
||||
static op_implicit_list_t list_cmpxchg8b[] =
|
||||
/* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cmpxchg8b */
|
||||
|
||||
static op_implicit_list_t list_cpuid[] =
|
||||
/* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 3 }, {0}}; /* cpuid */
|
||||
static op_implicit_list_t list_cpuid[] =
|
||||
/* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cpuid */
|
||||
|
||||
static op_implicit_list_t list_cwd[] =
|
||||
/* 99 : CWD/CWQ : rw EAX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* cwd */
|
||||
static op_implicit_list_t list_cwd[] =
|
||||
/* 99 : CWD/CWQ : rw EAX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* cwd */
|
||||
|
||||
static op_implicit_list_t list_daa[] =
|
||||
/* 27 : DAA : rw AL */
|
||||
/* 2F : DAS : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* daa */
|
||||
static op_implicit_list_t list_daa[] =
|
||||
/* 27 : DAA : rw AL */
|
||||
/* 2F : DAS : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* daa */
|
||||
|
||||
static op_implicit_list_t list_idiv[] =
|
||||
/* F6 : DIV, IDIV : r AX, w AL, w AH */
|
||||
/* FIXED: first op was EAX, not Aw. TODO: verify! */
|
||||
{{ OP_R, REG_WORD_OFFSET },
|
||||
{ OP_W, REG_BYTE_OFFSET },
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* div */
|
||||
static op_implicit_list_t list_idiv[] =
|
||||
/* F6 : DIV, IDIV : r AX, w AL, w AH */
|
||||
/* FIXED: first op was EAX, not Aw. TODO: verify! */
|
||||
{{ OP_R, REG_WORD_OFFSET },
|
||||
{ OP_W, REG_BYTE_OFFSET },
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* div */
|
||||
|
||||
static op_implicit_list_t list_div[] =
|
||||
/* F7 : DIV, IDIV : rw EDX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* div */
|
||||
static op_implicit_list_t list_div[] =
|
||||
/* F7 : DIV, IDIV : rw EDX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* div */
|
||||
|
||||
static op_implicit_list_t list_enter[] =
|
||||
/* C8 : ENTER : rw ESP w EBP */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 4 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 5 }, {0}}; /* enter */
|
||||
static op_implicit_list_t list_enter[] =
|
||||
/* C8 : ENTER : rw ESP w EBP */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 4 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 5 }, {0,0}}; /* enter */
|
||||
|
||||
static op_implicit_list_t list_f2xm1[] =
|
||||
/* D9 F0 : F2XM1 : rw ST(0) */
|
||||
/* D9 E1 : FABS : rw ST(0) */
|
||||
/* D9 E0 : FCHS : rw ST(0) */
|
||||
/* D9 FF : FCOS : rw ST(0)*/
|
||||
/* D8, DA : FDIV : rw ST(0) */
|
||||
/* D8, DA : FDIVR : rw ST(0) */
|
||||
/* D9 F2 : FPTAN : rw ST(0) */
|
||||
/* D9 FC : FRNDINT : rw ST(0) */
|
||||
/* D9 FB : FSINCOS : rw ST(0) */
|
||||
/* D9 FE : FSIN : rw ST(0) */
|
||||
/* D9 FA : FSQRT : rw ST(0) */
|
||||
/* D9 F4 : FXTRACT : rw ST(0) */
|
||||
{{ OP_R | OP_W, REG_FPU_OFFSET }, {0}}; /* f2xm1 */
|
||||
static op_implicit_list_t list_f2xm1[] =
|
||||
/* D9 F0 : F2XM1 : rw ST(0) */
|
||||
/* D9 E1 : FABS : rw ST(0) */
|
||||
/* D9 E0 : FCHS : rw ST(0) */
|
||||
/* D9 FF : FCOS : rw ST(0)*/
|
||||
/* D8, DA : FDIV : rw ST(0) */
|
||||
/* D8, DA : FDIVR : rw ST(0) */
|
||||
/* D9 F2 : FPTAN : rw ST(0) */
|
||||
/* D9 FC : FRNDINT : rw ST(0) */
|
||||
/* D9 FB : FSINCOS : rw ST(0) */
|
||||
/* D9 FE : FSIN : rw ST(0) */
|
||||
/* D9 FA : FSQRT : rw ST(0) */
|
||||
/* D9 F4 : FXTRACT : rw ST(0) */
|
||||
{{ OP_R | OP_W, REG_FPU_OFFSET }, {0,0}}; /* f2xm1 */
|
||||
|
||||
static op_implicit_list_t list_fcom[] =
|
||||
/* D8, DC, DE D9 : FCOM : r ST(0) */
|
||||
/* DE, DA : FICOM : r ST(0) */
|
||||
/* DF, D8 : FIST : r ST(0) */
|
||||
/* D9 E4 : FTST : r ST(0) */
|
||||
/* D9 E5 : FXAM : r ST(0) */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0}}; /* fcom */
|
||||
static op_implicit_list_t list_fcom[] =
|
||||
/* D8, DC, DE D9 : FCOM : r ST(0) */
|
||||
/* DE, DA : FICOM : r ST(0) */
|
||||
/* DF, D8 : FIST : r ST(0) */
|
||||
/* D9 E4 : FTST : r ST(0) */
|
||||
/* D9 E5 : FXAM : r ST(0) */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fcom */
|
||||
|
||||
static op_implicit_list_t list_fpatan[] =
|
||||
/* D9 F3 : FPATAN : r ST(0), rw ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0}}; /* fpatan */
|
||||
static op_implicit_list_t list_fpatan[] =
|
||||
/* D9 F3 : FPATAN : r ST(0), rw ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fpatan */
|
||||
|
||||
static op_implicit_list_t list_fprem[] =
|
||||
/* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
|
||||
/* D9 FD : FSCALE : rw ST(0), r ST(1) */
|
||||
{{ OP_R | OP_W, REG_FPU_OFFSET },
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fprem */
|
||||
static op_implicit_list_t list_fprem[] =
|
||||
/* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
|
||||
/* D9 FD : FSCALE : rw ST(0), r ST(1) */
|
||||
{{ OP_R | OP_W, REG_FPU_OFFSET },
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fprem */
|
||||
|
||||
static op_implicit_list_t list_faddp[] =
|
||||
/* DE C1 : FADDP : r ST(0), rw ST(1) */
|
||||
/* DE E9 : FSUBP : r ST(0), rw ST(1) */
|
||||
/* D9 F1 : FYL2X : r ST(0), rw ST(1) */
|
||||
/* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET },
|
||||
{ OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0}}; /* faddp */
|
||||
static op_implicit_list_t list_faddp[] =
|
||||
/* DE C1 : FADDP : r ST(0), rw ST(1) */
|
||||
/* DE E9 : FSUBP : r ST(0), rw ST(1) */
|
||||
/* D9 F1 : FYL2X : r ST(0), rw ST(1) */
|
||||
/* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET },
|
||||
{ OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0,0}}; /* faddp */
|
||||
|
||||
static op_implicit_list_t list_fucompp[] =
|
||||
/* DA E9 : FUCOMPP : r ST(0), r ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET },
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fucompp */
|
||||
static op_implicit_list_t list_fucompp[] =
|
||||
/* DA E9 : FUCOMPP : r ST(0), r ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET },
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fucompp */
|
||||
|
||||
static op_implicit_list_t list_imul[] =
|
||||
/* F6 : IMUL : r AL, w AX */
|
||||
/* F6 : MUL : r AL, w AX */
|
||||
{{ OP_R, REG_BYTE_OFFSET },
|
||||
{ OP_W, REG_WORD_OFFSET }, {0}}; /* imul */
|
||||
static op_implicit_list_t list_imul[] =
|
||||
/* F6 : IMUL : r AL, w AX */
|
||||
/* F6 : MUL : r AL, w AX */
|
||||
{{ OP_R, REG_BYTE_OFFSET },
|
||||
{ OP_W, REG_WORD_OFFSET }, {0,0}}; /* imul */
|
||||
|
||||
static op_implicit_list_t list_mul[] =
|
||||
/* F7 : IMUL : rw EAX, w EDX */
|
||||
/* F7 : MUL : rw EAX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* imul */
|
||||
static op_implicit_list_t list_mul[] =
|
||||
/* F7 : IMUL : rw EAX, w EDX */
|
||||
/* F7 : MUL : rw EAX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* imul */
|
||||
|
||||
static op_implicit_list_t list_lahf[] =
|
||||
/* 9F : LAHF : r EFLAGS, w AH */
|
||||
{{ OP_R, REG_FLAGS_INDEX },
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* lahf */
|
||||
static op_implicit_list_t list_lahf[] =
|
||||
/* 9F : LAHF : r EFLAGS, w AH */
|
||||
{{ OP_R, REG_FLAGS_INDEX },
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* lahf */
|
||||
|
||||
static op_implicit_list_t list_ldmxcsr[] =
|
||||
/* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
|
||||
{{ OP_W, REG_MXCSG_INDEX }, {0}}; /* ldmxcsr */
|
||||
static op_implicit_list_t list_ldmxcsr[] =
|
||||
/* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
|
||||
{{ OP_W, REG_MXCSG_INDEX }, {0,0}}; /* ldmxcsr */
|
||||
|
||||
static op_implicit_list_t list_leave[] =
|
||||
/* C9 : LEAVE : rw ESP, w EBP */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_DWORD_OFFSET + 5 }, {0}}; /* leave */
|
||||
static op_implicit_list_t list_leave[] =
|
||||
/* C9 : LEAVE : rw ESP, w EBP */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_DWORD_OFFSET + 5 }, {0,0}}; /* leave */
|
||||
|
||||
static op_implicit_list_t list_lgdt[] =
|
||||
/* 0F 01 : LGDT : w GDTR */
|
||||
{{ OP_W, REG_GDTR_INDEX }, {0}}; /* lgdt */
|
||||
static op_implicit_list_t list_lgdt[] =
|
||||
/* 0F 01 : LGDT : w GDTR */
|
||||
{{ OP_W, REG_GDTR_INDEX }, {0,0}}; /* lgdt */
|
||||
|
||||
static op_implicit_list_t list_lidt[] =
|
||||
/* 0F 01 : LIDT : w IDTR */
|
||||
{{ OP_W, REG_IDTR_INDEX }, {0}}; /* lidt */
|
||||
static op_implicit_list_t list_lidt[] =
|
||||
/* 0F 01 : LIDT : w IDTR */
|
||||
{{ OP_W, REG_IDTR_INDEX }, {0,0}}; /* lidt */
|
||||
|
||||
static op_implicit_list_t list_lldt[] =
|
||||
/* 0F 00 : LLDT : w LDTR */
|
||||
{{ OP_W, REG_LDTR_INDEX }, {0}}; /* lldt */
|
||||
static op_implicit_list_t list_lldt[] =
|
||||
/* 0F 00 : LLDT : w LDTR */
|
||||
{{ OP_W, REG_LDTR_INDEX }, {0,0}}; /* lldt */
|
||||
|
||||
static op_implicit_list_t list_lmsw[] =
|
||||
/* 0F 01 : LMSW : w CR0 */
|
||||
{{ OP_W, REG_CTRL_OFFSET }, {0}}; /* lmsw */
|
||||
static op_implicit_list_t list_lmsw[] =
|
||||
/* 0F 01 : LMSW : w CR0 */
|
||||
{{ OP_W, REG_CTRL_OFFSET }, {0,0}}; /* lmsw */
|
||||
|
||||
static op_implicit_list_t list_loop[] =
|
||||
/* E0, E1, E2 : LOOP : rw ECX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* loop */
|
||||
static op_implicit_list_t list_loop[] =
|
||||
/* E0, E1, E2 : LOOP : rw ECX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* loop */
|
||||
|
||||
static op_implicit_list_t list_ltr[] =
|
||||
/* 0F 00 : LTR : w Task Register */
|
||||
{{ OP_W, REG_TR_INDEX }, {0}}; /* ltr */
|
||||
static op_implicit_list_t list_ltr[] =
|
||||
/* 0F 00 : LTR : w Task Register */
|
||||
{{ OP_W, REG_TR_INDEX }, {0,0}}; /* ltr */
|
||||
|
||||
static op_implicit_list_t list_pop[] =
|
||||
/* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */
|
||||
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* pop, push */
|
||||
static op_implicit_list_t list_pop[] =
|
||||
/* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */
|
||||
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX }, {0,0}}; /* pop, push */
|
||||
|
||||
static op_implicit_list_t list_popad[] =
|
||||
/* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_DWORD_OFFSET + 7 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 6 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 5 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 3 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* popad */
|
||||
static op_implicit_list_t list_popad[] =
|
||||
/* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_DWORD_OFFSET + 7 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 6 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 5 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 3 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* popad */
|
||||
|
||||
static op_implicit_list_t list_popfd[] =
|
||||
/* 9D : POPFD : rw esp, w eflags */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_FLAGS_INDEX }, {0}}; /* popfd */
|
||||
static op_implicit_list_t list_popfd[] =
|
||||
/* 9D : POPFD : rw esp, w eflags */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_FLAGS_INDEX }, {0,0}}; /* popfd */
|
||||
|
||||
static op_implicit_list_t list_pushad[] =
|
||||
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
|
||||
/* 60 : PUSHAD : rw esp, r eax ecx edx ebx esp ebp esi edi */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_R, REG_DWORD_OFFSET },
|
||||
{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 3 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 5 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 6 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 7 }, {0}}; /* pushad */
|
||||
static op_implicit_list_t list_pushad[] =
|
||||
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
|
||||
/* 60 : PUSHAD : rw esp, r eax ecx edx ebx esp ebp esi edi */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_R, REG_DWORD_OFFSET },
|
||||
{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 3 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 5 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 6 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 7 }, {0,0}}; /* pushad */
|
||||
|
||||
static op_implicit_list_t list_pushfd[] =
|
||||
/* 9C : PUSHFD : rw esp, r eflags */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_R, REG_FLAGS_INDEX }, {0}}; /* pushfd */
|
||||
static op_implicit_list_t list_pushfd[] =
|
||||
/* 9C : PUSHFD : rw esp, r eflags */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_R, REG_FLAGS_INDEX }, {0,0}}; /* pushfd */
|
||||
|
||||
static op_implicit_list_t list_rdmsr[] =
|
||||
/* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
|
||||
{{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* rdmsr */
|
||||
static op_implicit_list_t list_rdmsr[] =
|
||||
/* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
|
||||
{{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdmsr */
|
||||
|
||||
static op_implicit_list_t list_rdpmc[] =
|
||||
/* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
|
||||
{{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* rdpmc */
|
||||
static op_implicit_list_t list_rdpmc[] =
|
||||
/* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
|
||||
{{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdpmc */
|
||||
|
||||
static op_implicit_list_t list_rdtsc[] =
|
||||
/* 0F 31 : RDTSC : rw EDX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* rdtsc */
|
||||
static op_implicit_list_t list_rdtsc[] =
|
||||
/* 0F 31 : RDTSC : rw EDX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdtsc */
|
||||
|
||||
static op_implicit_list_t list_rep[] =
|
||||
/* F3, F2 ... : REP : rw ECX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* rep */
|
||||
static op_implicit_list_t list_rep[] =
|
||||
/* F3, F2 ... : REP : rw ECX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* rep */
|
||||
|
||||
static op_implicit_list_t list_rsm[] =
|
||||
/* 0F AA : RSM : r CR4, r CR0 */
|
||||
{{ OP_R, REG_CTRL_OFFSET + 4 },
|
||||
{ OP_R, REG_CTRL_OFFSET }, {0}}; /* rsm */
|
||||
static op_implicit_list_t list_rsm[] =
|
||||
/* 0F AA : RSM : r CR4, r CR0 */
|
||||
{{ OP_R, REG_CTRL_OFFSET + 4 },
|
||||
{ OP_R, REG_CTRL_OFFSET }, {0,0}}; /* rsm */
|
||||
|
||||
static op_implicit_list_t list_sahf[] =
|
||||
/* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sahf */
|
||||
static op_implicit_list_t list_sahf[] =
|
||||
/* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sahf */
|
||||
|
||||
static op_implicit_list_t list_sgdt[] =
|
||||
/* 0F : SGDT : r gdtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sgdt */
|
||||
static op_implicit_list_t list_sgdt[] =
|
||||
/* 0F : SGDT : r gdtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sgdt */
|
||||
|
||||
static op_implicit_list_t list_sidt[] =
|
||||
/* 0F : SIDT : r idtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sidt */
|
||||
static op_implicit_list_t list_sidt[] =
|
||||
/* 0F : SIDT : r idtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sidt */
|
||||
|
||||
static op_implicit_list_t list_sldt[] =
|
||||
/* 0F : SLDT : r ldtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sldt */
|
||||
static op_implicit_list_t list_sldt[] =
|
||||
/* 0F : SLDT : r ldtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sldt */
|
||||
|
||||
static op_implicit_list_t list_smsw[] =
|
||||
/* 0F : SMSW : r CR0 */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* smsw */
|
||||
static op_implicit_list_t list_smsw[] =
|
||||
/* 0F : SMSW : r CR0 */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* smsw */
|
||||
|
||||
static op_implicit_list_t list_stmxcsr[] =
|
||||
/* 0F AE : STMXCSR : r MXCSR */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* stmxcsr */
|
||||
static op_implicit_list_t list_stmxcsr[] =
|
||||
/* 0F AE : STMXCSR : r MXCSR */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* stmxcsr */
|
||||
|
||||
static op_implicit_list_t list_str[] =
|
||||
/* 0F 00 : STR : r TR (task register) */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* str */
|
||||
static op_implicit_list_t list_str[] =
|
||||
/* 0F 00 : STR : r TR (task register) */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* str */
|
||||
|
||||
static op_implicit_list_t list_sysenter[] =
|
||||
/* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags
|
||||
* r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysenter */
|
||||
static op_implicit_list_t list_sysenter[] =
|
||||
/* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags
|
||||
* r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysenter */
|
||||
|
||||
static op_implicit_list_t list_sysexit[] =
|
||||
/* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
|
||||
* r sysenter_cs_msr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysexit */
|
||||
static op_implicit_list_t list_sysexit[] =
|
||||
/* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
|
||||
* r sysenter_cs_msr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysexit */
|
||||
|
||||
static op_implicit_list_t list_wrmsr[] =
|
||||
/* 0F 30 : WRMST : r edx, r eax, r ecx */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* wrmsr */
|
||||
static op_implicit_list_t list_wrmsr[] =
|
||||
/* 0F 30 : WRMST : r edx, r eax, r ecx */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* wrmsr */
|
||||
|
||||
static op_implicit_list_t list_xlat[] =
|
||||
/* D7 : XLAT : rw al r ebx (ptr) */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* xlat */
|
||||
static op_implicit_list_t list_xlat[] =
|
||||
/* D7 : XLAT : rw al r ebx (ptr) */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* xlat */
|
||||
/* TODO:
|
||||
* monitor 0f 01 c8 eax OP_R ecx OP_R edx OP_R
|
||||
* mwait 0f 01 c9 eax OP_R ecx OP_R
|
||||
*/
|
||||
static op_implicit_list_t list_monitor[] =
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* monitor */
|
||||
static op_implicit_list_t list_mwait[] =
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* mwait */
|
||||
static op_implicit_list_t list_monitor[] =
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* monitor */
|
||||
static op_implicit_list_t list_mwait[] =
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* mwait */
|
||||
|
||||
op_implicit_list_t *op_implicit_list[] = {
|
||||
/* This is a list of implicit operands which are read/written by
|
||||
* various x86 instructions. Note that modifications to the stack
|
||||
* register are mentioned here, but that additional information on
|
||||
* the effect an instruction has on the stack is contained in the
|
||||
* x86_insn_t 'stack_mod' and 'stack_mod_val' fields. Use of the
|
||||
* eflags register, i.e. setting, clearing, and testing flags, is
|
||||
* not recorded here but rather in the flags_set and flags_tested
|
||||
* fields of the x86_insn_t.*/
|
||||
NULL,
|
||||
list_aaa, list_aad, list_call, list_cbw, /* 1 - 4 */
|
||||
list_cwde, list_clts, list_cmpxchg, list_cmpxchgb, /* 5 - 8 */
|
||||
list_cmpxchg8b, list_cpuid, list_cwd, list_daa, /* 9 - 12 */
|
||||
list_idiv, list_div, list_enter, list_f2xm1, /* 13 - 16 */
|
||||
list_fcom, list_fpatan, list_fprem, list_faddp, /* 17 - 20 */
|
||||
list_fucompp, list_imul, list_mul, list_lahf, /* 21 - 24 */
|
||||
list_ldmxcsr, list_leave, list_lgdt, list_lidt, /* 25 - 28 */
|
||||
list_lldt, list_lmsw, list_loop, list_ltr, /* 29 - 32 */
|
||||
list_pop, list_popad, list_popfd, list_pushad, /* 33 - 36 */
|
||||
list_pushfd, list_rdmsr, list_rdpmc, list_rdtsc, /* 37 - 40 */
|
||||
/* NOTE: 'REP' is a hack since it is a prefix: if its position
|
||||
* in the table changes, then change IDX_IMPLICIT_REP in the .h */
|
||||
list_rep, list_rsm, list_sahf, list_sgdt, /* 41 - 44 */
|
||||
list_sidt, list_sldt, list_smsw, list_stmxcsr, /* 45 - 48 */
|
||||
list_str, list_sysenter, list_sysexit, list_wrmsr, /* 49 - 52 */
|
||||
list_xlat, list_monitor, list_mwait, /* 53 - 55*/
|
||||
NULL /* end of list */
|
||||
};
|
||||
/* This is a list of implicit operands which are read/written by
|
||||
* various x86 instructions. Note that modifications to the stack
|
||||
* register are mentioned here, but that additional information on
|
||||
* the effect an instruction has on the stack is contained in the
|
||||
* x86_insn_t 'stack_mod' and 'stack_mod_val' fields. Use of the
|
||||
* eflags register, i.e. setting, clearing, and testing flags, is
|
||||
* not recorded here but rather in the flags_set and flags_tested
|
||||
* fields of the x86_insn_t.*/
|
||||
NULL,
|
||||
list_aaa, list_aad, list_call, list_cbw, /* 1 - 4 */
|
||||
list_cwde, list_clts, list_cmpxchg, list_cmpxchgb, /* 5 - 8 */
|
||||
list_cmpxchg8b, list_cpuid, list_cwd, list_daa, /* 9 - 12 */
|
||||
list_idiv, list_div, list_enter, list_f2xm1, /* 13 - 16 */
|
||||
list_fcom, list_fpatan, list_fprem, list_faddp, /* 17 - 20 */
|
||||
list_fucompp, list_imul, list_mul, list_lahf, /* 21 - 24 */
|
||||
list_ldmxcsr, list_leave, list_lgdt, list_lidt, /* 25 - 28 */
|
||||
list_lldt, list_lmsw, list_loop, list_ltr, /* 29 - 32 */
|
||||
list_pop, list_popad, list_popfd, list_pushad, /* 33 - 36 */
|
||||
list_pushfd, list_rdmsr, list_rdpmc, list_rdtsc, /* 37 - 40 */
|
||||
/* NOTE: 'REP' is a hack since it is a prefix: if its position
|
||||
* in the table changes, then change IDX_IMPLICIT_REP in the .h */
|
||||
list_rep, list_rsm, list_sahf, list_sgdt, /* 41 - 44 */
|
||||
list_sidt, list_sldt, list_smsw, list_stmxcsr, /* 45 - 48 */
|
||||
list_str, list_sysenter, list_sysexit, list_wrmsr, /* 49 - 52 */
|
||||
list_xlat, list_monitor, list_mwait, /* 53 - 55*/
|
||||
NULL /* end of list */
|
||||
};
|
||||
|
||||
#define LAST_IMPL_IDX 55
|
||||
|
||||
static void handle_impl_reg( x86_op_t *op, uint32_t val ) {
|
||||
x86_reg_t *reg = &op->data.reg;
|
||||
op->type = op_register;
|
||||
ia32_handle_register( reg, (unsigned int) val );
|
||||
switch (reg->size) {
|
||||
case 1:
|
||||
op->datatype = op_byte; break;
|
||||
case 2:
|
||||
op->datatype = op_word; break;
|
||||
case 4:
|
||||
op->datatype = op_dword; break;
|
||||
case 8:
|
||||
op->datatype = op_qword; break;
|
||||
case 10:
|
||||
op->datatype = op_extreal; break;
|
||||
case 16:
|
||||
op->datatype = op_dqword; break;
|
||||
}
|
||||
return;
|
||||
x86_reg_t *reg = &op->data.reg;
|
||||
op->type = op_register;
|
||||
ia32_handle_register( reg, (unsigned int) val );
|
||||
switch (reg->size) {
|
||||
case 1:
|
||||
op->datatype = op_byte; break;
|
||||
case 2:
|
||||
op->datatype = op_word; break;
|
||||
case 4:
|
||||
op->datatype = op_dword; break;
|
||||
case 8:
|
||||
op->datatype = op_qword; break;
|
||||
case 10:
|
||||
op->datatype = op_extreal; break;
|
||||
case 16:
|
||||
op->datatype = op_dqword; break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* 'impl_idx' is the value from the opcode table: between 1 and LAST_IMPL_IDX */
|
||||
/* returns number of operands added */
|
||||
unsigned int Ia32_Decoder::ia32_insn_implicit_ops( unsigned int impl_idx ) {
|
||||
op_implicit_list_t *list;
|
||||
x86_oplist_t * existing=0;
|
||||
x86_op_t *op;
|
||||
unsigned int num = 0;
|
||||
op_implicit_list_t *list;
|
||||
x86_oplist_t * existing=0;
|
||||
x86_op_t *op;
|
||||
unsigned int num = 0;
|
||||
|
||||
if (! impl_idx || impl_idx > LAST_IMPL_IDX ) {
|
||||
return 0;
|
||||
}
|
||||
if (! impl_idx || impl_idx > LAST_IMPL_IDX ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( list = op_implicit_list[impl_idx]; list->type; list++, num++ ) {
|
||||
enum x86_op_access access = (enum x86_op_access) OP_PERM(list->type);
|
||||
x86_op_flags flags;
|
||||
for ( list = op_implicit_list[impl_idx]; list->type; list++, num++ ) {
|
||||
enum x86_op_access access = (enum x86_op_access) OP_PERM(list->type);
|
||||
x86_op_flags flags;
|
||||
flags.whole = (OP_FLAGS(list->type) >> 12);
|
||||
|
||||
op = NULL;
|
||||
/* In some cases (MUL), EAX is an implicit operand hardcoded in
|
||||
op = NULL;
|
||||
/* In some cases (MUL), EAX is an implicit operand hardcoded in
|
||||
* the instruction without being explicitly listed in assembly.
|
||||
* For this situation, find the hardcoded operand and add the
|
||||
* implied flag rather than adding a new implicit operand. */
|
||||
existing=0;
|
||||
if (ia32_true_register_id(list->operand) == REG_DWORD_OFFSET) {
|
||||
for ( existing = m_decoded->operands; existing; existing = existing->next ) {
|
||||
if (existing->op.type == op_register &&
|
||||
existing->op.data.reg.id == list->operand) {
|
||||
op = &existing->op;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!op) {
|
||||
op = m_decoded->x86_operand_new();
|
||||
/* all implicit operands are registers */
|
||||
handle_impl_reg( op, list->operand );
|
||||
/* decrement the 'explicit count' incremented by default in
|
||||
* x86_operand_new */
|
||||
m_decoded->explicit_count = m_decoded->explicit_count -1;
|
||||
}
|
||||
if (!op) {
|
||||
return num; /* gah! return early */
|
||||
}
|
||||
op->access = x86_op_access((int)op->access | (int)access);
|
||||
op->flags.whole |= flags.whole;
|
||||
op->flags.op_implied=true;
|
||||
}
|
||||
|
||||
return num;
|
||||
existing=0;
|
||||
if (ia32_true_register_id(list->operand) == REG_DWORD_OFFSET) {
|
||||
for ( existing = m_decoded->operands; existing; existing = existing->next ) {
|
||||
if (existing->op.type == op_register &&
|
||||
existing->op.data.reg.id == list->operand) {
|
||||
op = &existing->op;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!op) {
|
||||
op = m_decoded->x86_operand_new();
|
||||
/* all implicit operands are registers */
|
||||
handle_impl_reg( op, list->operand );
|
||||
/* decrement the 'explicit count' incremented by default in
|
||||
* x86_operand_new */
|
||||
m_decoded->explicit_count = m_decoded->explicit_count -1;
|
||||
}
|
||||
if (!op) {
|
||||
return num; /* gah! return early */
|
||||
}
|
||||
op->access = x86_op_access((int)op->access | (int)access);
|
||||
op->flags.whole |= flags.whole;
|
||||
op->flags.op_implied=true;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
6
3rd_party/libdisasm/ia32_insn.cpp
vendored
6
3rd_party/libdisasm/ia32_insn.cpp
vendored
@@ -240,7 +240,7 @@ void Ia32_Decoder::ia32_handle_prefix( unsigned int prefixes ) {
|
||||
}
|
||||
|
||||
|
||||
static void reg_32_to_16( x86_op_t *op, x86_insn_t *insn, void *arg ) {
|
||||
static void reg_32_to_16( x86_op_t *op, x86_insn_t */*insn*/, void */*arg*/ ) {
|
||||
|
||||
/* if this is a 32-bit register and it is a general register ... */
|
||||
if ( op->type == op_register && op->data.reg.size == 4 &&
|
||||
@@ -539,12 +539,12 @@ size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
|
||||
|
||||
size_t Ia32_Decoder::handle_insn_suffix( unsigned char *buf, size_t buf_len,
|
||||
ia32_insn_t *raw_insn ) {
|
||||
ia32_table_desc_t *table_desc;
|
||||
// ia32_table_desc_t *table_desc;
|
||||
ia32_insn_t *sfx_insn;
|
||||
size_t size;
|
||||
unsigned int prefixes = 0;
|
||||
|
||||
table_desc = &ia32_tables[raw_insn->table];
|
||||
// table_desc = &ia32_tables[raw_insn->table];
|
||||
size = ia32_table_lookup( buf, buf_len, raw_insn->table, &sfx_insn,
|
||||
&prefixes );
|
||||
if (size == INVALID_INSN || sfx_insn->mnem_flag == INS_INVALID ) {
|
||||
|
||||
421
3rd_party/libdisasm/ia32_invariant.cpp
vendored
421
3rd_party/libdisasm/ia32_invariant.cpp
vendored
@@ -9,8 +9,8 @@ extern ia32_table_desc_t *ia32_tables;
|
||||
extern ia32_settings_t ia32_settings;
|
||||
|
||||
extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
|
||||
unsigned int table, ia32_insn_t **raw_insn,
|
||||
unsigned int *prefixes );
|
||||
unsigned int table, ia32_insn_t **raw_insn,
|
||||
unsigned int *prefixes );
|
||||
|
||||
|
||||
/* -------------------------------- ModR/M, SIB */
|
||||
@@ -47,10 +47,10 @@ extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
|
||||
#define SIB_SCALE_NOBASE 0x00
|
||||
|
||||
/* Convenience struct for modR/M bitfield */
|
||||
struct modRM_byte {
|
||||
struct modRM_byte {
|
||||
unsigned int mod : 2;
|
||||
unsigned int reg : 3;
|
||||
unsigned int rm : 3;
|
||||
unsigned int rm : 3;
|
||||
};
|
||||
|
||||
/* Convenience struct for SIB bitfield */
|
||||
@@ -65,248 +65,249 @@ static void byte_decode(unsigned char b, struct modRM_byte *modrm) {
|
||||
#else
|
||||
static inline void byte_decode(unsigned char b, struct modRM_byte *modrm) {
|
||||
#endif
|
||||
/* generic bitfield-packing routine */
|
||||
/* generic bitfield-packing routine */
|
||||
|
||||
modrm->mod = b >> 6; /* top 2 bits */
|
||||
modrm->reg = (b & 56) >> 3; /* middle 3 bits */
|
||||
modrm->rm = b & 7; /* bottom 3 bits */
|
||||
modrm->mod = b >> 6; /* top 2 bits */
|
||||
modrm->reg = (b & 56) >> 3; /* middle 3 bits */
|
||||
modrm->rm = b & 7; /* bottom 3 bits */
|
||||
}
|
||||
static int ia32_invariant_modrm( unsigned char *in, unsigned char *out,
|
||||
unsigned int mode_16, x86_invariant_op_t *op) {
|
||||
struct modRM_byte modrm;
|
||||
struct SIB_byte sib;
|
||||
unsigned char *c, *cin;
|
||||
unsigned short *s;
|
||||
unsigned int *i;
|
||||
int size = 0; /* modrm byte is already counted */
|
||||
unsigned int mode_16, x86_invariant_op_t *op) {
|
||||
struct modRM_byte modrm;
|
||||
struct SIB_byte sib;
|
||||
unsigned char *c, *cin;
|
||||
unsigned short *s;
|
||||
unsigned int *i;
|
||||
int size = 0; /* modrm byte is already counted */
|
||||
|
||||
|
||||
byte_decode(*in, &modrm); /* get bitfields */
|
||||
byte_decode(*in, &modrm); /* get bitfields */
|
||||
|
||||
out[0] = in[0]; /* save modrm byte */
|
||||
cin = &in[1];
|
||||
c = &out[1];
|
||||
s = (unsigned short *)&out[1];
|
||||
i = (unsigned int *)&out[1];
|
||||
out[0] = in[0]; /* save modrm byte */
|
||||
cin = &in[1];
|
||||
c = &out[1];
|
||||
s = (unsigned short *)&out[1];
|
||||
i = (unsigned int *)&out[1];
|
||||
|
||||
op->type = op_expression;
|
||||
op->flags.op_pointer = true; //|= op_pointer;
|
||||
if ( ! mode_16 && modrm.rm == MODRM_RM_SIB &&
|
||||
modrm.mod != MODRM_MOD_NOEA ) {
|
||||
size ++;
|
||||
byte_decode(*cin, (struct modRM_byte *)(void*)&sib);
|
||||
op->type = op_expression;
|
||||
op->flags.op_pointer = true; //|= op_pointer;
|
||||
if ( ! mode_16 && modrm.rm == MODRM_RM_SIB &&
|
||||
modrm.mod != MODRM_MOD_NOEA ) {
|
||||
size ++;
|
||||
byte_decode(*cin, (struct modRM_byte *)(void*)&sib);
|
||||
|
||||
out[1] = in[1]; /* save sib byte */
|
||||
cin = &in[2];
|
||||
c = &out[2];
|
||||
s = (unsigned short *)&out[2];
|
||||
i = (unsigned int *)&out[2];
|
||||
out[1] = in[1]; /* save sib byte */
|
||||
cin = &in[2];
|
||||
c = &out[2];
|
||||
s = (unsigned short *)&out[2];
|
||||
i = (unsigned int *)&out[2];
|
||||
|
||||
if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) {
|
||||
/* disp 32 is variant! */
|
||||
memset( i, X86_WILDCARD_BYTE, 4 );
|
||||
size += 4;
|
||||
}
|
||||
}
|
||||
if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) {
|
||||
/* disp 32 is variant! */
|
||||
memset( i, X86_WILDCARD_BYTE, 4 );
|
||||
size += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (! modrm.mod && modrm.rm == 101) {
|
||||
if ( mode_16 ) { /* straight RVA in disp */
|
||||
memset( s, X86_WILDCARD_BYTE, 2 );
|
||||
size += 2;
|
||||
} else {
|
||||
memset( i, X86_WILDCARD_BYTE, 2 );
|
||||
size += 4;
|
||||
}
|
||||
} else if (modrm.mod && modrm.mod < 3) {
|
||||
if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */
|
||||
*c = *cin;
|
||||
size += 1;
|
||||
} else if ( mode_16 ) {
|
||||
*s = (* ((unsigned short *) cin));
|
||||
size += 2;
|
||||
} else {
|
||||
*i = (*((unsigned int *) cin));
|
||||
size += 4;
|
||||
}
|
||||
} else if ( modrm.mod == 3 ) {
|
||||
op->type = op_register;
|
||||
op->flags.op_pointer = false;// &= ~op_pointer;
|
||||
}
|
||||
if (! modrm.mod && modrm.rm == 101) {
|
||||
if ( mode_16 ) { /* straight RVA in disp */
|
||||
memset( s, X86_WILDCARD_BYTE, 2 );
|
||||
size += 2;
|
||||
} else {
|
||||
memset( i, X86_WILDCARD_BYTE, 2 );
|
||||
size += 4;
|
||||
}
|
||||
} else if (modrm.mod && modrm.mod < 3) {
|
||||
if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */
|
||||
*c = *cin;
|
||||
size += 1;
|
||||
} else if ( mode_16 ) {
|
||||
*s = (* ((unsigned short *) cin));
|
||||
size += 2;
|
||||
} else {
|
||||
*i = (*((unsigned int *) cin));
|
||||
size += 4;
|
||||
}
|
||||
} else if ( modrm.mod == 3 ) {
|
||||
op->type = op_register;
|
||||
op->flags.op_pointer = false;// &= ~op_pointer;
|
||||
}
|
||||
|
||||
return (size);
|
||||
return (size);
|
||||
}
|
||||
|
||||
|
||||
static int ia32_decode_invariant( unsigned char *buf, size_t buf_len,
|
||||
ia32_insn_t *t, unsigned char *out,
|
||||
unsigned int prefixes, x86_invariant_t *inv) {
|
||||
static int ia32_decode_invariant( unsigned char *buf, size_t /*buf_len*/,
|
||||
ia32_insn_t *t, unsigned char *out,
|
||||
unsigned int prefixes, x86_invariant_t *inv) {
|
||||
|
||||
unsigned int addr_size, op_size, mode_16;
|
||||
unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag };
|
||||
int x, type, bytes = 0, size = 0, modrm = 0;
|
||||
unsigned int addr_size, op_size, mode_16;
|
||||
unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag };
|
||||
int x, type, bytes = 0, size = 0, modrm = 0;
|
||||
|
||||
/* set addressing mode */
|
||||
if (ia32_settings.options & opt_16_bit) {
|
||||
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2;
|
||||
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2;
|
||||
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1;
|
||||
} else {
|
||||
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4;
|
||||
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4;
|
||||
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0;
|
||||
}
|
||||
/* set addressing mode */
|
||||
if (ia32_settings.options & opt_16_bit) {
|
||||
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2;
|
||||
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2;
|
||||
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1;
|
||||
} else {
|
||||
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4;
|
||||
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4;
|
||||
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0;
|
||||
}
|
||||
|
||||
for (x = 0; x < 3; x++) {
|
||||
inv->operands[x].access = (enum x86_op_access) OP_PERM(op_flags[x]);
|
||||
inv->operands[x].flags.whole = (OP_FLAGS(op_flags[x]) >> 12);
|
||||
for (x = 0; x < 3; x++) {
|
||||
inv->operands[x].access = (enum x86_op_access) OP_PERM(op_flags[x]);
|
||||
inv->operands[x].flags.whole = (OP_FLAGS(op_flags[x]) >> 12);
|
||||
//(enum x86_op_flags) (OP_FLAGS(op_flags[x]) >> 12);
|
||||
|
||||
switch (op_flags[x] & OPTYPE_MASK) {
|
||||
case OPTYPE_c:
|
||||
size = (op_size == 4) ? 2 : 1;
|
||||
break;
|
||||
case OPTYPE_a: case OPTYPE_v:
|
||||
size = (op_size == 4) ? 4 : 2;
|
||||
break;
|
||||
case OPTYPE_p:
|
||||
size = (op_size == 4) ? 6 : 4;
|
||||
break;
|
||||
case OPTYPE_b:
|
||||
size = 1;
|
||||
break;
|
||||
case OPTYPE_w:
|
||||
size = 2;
|
||||
break;
|
||||
case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd:
|
||||
case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv:
|
||||
case OPTYPE_si: case OPTYPE_fx:
|
||||
size = 4;
|
||||
break;
|
||||
case OPTYPE_s:
|
||||
size = 6;
|
||||
break;
|
||||
case OPTYPE_q: case OPTYPE_pi:
|
||||
size = 8;
|
||||
break;
|
||||
case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss:
|
||||
case OPTYPE_pd: case OPTYPE_sd:
|
||||
size = 16;
|
||||
break;
|
||||
case OPTYPE_m:
|
||||
size = (addr_size == 4) ? 4 : 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (op_flags[x] & OPTYPE_MASK) {
|
||||
case OPTYPE_c:
|
||||
size = (op_size == 4) ? 2 : 1;
|
||||
break;
|
||||
case OPTYPE_a: case OPTYPE_v:
|
||||
size = (op_size == 4) ? 4 : 2;
|
||||
break;
|
||||
case OPTYPE_p:
|
||||
size = (op_size == 4) ? 6 : 4;
|
||||
break;
|
||||
case OPTYPE_b:
|
||||
size = 1;
|
||||
break;
|
||||
case OPTYPE_w:
|
||||
size = 2;
|
||||
break;
|
||||
case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd:
|
||||
case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv:
|
||||
case OPTYPE_si: case OPTYPE_fx:
|
||||
size = 4;
|
||||
break;
|
||||
case OPTYPE_s:
|
||||
size = 6;
|
||||
break;
|
||||
case OPTYPE_q: case OPTYPE_pi:
|
||||
size = 8;
|
||||
break;
|
||||
case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss:
|
||||
case OPTYPE_pd: case OPTYPE_sd:
|
||||
size = 16;
|
||||
break;
|
||||
case OPTYPE_m:
|
||||
size = (addr_size == 4) ? 4 : 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
type = op_flags[x] & ADDRMETH_MASK;
|
||||
switch (type) {
|
||||
case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q:
|
||||
case ADDRMETH_R: case ADDRMETH_W:
|
||||
modrm = 1;
|
||||
bytes += ia32_invariant_modrm( buf, out,
|
||||
mode_16, &inv->operands[x]);
|
||||
break;
|
||||
case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G:
|
||||
case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T:
|
||||
case ADDRMETH_V:
|
||||
inv->operands[x].type = op_register;
|
||||
modrm = 1;
|
||||
break;
|
||||
case ADDRMETH_A: case ADDRMETH_O:
|
||||
/* pad with xF4's */
|
||||
memset( &out[bytes + modrm], X86_WILDCARD_BYTE,
|
||||
size );
|
||||
bytes += size;
|
||||
inv->operands[x].type = op_offset;
|
||||
if ( type == ADDRMETH_O ) {
|
||||
inv->operands[x].flags.op_signed = true;
|
||||
type = op_flags[x] & ADDRMETH_MASK;
|
||||
switch (type) {
|
||||
case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q:
|
||||
case ADDRMETH_R: case ADDRMETH_W:
|
||||
modrm = 1;
|
||||
bytes += ia32_invariant_modrm( buf, out,
|
||||
mode_16, &inv->operands[x]);
|
||||
break;
|
||||
case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G:
|
||||
case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T:
|
||||
case ADDRMETH_V:
|
||||
inv->operands[x].type = op_register;
|
||||
modrm = 1;
|
||||
break;
|
||||
case ADDRMETH_A: case ADDRMETH_O:
|
||||
/* pad with xF4's */
|
||||
memset( &out[bytes + modrm], X86_WILDCARD_BYTE,
|
||||
size );
|
||||
bytes += size;
|
||||
inv->operands[x].type = op_offset;
|
||||
if ( type == ADDRMETH_O ) {
|
||||
inv->operands[x].flags.op_signed = true;
|
||||
inv->operands[x].flags.op_pointer = true;
|
||||
}
|
||||
break;
|
||||
case ADDRMETH_I: case ADDRMETH_J:
|
||||
/* grab imm value */
|
||||
if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) {
|
||||
/* assume this is an address */
|
||||
memset( &out[bytes + modrm], X86_WILDCARD_BYTE, size );
|
||||
} else {
|
||||
memcpy( &out[bytes + modrm], &buf[bytes + modrm], size );
|
||||
}
|
||||
|
||||
bytes += size;
|
||||
if ( type == ADDRMETH_J ) {
|
||||
if ( size == 1 ) {
|
||||
inv->operands[x].type = op_relative_near;
|
||||
} else {
|
||||
inv->operands[x].type = op_relative_far;
|
||||
}
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
} else {
|
||||
inv->operands[x].type = op_immediate;
|
||||
}
|
||||
break;
|
||||
case ADDRMETH_F:
|
||||
inv->operands[x].type = op_register;
|
||||
break;
|
||||
case ADDRMETH_X:
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
inv->operands[x].flags.op_pointer=true;
|
||||
inv->operands[x].flags.op_seg=x86_op_flags::op_ds_seg;
|
||||
}
|
||||
break;
|
||||
case ADDRMETH_I: case ADDRMETH_J:
|
||||
/* grab imm value */
|
||||
if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) {
|
||||
/* assume this is an address */
|
||||
memset( &out[bytes + modrm], X86_WILDCARD_BYTE, size );
|
||||
} else {
|
||||
memcpy( &out[bytes + modrm], &buf[bytes + modrm], size );
|
||||
}
|
||||
|
||||
bytes += size;
|
||||
if ( type == ADDRMETH_J ) {
|
||||
if ( size == 1 ) {
|
||||
inv->operands[x].type = op_relative_near;
|
||||
} else {
|
||||
inv->operands[x].type = op_relative_far;
|
||||
}
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
} else {
|
||||
inv->operands[x].type = op_immediate;
|
||||
}
|
||||
break;
|
||||
case ADDRMETH_F:
|
||||
inv->operands[x].type = op_register;
|
||||
break;
|
||||
case ADDRMETH_X:
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
inv->operands[x].flags.op_pointer=true;
|
||||
inv->operands[x].flags.op_seg=(x86_op_flags::op_ds_seg)>>8;
|
||||
inv->operands[x].flags.op_string=true;
|
||||
break;
|
||||
case ADDRMETH_Y:
|
||||
break;
|
||||
case ADDRMETH_Y:
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
inv->operands[x].flags.op_pointer=true;
|
||||
inv->operands[x].flags.op_seg=x86_op_flags::op_es_seg;
|
||||
inv->operands[x].flags.op_seg=x86_op_flags::op_es_seg>>8;
|
||||
inv->operands[x].flags.op_string=true;
|
||||
break;
|
||||
case ADDRMETH_RR:
|
||||
inv->operands[x].type = op_register;
|
||||
break;
|
||||
case ADDRMETH_II:
|
||||
inv->operands[x].type = op_immediate;
|
||||
break;
|
||||
default:
|
||||
inv->operands[x].type = op_unused;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ADDRMETH_RR:
|
||||
inv->operands[x].type = op_register;
|
||||
break;
|
||||
case ADDRMETH_II:
|
||||
inv->operands[x].type = op_immediate;
|
||||
break;
|
||||
default:
|
||||
inv->operands[x].type = op_unused;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (bytes + modrm);
|
||||
return (bytes + modrm);
|
||||
}
|
||||
|
||||
size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len,
|
||||
x86_invariant_t *inv ) {
|
||||
ia32_insn_t *raw_insn = NULL;
|
||||
unsigned int prefixes=0;
|
||||
unsigned int type;
|
||||
size_t size;
|
||||
|
||||
/* Perform recursive table lookup starting with main table (0) */
|
||||
size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes );
|
||||
if ( size == INVALID_INSN || size > buf_len ) {
|
||||
/* TODO: set errno */
|
||||
return 0;
|
||||
}
|
||||
size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len,
|
||||
x86_invariant_t *inv ) {
|
||||
ia32_insn_t *raw_insn = NULL;
|
||||
unsigned int prefixes=0;
|
||||
unsigned int type;
|
||||
size_t size;
|
||||
|
||||
/* copy opcode bytes to buffer */
|
||||
memcpy( inv->bytes, buf, size );
|
||||
/* Perform recursive table lookup starting with main table (0) */
|
||||
size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes );
|
||||
if ( size == INVALID_INSN || size > buf_len ) {
|
||||
/* TODO: set errno */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set mnemonic type and group */
|
||||
type = raw_insn->mnem_flag & ~INS_FLAG_MASK;
|
||||
/* copy opcode bytes to buffer */
|
||||
memcpy( inv->bytes, buf, size );
|
||||
|
||||
/* set mnemonic type and group */
|
||||
type = raw_insn->mnem_flag & ~INS_FLAG_MASK;
|
||||
inv->group = (x86_insn_t::x86_insn_group) ((INS_GROUP(type)) >> 12);
|
||||
inv->type = (enum x86_insn_type) INS_TYPE(type);
|
||||
|
||||
/* handle operands */
|
||||
size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn,
|
||||
&buf[size - 1], prefixes, inv );
|
||||
/* handle operands */
|
||||
size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn,
|
||||
&buf[size - 1], prefixes, inv );
|
||||
|
||||
inv->size = size;
|
||||
inv->size = size;
|
||||
|
||||
return size; /* return size of instruction in bytes */
|
||||
return size; /* return size of instruction in bytes */
|
||||
}
|
||||
|
||||
size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) {
|
||||
x86_invariant_t inv = { {0} };
|
||||
return( ia32_disasm_invariant( buf, buf_len, &inv ) );
|
||||
x86_invariant_t inv;
|
||||
memset(&inv,0,sizeof(x86_invariant_t));
|
||||
return( ia32_disasm_invariant( buf, buf_len, &inv ) );
|
||||
}
|
||||
|
||||
6
3rd_party/libdisasm/ia32_modrm.cpp
vendored
6
3rd_party/libdisasm/ia32_modrm.cpp
vendored
@@ -155,12 +155,12 @@ static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
|
||||
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 3);
|
||||
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
|
||||
case MOD16_RM_BPSI:
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
|
||||
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
|
||||
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 6);
|
||||
break;
|
||||
case MOD16_RM_BPDI:
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
|
||||
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
|
||||
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
|
||||
break;
|
||||
@@ -172,7 +172,7 @@ static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
|
||||
break;
|
||||
case MOD16_RM_BP:
|
||||
if ( modrm->mod != MOD16_MOD_NODISP ) {
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
|
||||
ia32_handle_register(&ea->base,
|
||||
REG_WORD_OFFSET + 5);
|
||||
}
|
||||
|
||||
5144
3rd_party/libdisasm/ia32_opcode_tables.cpp
vendored
5144
3rd_party/libdisasm/ia32_opcode_tables.cpp
vendored
File diff suppressed because it is too large
Load Diff
16
3rd_party/libdisasm/ia32_operand.cpp
vendored
16
3rd_party/libdisasm/ia32_operand.cpp
vendored
@@ -20,17 +20,17 @@ static void apply_seg( x86_op_t *op, unsigned int prefixes ) {
|
||||
switch ( prefixes & PREFIX_REG_MASK ) {
|
||||
/* NOTE: that op->flags for segment override are not a bitfield */
|
||||
case PREFIX_CS:
|
||||
op->flags.op_seg = x86_op_flags::op_cs_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_cs_seg>>8; break;
|
||||
case PREFIX_SS:
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8; break;
|
||||
case PREFIX_DS:
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg>>8; break;
|
||||
case PREFIX_ES:
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg>>8; break;
|
||||
case PREFIX_FS:
|
||||
op->flags.op_seg = x86_op_flags::op_fs_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_fs_seg>>8; break;
|
||||
case PREFIX_GS:
|
||||
op->flags.op_seg = x86_op_flags::op_gs_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_gs_seg>>8; break;
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -172,7 +172,7 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
|
||||
case ADDRMETH_X: /* Memory addressed by DS:SI [string] */
|
||||
op->type = op_expression;
|
||||
op->flags.op_hardcode = true;
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg>>8;
|
||||
op->flags.op_pointer = true;
|
||||
op->flags.op_string = true;
|
||||
ia32_handle_register( &op->data.expression.base,
|
||||
@@ -181,7 +181,7 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
|
||||
case ADDRMETH_Y: /* Memory addressed by ES:DI [string] */
|
||||
op->type = op_expression;
|
||||
op->flags.op_hardcode = true;
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg>>8;
|
||||
op->flags.op_pointer = true;
|
||||
op->flags.op_string = true;
|
||||
ia32_handle_register( &op->data.expression.base,
|
||||
|
||||
212
3rd_party/libdisasm/ia32_reg.cpp
vendored
212
3rd_party/libdisasm/ia32_reg.cpp
vendored
@@ -71,126 +71,126 @@ static struct {
|
||||
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_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_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_undef,0,{0} }
|
||||
};
|
||||
|
||||
|
||||
static size_t sz_regtable = NUM_X86_REGS + 1;
|
||||
|
||||
144
3rd_party/libdisasm/libdis.h
vendored
144
3rd_party/libdisasm/libdis.h
vendored
@@ -89,7 +89,7 @@ enum x86_options { /* these can be ORed together */
|
||||
opt_none= 0,
|
||||
opt_ignore_nulls=1, /* ignore sequences of > 4 NULL bytes */
|
||||
opt_16_bit=2, /* 16-bit/DOS disassembly */
|
||||
opt_att_mnemonics=4, /* use AT&T syntax names for alternate opcode mnemonics */
|
||||
opt_att_mnemonics=4 /* use AT&T syntax names for alternate opcode mnemonics */
|
||||
};
|
||||
|
||||
/* ========================================= Instruction Representation */
|
||||
@@ -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 */
|
||||
@@ -250,39 +250,43 @@ 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;
|
||||
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 */
|
||||
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 */
|
||||
size_t size()
|
||||
{
|
||||
return operand_size();
|
||||
@@ -301,6 +305,7 @@ struct x86_op_t{
|
||||
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) );
|
||||
}
|
||||
@@ -439,7 +444,7 @@ enum x86_insn_note {
|
||||
insn_note_smm = 2, /* "" in System Management Mode */
|
||||
insn_note_serial = 4, /* Serializing instruction */
|
||||
insn_note_nonswap = 8, /* Does not swap arguments in att-style formatting */
|
||||
insn_note_nosuffix = 16, /* Does not have size suffix in att-style formatting */
|
||||
insn_note_nosuffix = 16 /* Does not have size suffix in att-style formatting */
|
||||
};
|
||||
|
||||
/* This specifies what effects the instruction has on the %eflags register */
|
||||
@@ -520,7 +525,6 @@ 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
|
||||
@@ -572,8 +576,8 @@ 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 */
|
||||
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 */
|
||||
@@ -604,29 +608,36 @@ 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();
|
||||
size_t x86_operand_count( enum x86_op_foreach_type type );
|
||||
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 );
|
||||
/* accessor functions for the operands */
|
||||
x86_op_t * x86_operand_1st( );
|
||||
x86_op_t * x86_operand_2nd( );
|
||||
x86_op_t * x86_operand_3rd( );
|
||||
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( );
|
||||
int32_t x86_get_rel_offset( );
|
||||
x86_op_t * x86_get_branch_target( );
|
||||
x86_op_t * x86_get_imm( );
|
||||
/* More accessor fuctions, this time for user-defined info... */
|
||||
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( );
|
||||
uint8_t * x86_get_raw_imm( );
|
||||
/* 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);
|
||||
int x86_format_insn( char *buf, int len, enum x86_asm_format);
|
||||
void x86_oplist_free( );
|
||||
/* returns 0 if an instruction is invalid, 1 if valid */
|
||||
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();
|
||||
@@ -803,9 +814,10 @@ public:
|
||||
* void x86_get_aliased_reg( x86_reg_t *alias_reg, x86_reg_t *output_reg )
|
||||
* where 'alias_reg' is a reg operand and 'output_reg' is filled with the
|
||||
* register that the operand is an alias for */
|
||||
//#define x86_get_aliased_reg( alias_reg, output_reg ) \
|
||||
// x86_reg_from_id( alias_reg->alias, output_reg )
|
||||
|
||||
/*
|
||||
#define x86_get_aliased_reg( alias_reg, output_reg ) \
|
||||
x86_reg_from_id( alias_reg->alias, output_reg )
|
||||
*/
|
||||
|
||||
/* ================================== Invariant Instruction Representation */
|
||||
/* Invariant instructions are used for generating binary signatures;
|
||||
|
||||
36
3rd_party/libdisasm/x86_disasm.cpp
vendored
36
3rd_party/libdisasm/x86_disasm.cpp
vendored
@@ -52,7 +52,7 @@ unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
|
||||
/* copy enough bytes for disassembly into buffer : this
|
||||
* helps prevent buffer overruns at the end of a file */
|
||||
memset( bytes, 0, MAX_INSTRUCTION_SIZE );
|
||||
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
|
||||
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
|
||||
MAX_INSTRUCTION_SIZE );
|
||||
|
||||
/* actually do the disassembly */
|
||||
@@ -104,7 +104,7 @@ unsigned int X86_Disasm::x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
|
||||
bytes++; /* try next byte */
|
||||
}
|
||||
|
||||
insn.x86_oplist_free();
|
||||
insn.x86_oplist_free();
|
||||
}
|
||||
|
||||
return( count );
|
||||
@@ -127,9 +127,9 @@ static int32_t internal_resolver( x86_op_t *op, x86_insn_t *insn ){
|
||||
if ( x86_optype_is_address(op->type) ) {
|
||||
next_addr = op->data.sdword;
|
||||
} else if ( op->type == op_relative_near ) {
|
||||
next_addr = insn->addr + insn->size + op->data.relative_near;
|
||||
next_addr = insn->addr + insn->size + op->data.relative_near;
|
||||
} else if ( op->type == op_relative_far ) {
|
||||
next_addr = insn->addr + insn->size + op->data.relative_far;
|
||||
next_addr = insn->addr + insn->size + op->data.relative_far;
|
||||
}
|
||||
return( next_addr );
|
||||
}
|
||||
@@ -141,7 +141,7 @@ unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int bu
|
||||
x86_insn_t insn;
|
||||
x86_op_t *op;
|
||||
int32_t next_addr;
|
||||
uint32_t next_offset;
|
||||
int32_t next_offset;
|
||||
unsigned int size, count = 0, bytes = 0, cont = 1;
|
||||
|
||||
while ( cont && bytes < buf_len ) {
|
||||
@@ -175,8 +175,8 @@ unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int bu
|
||||
if (next_addr != -1 ) {
|
||||
next_offset = next_addr - buf_rva;
|
||||
/* if offset is in this buffer... */
|
||||
if ( next_offset >= 0 &&
|
||||
next_offset < buf_len ) {
|
||||
if ( next_offset >= 0 && next_offset < int(buf_len) )
|
||||
{
|
||||
/* go ahead and disassemble */
|
||||
count += x86_disasm_forward( buf,
|
||||
buf_len,
|
||||
@@ -197,24 +197,24 @@ unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int bu
|
||||
cont = 0;
|
||||
}
|
||||
|
||||
insn.x86_oplist_free( );
|
||||
insn.x86_oplist_free( );
|
||||
}
|
||||
return( count );
|
||||
}
|
||||
|
||||
/* invariant instruction representation */
|
||||
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
|
||||
x86_invariant_t *inv ){
|
||||
if (! buf || ! buf_len || ! inv ) {
|
||||
return(0);
|
||||
}
|
||||
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
|
||||
x86_invariant_t *inv ){
|
||||
if (! buf || ! buf_len || ! inv ) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
return ia32_disasm_invariant(buf, buf_len, inv);
|
||||
return ia32_disasm_invariant(buf, buf_len, inv);
|
||||
}
|
||||
size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len ) {
|
||||
if (! buf || ! buf_len ) {
|
||||
return(0);
|
||||
}
|
||||
if (! buf || ! buf_len ) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
return ia32_disasm_size(buf, buf_len);
|
||||
return ia32_disasm_size(buf, buf_len);
|
||||
}
|
||||
|
||||
42
3rd_party/libdisasm/x86_format.cpp
vendored
42
3rd_party/libdisasm/x86_format.cpp
vendored
@@ -46,7 +46,7 @@
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
static char *prefix_strings[] = {
|
||||
static const char *prefix_strings[] = {
|
||||
"", /* no prefix */
|
||||
"repz ", /* the trailing spaces make it easy to prepend to mnemonic */
|
||||
"repnz ",
|
||||
@@ -115,7 +115,7 @@ static void get_operand_data_str( x86_op_t *op, char *str, int len ){
|
||||
static void get_operand_regtype_str( int regtype, char *str, int len )
|
||||
{
|
||||
static struct {
|
||||
char *name;
|
||||
const char *name;
|
||||
int value;
|
||||
} operand_regtypes[] = {
|
||||
{"reg_gen" , 0x00001},
|
||||
@@ -284,7 +284,7 @@ static int format_expr( x86_ea_t *ea, char *buf, int len,
|
||||
static int format_seg( x86_op_t *op, char *buf, int len,
|
||||
enum x86_asm_format format ) {
|
||||
int len_orig = len;
|
||||
char *reg = "";
|
||||
const char *reg = "";
|
||||
|
||||
if (! op || ! buf || ! len || ! op->flags.whole) {
|
||||
return(0);
|
||||
@@ -295,8 +295,9 @@ static int format_seg( x86_op_t *op, char *buf, int len,
|
||||
if (! (int) op->flags.op_seg) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
switch (op->flags.op_seg) {
|
||||
uint16_t seg_ov=uint16_t(op->flags.op_seg)<<8;
|
||||
switch (seg_ov)
|
||||
{
|
||||
case x86_op_flags::op_es_seg: reg = "es"; break;
|
||||
case x86_op_flags::op_cs_seg: reg = "cs"; break;
|
||||
case x86_op_flags::op_ss_seg: reg = "ss"; break;
|
||||
@@ -328,9 +329,9 @@ static int format_seg( x86_op_t *op, char *buf, int len,
|
||||
return( len_orig - len ); /* return length of appended string */
|
||||
}
|
||||
|
||||
static char *get_operand_datatype_str( x86_op_t *op ){
|
||||
static const char *get_operand_datatype_str( x86_op_t *op ){
|
||||
|
||||
static char *types[] = {
|
||||
static const char *types[] = {
|
||||
"sbyte", /* 0 */
|
||||
"sword",
|
||||
"sqword",
|
||||
@@ -405,7 +406,7 @@ static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
|
||||
int len) {
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
const char *name;
|
||||
int value;
|
||||
} insn_flags[] = {
|
||||
{ "carry_set ", 0x0001 },
|
||||
@@ -440,9 +441,9 @@ static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
|
||||
return( len_orig - len );
|
||||
}
|
||||
|
||||
static char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
|
||||
static const char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
|
||||
|
||||
static char *types[] = {
|
||||
static const char *types[] = {
|
||||
"", // 0
|
||||
"controlflow",// 1
|
||||
"arithmetic", // 2
|
||||
@@ -467,10 +468,10 @@ static char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
|
||||
return types[gp];
|
||||
}
|
||||
|
||||
static char *get_insn_type_str( enum x86_insn_type type ) {
|
||||
static const char *get_insn_type_str( enum x86_insn_type type ) {
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
const char *name;
|
||||
int value;
|
||||
} types[] = {
|
||||
/* insn_controlflow */
|
||||
@@ -592,8 +593,8 @@ static char *get_insn_type_str( enum x86_insn_type type ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
|
||||
static char *intel[] = {
|
||||
static const char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
|
||||
static const char *intel[] = {
|
||||
"", // 0
|
||||
"8086", // 1
|
||||
"80286", // 2
|
||||
@@ -620,8 +621,8 @@ static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static char *get_insn_isa_str( enum x86_insn_isa isa ) {
|
||||
static char *subset[] = {
|
||||
static const char *get_insn_isa_str( enum x86_insn_isa isa ) {
|
||||
static const char *subset[] = {
|
||||
NULL, // 0
|
||||
"General Purpose", // 1
|
||||
"Floating Point", // 2
|
||||
@@ -880,11 +881,11 @@ static int format_operand_xml( x86_op_t *op, x86_insn_t *insn, char *buf,
|
||||
return( strlen( buf ) );
|
||||
}
|
||||
|
||||
static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf,
|
||||
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);
|
||||
const char *datatype = get_operand_datatype_str(op);
|
||||
|
||||
switch (op->type) {
|
||||
case op_register:
|
||||
@@ -1042,7 +1043,7 @@ char * x86_op_t::format( enum x86_asm_format format ) {
|
||||
|
||||
static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
|
||||
int size = 0;
|
||||
char *suffix;
|
||||
const char *suffix;
|
||||
|
||||
if (! insn || ! buf || ! len )
|
||||
return(0);
|
||||
@@ -1094,7 +1095,6 @@ 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];
|
||||
@@ -1137,7 +1137,7 @@ static int format_insn_note(x86_insn_t *insn, char *buf, int len){
|
||||
return( len_orig - len );
|
||||
}
|
||||
|
||||
static int format_raw_insn( x86_insn_t *insn, char *buf, int len ){
|
||||
static int format_raw_insn( x86_insn_t *insn, char *buf, size_t len ){
|
||||
struct op_string opstr = { buf, len };
|
||||
int i;
|
||||
|
||||
|
||||
8
3rd_party/libdisasm/x86_insn.cpp
vendored
8
3rd_party/libdisasm/x86_insn.cpp
vendored
@@ -17,7 +17,6 @@ int x86_insn_is_valid( x86_insn_t *insn ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \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 )
|
||||
@@ -203,13 +202,12 @@ size_t x86_op_t::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;
|
||||
}
|
||||
|
||||
void x86_insn_t::x86_set_insn_offset( unsigned int offset ){
|
||||
offset = offset;
|
||||
void x86_insn_t::x86_set_insn_offset( unsigned int _offset ){
|
||||
offset = _offset;
|
||||
}
|
||||
|
||||
void x86_insn_t::x86_set_insn_function( void * func ){
|
||||
@@ -220,7 +218,6 @@ 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;
|
||||
}
|
||||
@@ -229,7 +226,6 @@ void x86_insn_t::x86_untag_insn(){
|
||||
tag = 0;
|
||||
}
|
||||
|
||||
/** \return insn->tag */
|
||||
int x86_insn_t::x86_insn_is_tagged(){
|
||||
return tag;
|
||||
}
|
||||
|
||||
249
3rd_party/libdisasm/x86_operand_list.cpp
vendored
249
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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,31 +56,31 @@ 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 */
|
||||
@@ -88,122 +88,121 @@ void x86_insn_t::x86_oplist_free( )
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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 ( (type & op_explicit) && ! (type & op_implicit) ) {
|
||||
implicit = 0;
|
||||
}
|
||||
if ( (type & op_implicit) && ! (type & op_explicit) ) {
|
||||
_explicit = 0;
|
||||
}
|
||||
|
||||
if (! _explicit && ! (list->op.flags.op_implied) ) {
|
||||
/* operand is not 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 );
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
static void count_operand( x86_op_t */*op*/, x86_insn_t */*insn*/, void *arg ) {
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user