More simplifications on BB creation
This commit is contained in:
parent
ba110a64cb
commit
5087a051b5
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0}}; /* monitor */
|
||||
static op_implicit_list_t list_mwait[] =
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,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;
|
||||
}
|
||||
|
||||
3
3rd_party/libdisasm/ia32_insn.cpp
vendored
3
3rd_party/libdisasm/ia32_insn.cpp
vendored
@ -543,8 +543,7 @@ size_t Ia32_Decoder::handle_insn_suffix( unsigned char *buf, size_t buf_len,
|
||||
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 ) {
|
||||
|
||||
416
3rd_party/libdisasm/ia32_invariant.cpp
vendored
416
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,249 +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) {
|
||||
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;
|
||||
}
|
||||
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>>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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* copy opcode bytes to buffer */
|
||||
memcpy( inv->bytes, buf, size );
|
||||
|
||||
/* copy opcode bytes to buffer */
|
||||
memcpy( inv->bytes, buf, size );
|
||||
|
||||
/* set mnemonic type and group */
|
||||
type = raw_insn->mnem_flag & ~INS_FLAG_MASK;
|
||||
/* 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;
|
||||
memset(&inv,0,sizeof(x86_invariant_t));
|
||||
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 ) );
|
||||
}
|
||||
|
||||
12
3rd_party/libdisasm/ia32_opcode_tables.cpp
vendored
12
3rd_party/libdisasm/ia32_opcode_tables.cpp
vendored
@ -480,7 +480,7 @@ static ia32_insn_t tbl_0F[] = { /* Two-byte Opcodes */
|
||||
{ 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "sysexit", "", 0, 0, 0, 0 , 51 },
|
||||
{ 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_MOV, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "pshufb", "", 0, 0, 0, 0, 0 },
|
||||
{ 0, INS_MOV, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "pshufb", "", 0, 0, 0, 0, 0 },
|
||||
{ 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
|
||||
@ -655,7 +655,7 @@ static ia32_insn_t tbl_0F[] = { /* Two-byte Opcodes */
|
||||
{ 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "pavgw", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_MUL, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "pmulhuw", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_MUL, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pmulhw", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_MOV, INS_NOTE_NOSUFFIX, ADDRMETH_W | OPTYPE_q | OP_W, ADDRMETH_V | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movntq", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubsb", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubsw", "", 0, 0, 0, 0 , 0 },
|
||||
@ -665,22 +665,22 @@ static ia32_insn_t tbl_0F[] = { /* Two-byte Opcodes */
|
||||
{ 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "paddsw", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_ARITH, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "pmaxsw", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_XOR, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pxor", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psllw", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pslld", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psllq", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_MUL, 0, ADDRMETH_P | OPTYPE_q | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pmuludq", "", 0, 0, 0, 0, 0 },
|
||||
{ 0, INS_MUL, 0, ADDRMETH_P | OPTYPE_q | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pmuludq", "", 0, 0, 0, 0, 0 },
|
||||
{ 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pmaddwd", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "psadbw", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_MOV, 0, ADDRMETH_P | OPTYPE_pi | OP_W, ADDRMETH_Q | OPTYPE_pi | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "maskmovq", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubb", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubw", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubd", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psubq", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psubq", "", 0, 0, 0, 0, 0 },
|
||||
{ 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "paddb", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "paddw", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "paddd", "", 0, 0, 0, 0 , 0 },
|
||||
{ 0, INS_INVALID,0, ARG_NONE , ARG_NONE , ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0}
|
||||
{ 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 }
|
||||
};
|
||||
|
||||
|
||||
|
||||
334
3rd_party/libdisasm/ia32_reg.cpp
vendored
334
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_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} }
|
||||
};
|
||||
/* 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,"" }
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
reg->id = id;
|
||||
|
||||
unsigned int alias;
|
||||
if (! id || id > sz_regtable ) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
reg->id = id;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
7
3rd_party/libdisasm/libdis.h
vendored
7
3rd_party/libdisasm/libdis.h
vendored
@ -814,10 +814,9 @@ 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;
|
||||
|
||||
225
3rd_party/libdisasm/x86_disasm.cpp
vendored
225
3rd_party/libdisasm/x86_disasm.cpp
vendored
@ -9,8 +9,8 @@
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#define inline __inline
|
||||
#define snprintf _snprintf
|
||||
#define inline __inline
|
||||
#endif
|
||||
void x86_insn_t::make_invalid(unsigned char *buf)
|
||||
{
|
||||
@ -22,8 +22,8 @@ void x86_insn_t::make_invalid(unsigned char *buf)
|
||||
memcpy( bytes, buf, 1 );
|
||||
}
|
||||
unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
|
||||
uint32_t buf_rva, unsigned int offset,
|
||||
x86_insn_t *insn ){
|
||||
uint32_t buf_rva, unsigned int offset,
|
||||
x86_insn_t *insn ){
|
||||
int len, size;
|
||||
unsigned char bytes[MAX_INSTRUCTION_SIZE];
|
||||
|
||||
@ -53,7 +53,7 @@ unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
|
||||
* 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 :
|
||||
MAX_INSTRUCTION_SIZE );
|
||||
MAX_INSTRUCTION_SIZE );
|
||||
|
||||
/* actually do the disassembly */
|
||||
/* TODO: allow switching when more disassemblers are added */
|
||||
@ -81,140 +81,139 @@ unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
|
||||
}
|
||||
|
||||
unsigned int X86_Disasm::x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
|
||||
unsigned int offset, unsigned int len,
|
||||
DISASM_CALLBACK func, void *arg ) {
|
||||
x86_insn_t insn;
|
||||
unsigned int buf_len, size, count = 0, bytes = 0;
|
||||
unsigned int offset, unsigned int len,
|
||||
DISASM_CALLBACK func, void *arg ) {
|
||||
x86_insn_t insn;
|
||||
unsigned int buf_len, size, count = 0, bytes = 0;
|
||||
|
||||
/* buf_len is implied by the arguments */
|
||||
buf_len = len + offset;
|
||||
/* buf_len is implied by the arguments */
|
||||
buf_len = len + offset;
|
||||
|
||||
while ( bytes < len ) {
|
||||
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
|
||||
&insn );
|
||||
if ( size ) {
|
||||
/* invoke callback if it exists */
|
||||
if ( func ) {
|
||||
(*func)( &insn, arg );
|
||||
}
|
||||
bytes += size;
|
||||
count ++;
|
||||
} else {
|
||||
/* error */
|
||||
bytes++; /* try next byte */
|
||||
}
|
||||
|
||||
insn.x86_oplist_free();
|
||||
while ( bytes < len ) {
|
||||
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
|
||||
&insn );
|
||||
if ( size ) {
|
||||
/* invoke callback if it exists */
|
||||
if ( func ) {
|
||||
(*func)( &insn, arg );
|
||||
}
|
||||
bytes += size;
|
||||
count ++;
|
||||
} else {
|
||||
/* error */
|
||||
bytes++; /* try next byte */
|
||||
}
|
||||
|
||||
return( count );
|
||||
insn.x86_oplist_free();
|
||||
}
|
||||
|
||||
return( count );
|
||||
}
|
||||
|
||||
static inline int follow_insn_dest( x86_insn_t *insn ) {
|
||||
if ( insn->type == insn_jmp || insn->type == insn_jcc ||
|
||||
insn->type == insn_call || insn->type == insn_callcc ) {
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
if ( insn->type == insn_jmp || insn->type == insn_jcc ||
|
||||
insn->type == insn_call || insn->type == insn_callcc ) {
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static inline int insn_doesnt_return( x86_insn_t *insn ) {
|
||||
return( (insn->type == insn_jmp || insn->type == insn_return) ? 1: 0 );
|
||||
return( (insn->type == insn_jmp || insn->type == insn_return) ? 1: 0 );
|
||||
}
|
||||
|
||||
static int32_t internal_resolver( x86_op_t *op, x86_insn_t *insn ){
|
||||
int32_t next_addr = -1;
|
||||
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;
|
||||
} else if ( op->type == op_relative_far ) {
|
||||
next_addr = insn->addr + insn->size + op->data.relative_far;
|
||||
}
|
||||
return( next_addr );
|
||||
int32_t next_addr = -1;
|
||||
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;
|
||||
} else if ( op->type == op_relative_far ) {
|
||||
next_addr = insn->addr + insn->size + op->data.relative_far;
|
||||
}
|
||||
return( next_addr );
|
||||
}
|
||||
|
||||
unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
|
||||
uint32_t buf_rva, unsigned int offset,
|
||||
DISASM_CALLBACK func, void *arg,
|
||||
DISASM_RESOLVER resolver, void *r_arg ){
|
||||
x86_insn_t insn;
|
||||
x86_op_t *op;
|
||||
int32_t next_addr;
|
||||
int32_t next_offset;
|
||||
unsigned int size, count = 0, bytes = 0, cont = 1;
|
||||
uint32_t buf_rva, unsigned int offset,
|
||||
DISASM_CALLBACK func, void *arg,
|
||||
DISASM_RESOLVER resolver, void *r_arg ){
|
||||
x86_insn_t insn;
|
||||
x86_op_t *op;
|
||||
int32_t next_addr;
|
||||
int32_t next_offset;
|
||||
unsigned int size, count = 0, bytes = 0, cont = 1;
|
||||
|
||||
while ( cont && bytes < buf_len ) {
|
||||
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
|
||||
while ( cont && bytes < buf_len ) {
|
||||
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
|
||||
&insn );
|
||||
|
||||
if ( size ) {
|
||||
/* invoke callback if it exists */
|
||||
if ( func ) {
|
||||
(*func)( &insn, arg );
|
||||
}
|
||||
bytes += size;
|
||||
count ++;
|
||||
} else {
|
||||
/* error */
|
||||
bytes++; /* try next byte */
|
||||
}
|
||||
|
||||
if ( follow_insn_dest(&insn) ) {
|
||||
op = insn.x86_operand_1st();//x86_get_dest_operand
|
||||
next_addr = -1;
|
||||
|
||||
/* if caller supplied a resolver, use it to determine
|
||||
* the address to disassemble */
|
||||
if ( resolver ) {
|
||||
next_addr = resolver(op, &insn, r_arg);
|
||||
} else {
|
||||
next_addr = internal_resolver(op, &insn);
|
||||
}
|
||||
|
||||
if (next_addr != -1 ) {
|
||||
next_offset = next_addr - buf_rva;
|
||||
/* if offset is in this buffer... */
|
||||
if ( next_offset >= 0 && next_offset < int(buf_len) )
|
||||
{
|
||||
/* go ahead and disassemble */
|
||||
count += x86_disasm_forward( buf,
|
||||
buf_len,
|
||||
buf_rva,
|
||||
next_offset,
|
||||
func, arg,
|
||||
resolver, r_arg );
|
||||
} else {
|
||||
/* report unresolved address */
|
||||
x86_report_error( report_disasm_bounds,
|
||||
(void*)(long)next_addr );
|
||||
}
|
||||
}
|
||||
} /* end follow_insn */
|
||||
|
||||
if ( insn_doesnt_return(&insn) ) {
|
||||
/* stop disassembling */
|
||||
cont = 0;
|
||||
}
|
||||
|
||||
insn.x86_oplist_free( );
|
||||
if ( size ) {
|
||||
/* invoke callback if it exists */
|
||||
if ( func ) {
|
||||
(*func)( &insn, arg );
|
||||
}
|
||||
bytes += size;
|
||||
count ++;
|
||||
} else {
|
||||
/* error */
|
||||
bytes++; /* try next byte */
|
||||
}
|
||||
return( count );
|
||||
|
||||
if ( follow_insn_dest(&insn) ) {
|
||||
op = insn.x86_operand_1st();//x86_get_dest_operand
|
||||
next_addr = -1;
|
||||
|
||||
/* if caller supplied a resolver, use it to determine
|
||||
* the address to disassemble */
|
||||
if ( resolver ) {
|
||||
next_addr = resolver(op, &insn, r_arg);
|
||||
} else {
|
||||
next_addr = internal_resolver(op, &insn);
|
||||
}
|
||||
|
||||
if (next_addr != -1 ) {
|
||||
next_offset = next_addr - buf_rva;
|
||||
/* if offset is in this buffer... */
|
||||
if ( next_offset >= 0 && next_offset < buf_len ) {
|
||||
/* go ahead and disassemble */
|
||||
count += x86_disasm_forward( buf,
|
||||
buf_len,
|
||||
buf_rva,
|
||||
next_offset,
|
||||
func, arg,
|
||||
resolver, r_arg );
|
||||
} else {
|
||||
/* report unresolved address */
|
||||
x86_report_error( report_disasm_bounds,
|
||||
(void*)(long)next_addr );
|
||||
}
|
||||
}
|
||||
} /* end follow_insn */
|
||||
|
||||
if ( insn_doesnt_return(&insn) ) {
|
||||
/* stop disassembling */
|
||||
cont = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@ -16,16 +16,21 @@ class CIcodeRec;
|
||||
struct BB;
|
||||
struct LOCAL_ID;
|
||||
struct interval;
|
||||
|
||||
//TODO: consider default address value -> INVALID
|
||||
struct TYPEADR_TYPE
|
||||
{
|
||||
uint32_t ip; /* Out edge icode address */
|
||||
BB * BBptr; /* Out edge pointer to next BB */
|
||||
interval *intPtr; /* Out edge ptr to next interval*/
|
||||
TYPEADR_TYPE(uint32_t addr=0) : ip(addr),BBptr(nullptr),intPtr(nullptr)
|
||||
{}
|
||||
TYPEADR_TYPE(interval *v) : ip(0),BBptr(nullptr),intPtr(v)
|
||||
{}
|
||||
};
|
||||
|
||||
struct BB : public llvm::ilist_node<BB>
|
||||
{
|
||||
|
||||
private:
|
||||
BB(const BB&);
|
||||
BB() : nodeType(0),traversed(DFS_NONE),
|
||||
@ -76,7 +81,7 @@ public:
|
||||
* derived graph Gi-1 */
|
||||
|
||||
/* For live register analysis
|
||||
* LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b)) */
|
||||
* LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b)) */
|
||||
std::bitset<32> liveUse; /* LiveUse(b) */
|
||||
std::bitset<32> def; /* Def(b) */
|
||||
std::bitset<32> liveIn; /* LiveIn(b) */
|
||||
@ -90,9 +95,8 @@ public:
|
||||
int ifFollow; /* node that ends the if */
|
||||
int loopType; /* Type of loop (if any) */
|
||||
int latchNode; /* latching node of the loop */
|
||||
int numBackEdges; /* # of back edges */
|
||||
int loopHead; /* most nested loop head to which
|
||||
* thcis node belongs (dfsLast) */
|
||||
size_t numBackEdges; /* # of back edges */
|
||||
int loopHead; /* most nested loop head to which this node belongs (dfsLast) */
|
||||
int loopFollow; /* node that follows the loop */
|
||||
int caseHead; /* most nested case to which this
|
||||
node belongs (dfsLast) */
|
||||
@ -100,8 +104,8 @@ public:
|
||||
|
||||
int index; /* Index, used in several ways */
|
||||
static BB * Create(void *ctx=0,const std::string &s="",Function *parent=0,BB *insertBefore=0);
|
||||
static BB * Create(int start, int ip, uint8_t nodeType, int numOutEdges, Function * parent);
|
||||
static BB * Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Function *parent);
|
||||
static BB * CreateIntervalBB(Function *parent);
|
||||
static BB * Create(const rCODE &r, uint8_t _nodeType, Function *parent);
|
||||
void writeCode(int indLevel, Function *pProc, int *numLoc, int latchNode, int ifFollow);
|
||||
void mergeFallThrough(CIcodeRec &Icode);
|
||||
void dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last);
|
||||
@ -118,10 +122,15 @@ public:
|
||||
bool valid() {return 0==(flg & INVALID_BB); }
|
||||
bool wasTraversedAtLevel(int l) const {return traversed==l;}
|
||||
ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond);
|
||||
void addOutEdge(uint32_t ip) // TODO: fix this
|
||||
void addOutEdge(uint32_t ip) // TODO: fix this
|
||||
{
|
||||
edges[0].ip = ip;
|
||||
edges.push_back(TYPEADR_TYPE(ip));
|
||||
}
|
||||
void addOutEdgeInterval(interval *i) // TODO: fix this
|
||||
{
|
||||
edges.push_back(TYPEADR_TYPE(i));
|
||||
}
|
||||
|
||||
void RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode);
|
||||
private:
|
||||
bool FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at);
|
||||
|
||||
@ -45,10 +45,10 @@ protected:
|
||||
} boolExpr;
|
||||
|
||||
public:
|
||||
condNodeType m_type; /* Conditional Expression Node Type */
|
||||
condNodeType m_type; /* Conditional Expression Node Type */
|
||||
union _exprNode { /* Different cond expr nodes */
|
||||
COND_EXPR *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
|
||||
IDENTTYPE ident; /* for IDENTIFIER */
|
||||
COND_EXPR *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
|
||||
IDENTTYPE ident; /* for IDENTIFIER */
|
||||
} expr;
|
||||
COND_EXPR *lhs()
|
||||
{
|
||||
@ -72,19 +72,19 @@ public:
|
||||
}
|
||||
condOp op() const { return boolExpr.op;}
|
||||
public:
|
||||
static COND_EXPR *idRegIdx(int idx, regType reg_type);
|
||||
static COND_EXPR *idKte(uint32_t kte, uint8_t size);
|
||||
static COND_EXPR *idLoc(int off, LOCAL_ID *localId);
|
||||
static COND_EXPR *idReg(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym);
|
||||
static COND_EXPR *idLongIdx(int idx);
|
||||
static COND_EXPR *idOther(eReg seg, eReg regi, int16_t off);
|
||||
static COND_EXPR *idParam(int off, const STKFRAME *argSymtab);
|
||||
static COND_EXPR *unary(condNodeType t, COND_EXPR *sub_expr);
|
||||
static COND_EXPR *idLong(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
|
||||
static COND_EXPR *idFunc(Function *pproc, STKFRAME *args);
|
||||
static COND_EXPR *idID(const ID *retVal, LOCAL_ID *locsym, iICODE ix_);
|
||||
static COND_EXPR * idRegIdx(int idx, regType reg_type);
|
||||
static COND_EXPR * idKte(uint32_t kte, uint8_t size);
|
||||
static COND_EXPR * idLoc(int off, LOCAL_ID *localId);
|
||||
static COND_EXPR * idReg(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym);
|
||||
static COND_EXPR * idLongIdx(int idx);
|
||||
static COND_EXPR * idOther(eReg seg, eReg regi, int16_t off);
|
||||
static COND_EXPR * idParam(int off, const STKFRAME *argSymtab);
|
||||
static COND_EXPR * unary(condNodeType t, COND_EXPR *sub_expr);
|
||||
static COND_EXPR * idLong(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
|
||||
static COND_EXPR * idFunc(Function *pproc, STKFRAME *args);
|
||||
static COND_EXPR * idID(const ID *retVal, LOCAL_ID *locsym, iICODE ix_);
|
||||
static COND_EXPR * id(const LLInst &ll_insn, opLoc sd, Function *pProc, iICODE ix_, ICODE &duIcode, operDu du);
|
||||
static COND_EXPR *boolOp(COND_EXPR *_lhs, COND_EXPR *_rhs, condOp _op);
|
||||
static COND_EXPR * boolOp(COND_EXPR *_lhs, COND_EXPR *_rhs, condOp _op);
|
||||
static bool insertSubTreeLongReg(COND_EXPR *exp, COND_EXPR **tree, int longIdx);
|
||||
static bool insertSubTreeReg(COND_EXPR *&tree, COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
public:
|
||||
|
||||
@ -23,6 +23,7 @@ struct SymbolCommon
|
||||
};
|
||||
struct SYM : public SymbolCommon
|
||||
{
|
||||
typedef uint32_t tLabel;
|
||||
SYM() : label(0),flg(0)
|
||||
{
|
||||
|
||||
@ -33,9 +34,10 @@ struct SYM : public SymbolCommon
|
||||
/* STACK FRAME */
|
||||
struct STKSYM : public SymbolCommon
|
||||
{
|
||||
typedef int16_t tLabel;
|
||||
COND_EXPR *actual; /* Expression tree of actual parameter */
|
||||
COND_EXPR *regs; /* For register arguments only */
|
||||
int16_t label; /* Immediate off from BP (+:args, -:params) */
|
||||
tLabel label; /* Immediate off from BP (+:args, -:params) */
|
||||
uint8_t regOff; /* Offset is a register (e.g. SI, DI) */
|
||||
bool hasMacro; /* This type needs a macro */
|
||||
std::string macro; /* Macro name */
|
||||
@ -60,13 +62,13 @@ class SymbolTableCommon : public std::vector<T>
|
||||
public:
|
||||
typedef typename std::vector<T>::iterator iterator;
|
||||
typedef typename std::vector<T>::const_iterator const_iterator;
|
||||
iterator findByLabel(uint32_t lab)
|
||||
iterator findByLabel(typename T::tLabel lab)
|
||||
{
|
||||
auto iter = std::find_if(this->begin(),this->end(),
|
||||
[lab](T &s)->bool {return s.label==lab;});
|
||||
return iter;
|
||||
}
|
||||
const_iterator findByLabel(uint32_t lab) const
|
||||
const_iterator findByLabel(typename T::tLabel lab) const
|
||||
{
|
||||
auto iter = std::find_if(this->begin(),this->end(),
|
||||
[lab](const T &s)->bool {return s.label==lab;});
|
||||
|
||||
@ -19,7 +19,7 @@ BB *BB::Create(void */*ctx*/, const string &/*s*/, Function *parent, BB */*inser
|
||||
* @arg start - basic block starts here, might be parent->Icode.end()
|
||||
* @arg fin - last of basic block's instructions
|
||||
*/
|
||||
BB *BB::Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Function *parent)
|
||||
BB *BB::Create(const rCODE &r,uint8_t _nodeType, Function *parent)
|
||||
{
|
||||
BB* pnewBB;
|
||||
pnewBB = new BB;
|
||||
@ -27,47 +27,28 @@ BB *BB::Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Fun
|
||||
pnewBB->immedDom = NO_DOM;
|
||||
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
|
||||
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
|
||||
pnewBB->instructions = make_iterator_range(start,fin);
|
||||
if(start==parent->Icode.end())
|
||||
{
|
||||
pnewBB->instructions = make_iterator_range(parent->Icode.end(),parent->Icode.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
pnewBB->instructions.advance_end(1); // 1 after fin, to create range where fin is inclusive
|
||||
}
|
||||
if (numOutEdges)
|
||||
pnewBB->edges.resize(numOutEdges);
|
||||
pnewBB->instructions = r;
|
||||
|
||||
/* Mark the basic block to which the icodes belong to, but only for
|
||||
* real code basic blocks (ie. not interval bbs) */
|
||||
* real code basic blocks (ie. not interval bbs) */
|
||||
if(parent)
|
||||
{
|
||||
if (start != parent->Icode.end())
|
||||
parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
|
||||
//setInBB should automatically handle if our range is empty
|
||||
parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
|
||||
parent->heldBBs.push_back(pnewBB);
|
||||
parent->m_cfg.push_back(pnewBB);
|
||||
pnewBB->Parent = parent;
|
||||
}
|
||||
if ( start != parent->Icode.end() ) /* Only for code BB's */
|
||||
|
||||
if ( r.begin() != parent->Icode.end() ) /* Only for code BB's */
|
||||
stats.numBBbef++;
|
||||
return pnewBB;
|
||||
|
||||
}
|
||||
BB *BB::Create(int start, int ip, uint8_t _nodeType, int numOutEdges, Function *parent)
|
||||
BB *BB::CreateIntervalBB(Function *parent)
|
||||
{
|
||||
iICODE st(parent->Icode.begin());
|
||||
iICODE fin(parent->Icode.begin());
|
||||
if(start==-1)
|
||||
{
|
||||
st = parent->Icode.end();
|
||||
fin = parent->Icode.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
advance(st,start);
|
||||
advance(fin,ip);
|
||||
}
|
||||
return Create(st,fin,_nodeType,numOutEdges,parent);
|
||||
iICODE endOfParent = parent->Icode.end();
|
||||
return Create(make_iterator_range(endOfParent,endOfParent),INTERVAL_NODE,parent);
|
||||
}
|
||||
|
||||
static const char *const s_nodeType[] = {"branch", "if", "case", "fall", "return", "call",
|
||||
|
||||
@ -336,9 +336,7 @@ void Function::structLoops(derSeq *derivedG)
|
||||
* h. Note that h is a case node. */
|
||||
static bool successor (int s, int h, Function * pProc)
|
||||
{
|
||||
BB * header;
|
||||
|
||||
header = pProc->m_dfsLast[h];
|
||||
BB * header = pProc->m_dfsLast[h];
|
||||
auto iter = std::find_if(header->edges.begin(),
|
||||
header->edges.end(),
|
||||
[s](const TYPEADR_TYPE &te)->bool{ return te.BBptr->dfsLastNum == s;});
|
||||
@ -431,9 +429,9 @@ static void flagNodes (nodeList &l, int f, Function * pProc)
|
||||
/* Structures if statements */
|
||||
void Function::structIfs ()
|
||||
{
|
||||
size_t followInEdges; /* Largest # in-edges so far */
|
||||
int curr, /* Index for linear scan of nodes */
|
||||
/*desc,*/ /* Index for descendant */
|
||||
followInEdges, /* Largest # in-edges so far */
|
||||
follow; /* Possible follow node */
|
||||
nodeList domDesc, /* List of nodes dominated by curr */
|
||||
unresolved /* List of unresolved if nodes */
|
||||
|
||||
162
src/graph.cpp
162
src/graph.cpp
@ -3,11 +3,17 @@
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include <string.h>
|
||||
#include <malloc.h> /* For free() */
|
||||
#include <boost/range/rbegin.hpp>
|
||||
#include <boost/range/rend.hpp>
|
||||
#include <boost/range/adaptors.hpp>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "graph.h"
|
||||
#include "project.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
extern Project g_proj;
|
||||
//static BB * rmJMP(Function * pProc, int marker, BB * pBB);
|
||||
//static void mergeFallThrough(Function * pProc, BB * pBB);
|
||||
@ -33,116 +39,98 @@ void Function::createCFG()
|
||||
BB * psBB;
|
||||
BB * pBB;
|
||||
iICODE pIcode = Icode.begin();
|
||||
iICODE iStart = Icode.begin();
|
||||
|
||||
stats.numBBbef = stats.numBBaft = 0;
|
||||
for (; pIcode!=Icode.end(); ++pIcode)
|
||||
rICODE current_range=make_iterator_range(pIcode,++iICODE(pIcode));
|
||||
for (; pIcode!=Icode.end(); ++pIcode,current_range.advance_end(1))
|
||||
{
|
||||
iICODE nextIcode = ++iICODE(pIcode);
|
||||
pBB = nullptr;
|
||||
|
||||
LLInst *ll = pIcode->ll();
|
||||
/* Only process icodes that have valid instructions */
|
||||
if(ll->testFlags(NO_CODE))
|
||||
continue;
|
||||
/* Stick a NOWHERE_NODE on the end if we terminate
|
||||
* with anything other than a ret, jump or terminate */
|
||||
* with anything other than a ret, jump or terminate */
|
||||
if (nextIcode == Icode.end() and
|
||||
(not ll->testFlags(TERMINATES)) and
|
||||
(not ll->match(iJMP)) and (not ll->match(iJMPF)) and
|
||||
(not ll->match(iRET)) and (not ll->match(iRETF)))
|
||||
{
|
||||
//pBB=BB::Create(start, ip, NOWHERE_NODE, 0, this);
|
||||
pBB=BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
|
||||
|
||||
pBB=BB::Create(current_range, NOWHERE_NODE, this);
|
||||
}
|
||||
|
||||
/* Only process icodes that have valid instructions */
|
||||
else if (not ll->testFlags(NO_CODE) )
|
||||
{
|
||||
else
|
||||
switch (ll->getOpcode()) {
|
||||
case iJB: case iJBE: case iJAE: case iJA:
|
||||
case iJL: case iJLE: case iJGE: case iJG:
|
||||
case iJE: case iJNE: case iJS: case iJNS:
|
||||
case iJO: case iJNO: case iJP: case iJNP:
|
||||
case iJCXZ:
|
||||
pBB = BB::Create(iStart, pIcode, TWO_BRANCH, 2, this);
|
||||
pBB = BB::Create(current_range, TWO_BRANCH, this);
|
||||
CondJumps:
|
||||
//start = ip + 1;
|
||||
iStart = ++iICODE(pIcode);
|
||||
pBB->edges[0].ip = (uint32_t)iStart->loc_ip;
|
||||
/* This is for jumps off into nowhere */
|
||||
if ( ll->testFlags(NO_LABEL) )
|
||||
{
|
||||
pBB->edges.pop_back();
|
||||
}
|
||||
else
|
||||
pBB->edges[1].ip = ll->src().getImm2();
|
||||
pBB->addOutEdge(nextIcode->loc_ip);
|
||||
/* This is checking for jumps off into nowhere */
|
||||
if ( not ll->testFlags(NO_LABEL) )
|
||||
pBB->addOutEdge(ll->src().getImm2());
|
||||
break;
|
||||
|
||||
case iLOOP: case iLOOPE: case iLOOPNE:
|
||||
//pBB = BB::Create(start, ip, LOOP_NODE, 2, this);
|
||||
pBB = BB::Create(iStart, pIcode, LOOP_NODE, 2, this);
|
||||
pBB = BB::Create(current_range, LOOP_NODE, this);
|
||||
goto CondJumps;
|
||||
|
||||
case iJMPF: case iJMP:
|
||||
if (ll->testFlags(SWITCH))
|
||||
{
|
||||
//pBB = BB::Create(start, ip, MULTI_BRANCH, ll->caseTbl.numEntries, this);
|
||||
pBB = BB::Create(iStart, pIcode, MULTI_BRANCH, ll->caseTbl2.size(), this);
|
||||
pBB = BB::Create(current_range, MULTI_BRANCH, this);
|
||||
for (size_t i = 0; i < ll->caseTbl2.size(); i++)
|
||||
pBB->edges[i].ip = ll->caseTbl2[i];
|
||||
pBB->addOutEdge(ll->caseTbl2[i]);
|
||||
hasCase = true;
|
||||
}
|
||||
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT
|
||||
{
|
||||
//pBB = BB::Create(start, ip, ONE_BRANCH, 1, this);
|
||||
pBB = BB::Create(iStart, pIcode, ONE_BRANCH, 1, this);
|
||||
|
||||
pBB->edges[0].ip = ll->src().getImm2();
|
||||
pBB = BB::Create(current_range, ONE_BRANCH, this);
|
||||
pBB->addOutEdge(ll->src().getImm2());
|
||||
}
|
||||
else
|
||||
BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode);
|
||||
pBB = BB::Create(current_range, NOWHERE_NODE, this);
|
||||
break;
|
||||
|
||||
case iCALLF: case iCALL:
|
||||
{
|
||||
Function * p = ll->src().proc.proc;
|
||||
if (p)
|
||||
i = ((p->flg) & TERMINATES) ? 0 : 1;
|
||||
else
|
||||
i = 1;
|
||||
pBB = BB::Create(iStart, pIcode, CALL_NODE, i, this);
|
||||
iStart = ++iICODE(pIcode);//start = ip + 1;
|
||||
if (i)
|
||||
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
|
||||
}
|
||||
pBB = BB::Create(current_range, CALL_NODE, this);
|
||||
if (p && not ((p->flg) & TERMINATES) )
|
||||
pBB->addOutEdge(nextIcode->loc_ip);
|
||||
break;
|
||||
}
|
||||
|
||||
case iRET: case iRETF:
|
||||
//BB::Create(start, ip, RETURN_NODE, 0, this);
|
||||
BB::Create(iStart, pIcode, RETURN_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode);
|
||||
pBB = BB::Create(current_range, RETURN_NODE, this);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Check for exit to DOS */
|
||||
iICODE next1=++iICODE(pIcode);
|
||||
if ( ll->testFlags(TERMINATES) )
|
||||
{
|
||||
pBB = BB::Create(iStart, pIcode, TERMINATE_NODE, 0, this);
|
||||
//pBB = BB::Create(start, ip, TERMINATE_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode); // start = ip + 1;
|
||||
pBB = BB::Create(current_range, TERMINATE_NODE, this);
|
||||
}
|
||||
/* Check for a fall through */
|
||||
else if (next1 != Icode.end())
|
||||
else if (nextIcode != Icode.end())
|
||||
{
|
||||
if (next1->ll()->testFlags(TARGET | CASE))
|
||||
if (nextIcode->ll()->testFlags(TARGET | CASE))
|
||||
{
|
||||
//pBB = BB::Create(start, ip, FALL_NODE, 1, this);
|
||||
pBB = BB::Create(iStart, pIcode, FALL_NODE, 1, this);
|
||||
iStart = ++iICODE(pIcode); // start = ip + 1;
|
||||
pBB->addOutEdge(iStart->loc_ip);
|
||||
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
|
||||
pBB = BB::Create(current_range, FALL_NODE, this);
|
||||
pBB->addOutEdge(nextIcode->loc_ip);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(pBB!=nullptr) // created a new Basic block
|
||||
{
|
||||
// restart the range
|
||||
// end iterator will be updated by expression in for statement
|
||||
current_range=make_iterator_range(nextIcode,nextIcode);
|
||||
}
|
||||
}
|
||||
auto iter=heldBBs.begin();
|
||||
@ -160,14 +148,14 @@ CondJumps:
|
||||
}
|
||||
auto iter2=std::find_if(heldBBs.begin(),heldBBs.end(),
|
||||
[ip](BB *psBB)->bool {return psBB->begin()->loc_ip==ip;});
|
||||
if(iter2==heldBBs.end())
|
||||
fatalError(NO_BB, ip, name.c_str());
|
||||
psBB = *iter2;
|
||||
pBB->edges[edeg_idx].BBptr = psBB;
|
||||
psBB->inEdges.push_back((BB *)nullptr);
|
||||
}
|
||||
if(iter2==heldBBs.end())
|
||||
fatalError(NO_BB, ip, name.c_str());
|
||||
psBB = *iter2;
|
||||
pBB->edges[edeg_idx].BBptr = psBB;
|
||||
psBB->inEdges.push_back((BB *)nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Function::markImpure()
|
||||
{
|
||||
@ -350,33 +338,33 @@ void BB::mergeFallThrough( CIcodeRec &Icode)
|
||||
auto iter=std::find_if(this->end(),pChild->begin(),[](ICODE &c)
|
||||
{return not c.ll()->testFlags(NO_CODE);});
|
||||
|
||||
if (iter != pChild->begin())
|
||||
break;
|
||||
back().ll()->setFlags(NO_CODE);
|
||||
back().invalidate();
|
||||
nodeType = FALL_NODE;
|
||||
//instructions.advance_end(-1); //TODO: causes creation of empty BB
|
||||
}
|
||||
/* If there's no other edges into child can merge */
|
||||
if (pChild->inEdges.size() != 1)
|
||||
if (iter != pChild->begin())
|
||||
break;
|
||||
|
||||
nodeType = pChild->nodeType;
|
||||
instructions = boost::make_iterator_range(begin(),pChild->end());
|
||||
pChild->front().ll()->clrFlags(TARGET);
|
||||
edges.swap(pChild->edges);
|
||||
|
||||
pChild->inEdges.clear();
|
||||
pChild->edges.clear();
|
||||
back().ll()->setFlags(NO_CODE);
|
||||
back().invalidate();
|
||||
nodeType = FALL_NODE;
|
||||
//instructions.advance_end(-1); //TODO: causes creation of empty BB
|
||||
}
|
||||
traversed = DFS_MERGE;
|
||||
/* If there's no other edges into child can merge */
|
||||
if (pChild->inEdges.size() != 1)
|
||||
break;
|
||||
|
||||
/* Process all out edges recursively */
|
||||
for (size_t i = 0; i < edges.size(); i++)
|
||||
{
|
||||
if (edges[i].BBptr->traversed != DFS_MERGE)
|
||||
edges[i].BBptr->mergeFallThrough(Icode);
|
||||
}
|
||||
nodeType = pChild->nodeType;
|
||||
instructions = boost::make_iterator_range(begin(),pChild->end());
|
||||
pChild->front().ll()->clrFlags(TARGET);
|
||||
edges.swap(pChild->edges);
|
||||
|
||||
pChild->inEdges.clear();
|
||||
pChild->edges.clear();
|
||||
}
|
||||
traversed = DFS_MERGE;
|
||||
|
||||
/* Process all out edges recursively */
|
||||
for (size_t i = 0; i < edges.size(); i++)
|
||||
{
|
||||
if (edges[i].BBptr->traversed != DFS_MERGE)
|
||||
edges[i].BBptr->mergeFallThrough(Icode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ OPTION option; /* Command line options */
|
||||
Project *Project::s_instance = 0;
|
||||
Project::Project() : callGraph(nullptr)
|
||||
{
|
||||
|
||||
memset(&prog,0,sizeof(prog));
|
||||
}
|
||||
void Project::initialize()
|
||||
{
|
||||
@ -49,8 +49,7 @@ ilFunction Project::findByEntry(uint32_t entry)
|
||||
{
|
||||
/* Search procedure list for one with appropriate entry point */
|
||||
ilFunction iter= std::find_if(pProcList.begin(),pProcList.end(),
|
||||
[entry](const Function &f) ->
|
||||
bool { return f.procEntry==entry; });
|
||||
[entry](const Function &f) { return f.procEntry==entry; });
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
@ -540,20 +540,19 @@ void Function::propLong()
|
||||
for (size_t i = 0; i < localId.csym(); i++)
|
||||
{
|
||||
const ID &pLocId(localId.id_arr[i]);
|
||||
if ((pLocId.type==TYPE_LONG_SIGN) || (pLocId.type==TYPE_LONG_UNSIGN))
|
||||
if ((pLocId.type!=TYPE_LONG_SIGN) and (pLocId.type!=TYPE_LONG_UNSIGN))
|
||||
continue;
|
||||
switch (pLocId.loc)
|
||||
{
|
||||
switch (pLocId.loc)
|
||||
{
|
||||
case STK_FRAME:
|
||||
propLongStk (i, pLocId);
|
||||
break;
|
||||
case REG_FRAME:
|
||||
propLongReg (i, pLocId);
|
||||
break;
|
||||
case GLB_FRAME:
|
||||
propLongGlb (i, pLocId);
|
||||
break;
|
||||
}
|
||||
case STK_FRAME:
|
||||
propLongStk (i, pLocId);
|
||||
break;
|
||||
case REG_FRAME:
|
||||
propLongReg (i, pLocId);
|
||||
break;
|
||||
case GLB_FRAME:
|
||||
propLongGlb (i, pLocId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,29 +236,23 @@ derSeq_Entry::~derSeq_Entry()
|
||||
bool Function::nextOrderGraph (derSeq &derivedGi)
|
||||
{
|
||||
interval *Ii; /* Interval being processed */
|
||||
BB *BBnode, /* New basic block of intervals */
|
||||
//*curr, /* BB being checked for out edges */
|
||||
*succ /* Successor node */
|
||||
;
|
||||
//queue *listIi; /* List of intervals */
|
||||
int i; /* Index to outEdges array */
|
||||
/*j;*/ /* Index to successors */
|
||||
boolT sameGraph; /* Boolean, isomorphic graphs */
|
||||
BB *BBnode; /* New basic block of intervals */
|
||||
bool sameGraph; /* Boolean, isomorphic graphs */
|
||||
|
||||
/* Process Gi's intervals */
|
||||
derSeq_Entry &prev_entry(derivedGi.back());
|
||||
derivedGi.push_back(derSeq_Entry());
|
||||
derSeq_Entry &new_entry(derivedGi.back());
|
||||
Ii = prev_entry.Ii;
|
||||
|
||||
sameGraph = true;
|
||||
BBnode = 0;
|
||||
std::vector<BB *> bbs;
|
||||
while (Ii)
|
||||
for(Ii = prev_entry.Ii; Ii != nullptr; Ii = Ii->next)
|
||||
{
|
||||
i = 0;
|
||||
bbs.push_back(BB::Create(-1, -1, INTERVAL_NODE, Ii->numOutEdges, this));
|
||||
BBnode = bbs.back();
|
||||
|
||||
BBnode = BB::CreateIntervalBB(this);
|
||||
BBnode->correspInt = Ii;
|
||||
bbs.push_back(BBnode);
|
||||
const queue &listIi(Ii->nodes);
|
||||
|
||||
/* Check for more than 1 interval */
|
||||
@ -267,21 +261,17 @@ bool Function::nextOrderGraph (derSeq &derivedGi)
|
||||
|
||||
/* Find out edges */
|
||||
|
||||
if (BBnode->edges.size() > 0)
|
||||
if (Ii->numOutEdges <= 0)
|
||||
continue;
|
||||
for(BB *curr : listIi)
|
||||
{
|
||||
for(BB *curr : listIi)
|
||||
for (size_t j = 0; j < curr->edges.size(); j++)
|
||||
{
|
||||
for (size_t j = 0; j < curr->edges.size(); j++)
|
||||
{
|
||||
succ = curr->edges[j].BBptr;
|
||||
if (succ->inInterval != curr->inInterval)
|
||||
BBnode->edges[i++].intPtr = succ->inInterval;
|
||||
}
|
||||
BB *successor_node = curr->edges[j].BBptr;
|
||||
if (successor_node->inInterval != curr->inInterval)
|
||||
BBnode->addOutEdgeInterval(successor_node->inInterval);
|
||||
}
|
||||
}
|
||||
|
||||
/* Next interval */
|
||||
Ii = Ii->next;
|
||||
}
|
||||
|
||||
/* Convert list of pointers to intervals into a real graph.
|
||||
@ -303,7 +293,7 @@ bool Function::nextOrderGraph (derSeq &derivedGi)
|
||||
(*iter)->inEdgeCount++;
|
||||
}
|
||||
}
|
||||
return (boolT)(! sameGraph);
|
||||
return not sameGraph;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -357,8 +357,7 @@ static void fixFloatEmulation(x86_insn_t &insn)
|
||||
if ((wOp < 0x34) || (wOp > 0x3B))
|
||||
return;
|
||||
uint8_t buf[16];
|
||||
/* This is a Borland/Microsoft floating point emulation instruction.
|
||||
Treat as if it is an ESC opcode */
|
||||
/* This is a Borland/Microsoft floating point emulation instruction. Treat as if it is an ESC opcode */
|
||||
|
||||
int actual_valid_bytes=std::min(16U,prog.cbImage-insn.offset);
|
||||
memcpy(buf,prog.Image+insn.offset,actual_valid_bytes);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "dcc.h"
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include "dcc.h"
|
||||
|
||||
TEST(CowriteTest, HandlesZeroInput) {
|
||||
EXPECT_EQ(1, 1);
|
||||
|
||||
@ -13,8 +13,8 @@ TEST(Project, NewProjectIsInitalized) {
|
||||
|
||||
TEST(Project, CreatedProjectHasValidNames) {
|
||||
Project p;
|
||||
std::vector<std::string> strs = {"./Project1.EXE","/home/Project2.EXE","/home/Pro ject3"};
|
||||
std::vector<std::string> expected = {"Project1","Project2","Pro ject3"};
|
||||
std::vector<std::string> strs = {"./Project1.EXE","/home/Project2.EXE","/home/Pro\\ ject3"};
|
||||
std::vector<std::string> expected = {"Project1","Project2","Pro\\ ject3"};
|
||||
for(size_t i=0; i<strs.size(); i++)
|
||||
{
|
||||
p.create(strs[i]);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user