More simplifications on BB creation

This commit is contained in:
Artur K 2012-07-14 23:04:09 +02:00
parent ba110a64cb
commit 5087a051b5
19 changed files with 989 additions and 1027 deletions

View File

@ -13,412 +13,412 @@
* would have 'write only' access for AX and 'read only' access for AL, * would have 'write only' access for AX and 'read only' access for AL,
* even though both AL and AX are read and written */ * even though both AL and AX are read and written */
typedef struct { typedef struct {
uint32_t type; uint32_t type;
uint32_t operand; uint32_t operand;
} op_implicit_list_t; } op_implicit_list_t;
static op_implicit_list_t list_aaa[] = static op_implicit_list_t list_aaa[] =
/* 37 : AAA : rw AL */ /* 37 : AAA : rw AL */
/* 3F : AAS : rw AL */ /* 3F : AAS : rw AL */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* aaa */ {{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* aaa */
static op_implicit_list_t list_aad[] = static op_implicit_list_t list_aad[] =
/* D5 0A, D5 (ib) : AAD : rw AX */ /* D5 0A, D5 (ib) : AAD : rw AX */
/* D4 0A, D4 (ib) : AAM : rw AX */ /* D4 0A, D4 (ib) : AAM : rw AX */
{{ OP_R | OP_W, REG_WORD_OFFSET }, {0,0}}; /* aad */ {{ OP_R | OP_W, REG_WORD_OFFSET }, {0,0}}; /* aad */
static op_implicit_list_t list_call[] = static op_implicit_list_t list_call[] =
/* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */ /* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
/* C2, C3, CA, CB : RET : 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_EIP_INDEX },
{ OP_R | OP_W, REG_ESP_INDEX }, {0,0}}; /* call, ret */ { OP_R | OP_W, REG_ESP_INDEX }, {0,0}}; /* call, ret */
static op_implicit_list_t list_cbw[] = static op_implicit_list_t list_cbw[] =
/* 98 : CBW : r AL, rw AX */ /* 98 : CBW : r AL, rw AX */
{{ OP_R | OP_W, REG_WORD_OFFSET }, {{ OP_R | OP_W, REG_WORD_OFFSET },
{ OP_R, REG_BYTE_OFFSET}, {0,0}}; /* cbw */ { OP_R, REG_BYTE_OFFSET}, {0,0}}; /* cbw */
static op_implicit_list_t list_cwde[] = static op_implicit_list_t list_cwde[] =
/* 98 : CWDE : r AX, rw EAX */ /* 98 : CWDE : r AX, rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_R, REG_WORD_OFFSET }, {0,0}}; /* cwde */ { OP_R, REG_WORD_OFFSET }, {0,0}}; /* cwde */
static op_implicit_list_t list_clts[] = static op_implicit_list_t list_clts[] =
/* 0F 06 : CLTS : rw CR0 */ /* 0F 06 : CLTS : rw CR0 */
{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0,0}}; /* clts */ {{ OP_R | OP_W, REG_CTRL_OFFSET}, {0,0}}; /* clts */
static op_implicit_list_t list_cmpxchg[] = static op_implicit_list_t list_cmpxchg[] =
/* 0F B0 : CMPXCHG : rw AL */ /* 0F B0 : CMPXCHG : rw AL */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* cmpxchg */ {{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* cmpxchg */
static op_implicit_list_t list_cmpxchgb[] = static op_implicit_list_t list_cmpxchgb[] =
/* 0F B1 : CMPXCHG : rw EAX */ /* 0F B1 : CMPXCHG : rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* cmpxchg */ {{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* cmpxchg */
static op_implicit_list_t list_cmpxchg8b[] = static op_implicit_list_t list_cmpxchg8b[] =
/* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */ /* 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 },
{ OP_R | OP_W, REG_DWORD_OFFSET + 2 }, { OP_R | OP_W, REG_DWORD_OFFSET + 2 },
{ OP_R, REG_DWORD_OFFSET + 1 }, { OP_R, REG_DWORD_OFFSET + 1 },
{ OP_R, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cmpxchg8b */ { OP_R, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cmpxchg8b */
static op_implicit_list_t list_cpuid[] = static op_implicit_list_t list_cpuid[] =
/* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */ /* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_W, REG_DWORD_OFFSET + 1 }, { OP_W, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET + 2 }, { OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cpuid */ { OP_W, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cpuid */
static op_implicit_list_t list_cwd[] = static op_implicit_list_t list_cwd[] =
/* 99 : CWD/CWQ : rw EAX, w EDX */ /* 99 : CWD/CWQ : rw EAX, w EDX */
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* cwd */ { OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* cwd */
static op_implicit_list_t list_daa[] = static op_implicit_list_t list_daa[] =
/* 27 : DAA : rw AL */ /* 27 : DAA : rw AL */
/* 2F : DAS : rw AL */ /* 2F : DAS : rw AL */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* daa */ {{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* daa */
static op_implicit_list_t list_idiv[] = static op_implicit_list_t list_idiv[] =
/* F6 : DIV, IDIV : r AX, w AL, w AH */ /* F6 : DIV, IDIV : r AX, w AL, w AH */
/* FIXED: first op was EAX, not Aw. TODO: verify! */ /* FIXED: first op was EAX, not Aw. TODO: verify! */
{{ OP_R, REG_WORD_OFFSET }, {{ OP_R, REG_WORD_OFFSET },
{ OP_W, REG_BYTE_OFFSET }, { OP_W, REG_BYTE_OFFSET },
{ OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* div */ { OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* div */
static op_implicit_list_t list_div[] = static op_implicit_list_t list_div[] =
/* F7 : DIV, IDIV : rw EDX, rw EAX */ /* F7 : DIV, IDIV : rw EDX, rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 }, {{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* div */ { OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* div */
static op_implicit_list_t list_enter[] = static op_implicit_list_t list_enter[] =
/* C8 : ENTER : rw ESP w EBP */ /* C8 : ENTER : rw ESP w EBP */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 4 }, {{ OP_R | OP_W, REG_DWORD_OFFSET + 4 },
{ OP_R, REG_DWORD_OFFSET + 5 }, {0,0}}; /* enter */ { OP_R, REG_DWORD_OFFSET + 5 }, {0,0}}; /* enter */
static op_implicit_list_t list_f2xm1[] = static op_implicit_list_t list_f2xm1[] =
/* D9 F0 : F2XM1 : rw ST(0) */ /* D9 F0 : F2XM1 : rw ST(0) */
/* D9 E1 : FABS : rw ST(0) */ /* D9 E1 : FABS : rw ST(0) */
/* D9 E0 : FCHS : rw ST(0) */ /* D9 E0 : FCHS : rw ST(0) */
/* D9 FF : FCOS : rw ST(0)*/ /* D9 FF : FCOS : rw ST(0)*/
/* D8, DA : FDIV : rw ST(0) */ /* D8, DA : FDIV : rw ST(0) */
/* D8, DA : FDIVR : rw ST(0) */ /* D8, DA : FDIVR : rw ST(0) */
/* D9 F2 : FPTAN : rw ST(0) */ /* D9 F2 : FPTAN : rw ST(0) */
/* D9 FC : FRNDINT : rw ST(0) */ /* D9 FC : FRNDINT : rw ST(0) */
/* D9 FB : FSINCOS : rw ST(0) */ /* D9 FB : FSINCOS : rw ST(0) */
/* D9 FE : FSIN : rw ST(0) */ /* D9 FE : FSIN : rw ST(0) */
/* D9 FA : FSQRT : rw ST(0) */ /* D9 FA : FSQRT : rw ST(0) */
/* D9 F4 : FXTRACT : rw ST(0) */ /* D9 F4 : FXTRACT : rw ST(0) */
{{ OP_R | OP_W, REG_FPU_OFFSET }, {0,0}}; /* f2xm1 */ {{ OP_R | OP_W, REG_FPU_OFFSET }, {0,0}}; /* f2xm1 */
static op_implicit_list_t list_fcom[] = static op_implicit_list_t list_fcom[] =
/* D8, DC, DE D9 : FCOM : r ST(0) */ /* D8, DC, DE D9 : FCOM : r ST(0) */
/* DE, DA : FICOM : r ST(0) */ /* DE, DA : FICOM : r ST(0) */
/* DF, D8 : FIST : r ST(0) */ /* DF, D8 : FIST : r ST(0) */
/* D9 E4 : FTST : r ST(0) */ /* D9 E4 : FTST : r ST(0) */
/* D9 E5 : FXAM : r ST(0) */ /* D9 E5 : FXAM : r ST(0) */
{{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fcom */ {{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fcom */
static op_implicit_list_t list_fpatan[] = static op_implicit_list_t list_fpatan[] =
/* D9 F3 : FPATAN : r ST(0), rw ST(1) */ /* D9 F3 : FPATAN : r ST(0), rw ST(1) */
{{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fpatan */ {{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fpatan */
static op_implicit_list_t list_fprem[] = static op_implicit_list_t list_fprem[] =
/* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */ /* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
/* D9 FD : FSCALE : rw ST(0), r ST(1) */ /* D9 FD : FSCALE : rw ST(0), r ST(1) */
{{ OP_R | OP_W, REG_FPU_OFFSET }, {{ OP_R | OP_W, REG_FPU_OFFSET },
{ OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fprem */ { OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fprem */
static op_implicit_list_t list_faddp[] = static op_implicit_list_t list_faddp[] =
/* DE C1 : FADDP : r ST(0), rw ST(1) */ /* DE C1 : FADDP : r ST(0), rw ST(1) */
/* DE E9 : FSUBP : 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 F1 : FYL2X : r ST(0), rw ST(1) */
/* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */ /* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
{{ OP_R, REG_FPU_OFFSET }, {{ OP_R, REG_FPU_OFFSET },
{ OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0,0}}; /* faddp */ { OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0,0}}; /* faddp */
static op_implicit_list_t list_fucompp[] = static op_implicit_list_t list_fucompp[] =
/* DA E9 : FUCOMPP : r ST(0), r ST(1) */ /* DA E9 : FUCOMPP : r ST(0), r ST(1) */
{{ OP_R, REG_FPU_OFFSET }, {{ OP_R, REG_FPU_OFFSET },
{ OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fucompp */ { OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fucompp */
static op_implicit_list_t list_imul[] = static op_implicit_list_t list_imul[] =
/* F6 : IMUL : r AL, w AX */ /* F6 : IMUL : r AL, w AX */
/* F6 : MUL : r AL, w AX */ /* F6 : MUL : r AL, w AX */
{{ OP_R, REG_BYTE_OFFSET }, {{ OP_R, REG_BYTE_OFFSET },
{ OP_W, REG_WORD_OFFSET }, {0,0}}; /* imul */ { OP_W, REG_WORD_OFFSET }, {0,0}}; /* imul */
static op_implicit_list_t list_mul[] = static op_implicit_list_t list_mul[] =
/* F7 : IMUL : rw EAX, w EDX */ /* F7 : IMUL : rw EAX, w EDX */
/* F7 : MUL : rw EAX, w EDX */ /* F7 : MUL : rw EAX, w EDX */
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* imul */ { OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* imul */
static op_implicit_list_t list_lahf[] = static op_implicit_list_t list_lahf[] =
/* 9F : LAHF : r EFLAGS, w AH */ /* 9F : LAHF : r EFLAGS, w AH */
{{ OP_R, REG_FLAGS_INDEX }, {{ OP_R, REG_FLAGS_INDEX },
{ OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* lahf */ { OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* lahf */
static op_implicit_list_t list_ldmxcsr[] = static op_implicit_list_t list_ldmxcsr[] =
/* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */ /* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
{{ OP_W, REG_MXCSG_INDEX }, {0,0}}; /* ldmxcsr */ {{ OP_W, REG_MXCSG_INDEX }, {0,0}}; /* ldmxcsr */
static op_implicit_list_t list_leave[] = static op_implicit_list_t list_leave[] =
/* C9 : LEAVE : rw ESP, w EBP */ /* C9 : LEAVE : rw ESP, w EBP */
{{ OP_R | OP_W, REG_ESP_INDEX }, {{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_W, REG_DWORD_OFFSET + 5 }, {0,0}}; /* leave */ { OP_W, REG_DWORD_OFFSET + 5 }, {0,0}}; /* leave */
static op_implicit_list_t list_lgdt[] = static op_implicit_list_t list_lgdt[] =
/* 0F 01 : LGDT : w GDTR */ /* 0F 01 : LGDT : w GDTR */
{{ OP_W, REG_GDTR_INDEX }, {0,0}}; /* lgdt */ {{ OP_W, REG_GDTR_INDEX }, {0,0}}; /* lgdt */
static op_implicit_list_t list_lidt[] = static op_implicit_list_t list_lidt[] =
/* 0F 01 : LIDT : w IDTR */ /* 0F 01 : LIDT : w IDTR */
{{ OP_W, REG_IDTR_INDEX }, {0,0}}; /* lidt */ {{ OP_W, REG_IDTR_INDEX }, {0,0}}; /* lidt */
static op_implicit_list_t list_lldt[] = static op_implicit_list_t list_lldt[] =
/* 0F 00 : LLDT : w LDTR */ /* 0F 00 : LLDT : w LDTR */
{{ OP_W, REG_LDTR_INDEX }, {0,0}}; /* lldt */ {{ OP_W, REG_LDTR_INDEX }, {0,0}}; /* lldt */
static op_implicit_list_t list_lmsw[] = static op_implicit_list_t list_lmsw[] =
/* 0F 01 : LMSW : w CR0 */ /* 0F 01 : LMSW : w CR0 */
{{ OP_W, REG_CTRL_OFFSET }, {0,0}}; /* lmsw */ {{ OP_W, REG_CTRL_OFFSET }, {0,0}}; /* lmsw */
static op_implicit_list_t list_loop[] = static op_implicit_list_t list_loop[] =
/* E0, E1, E2 : LOOP : rw ECX */ /* E0, E1, E2 : LOOP : rw ECX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* loop */ {{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* loop */
static op_implicit_list_t list_ltr[] = static op_implicit_list_t list_ltr[] =
/* 0F 00 : LTR : w Task Register */ /* 0F 00 : LTR : w Task Register */
{{ OP_W, REG_TR_INDEX }, {0,0}}; /* ltr */ {{ OP_W, REG_TR_INDEX }, {0,0}}; /* ltr */
static op_implicit_list_t list_pop[] = static op_implicit_list_t list_pop[] =
/* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */ /* 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 */ /* 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 */ {{ OP_R | OP_W, REG_ESP_INDEX }, {0,0}}; /* pop, push */
static op_implicit_list_t list_popad[] = static op_implicit_list_t list_popad[] =
/* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */ /* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
{{ OP_R | OP_W, REG_ESP_INDEX }, {{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_W, REG_DWORD_OFFSET + 7 }, { OP_W, REG_DWORD_OFFSET + 7 },
{ OP_W, REG_DWORD_OFFSET + 6 }, { OP_W, REG_DWORD_OFFSET + 6 },
{ OP_W, REG_DWORD_OFFSET + 5 }, { OP_W, REG_DWORD_OFFSET + 5 },
{ OP_W, REG_DWORD_OFFSET + 3 }, { OP_W, REG_DWORD_OFFSET + 3 },
{ OP_W, REG_DWORD_OFFSET + 2 }, { OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET + 1 }, { OP_W, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* popad */ { OP_W, REG_DWORD_OFFSET }, {0,0}}; /* popad */
static op_implicit_list_t list_popfd[] = static op_implicit_list_t list_popfd[] =
/* 9D : POPFD : rw esp, w eflags */ /* 9D : POPFD : rw esp, w eflags */
{{ OP_R | OP_W, REG_ESP_INDEX }, {{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_W, REG_FLAGS_INDEX }, {0,0}}; /* popfd */ { OP_W, REG_FLAGS_INDEX }, {0,0}}; /* popfd */
static op_implicit_list_t list_pushad[] = static op_implicit_list_t list_pushad[] =
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */ /* 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 */ /* 60 : PUSHAD : rw esp, r eax ecx edx ebx esp ebp esi edi */
{{ OP_R | OP_W, REG_ESP_INDEX }, {{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_R, REG_DWORD_OFFSET }, { OP_R, REG_DWORD_OFFSET },
{ OP_R, REG_DWORD_OFFSET + 1 }, { OP_R, REG_DWORD_OFFSET + 1 },
{ OP_R, REG_DWORD_OFFSET + 2 }, { OP_R, REG_DWORD_OFFSET + 2 },
{ OP_R, REG_DWORD_OFFSET + 3 }, { OP_R, REG_DWORD_OFFSET + 3 },
{ OP_R, REG_DWORD_OFFSET + 5 }, { OP_R, REG_DWORD_OFFSET + 5 },
{ OP_R, REG_DWORD_OFFSET + 6 }, { OP_R, REG_DWORD_OFFSET + 6 },
{ OP_R, REG_DWORD_OFFSET + 7 }, {0,0}}; /* pushad */ { OP_R, REG_DWORD_OFFSET + 7 }, {0,0}}; /* pushad */
static op_implicit_list_t list_pushfd[] = static op_implicit_list_t list_pushfd[] =
/* 9C : PUSHFD : rw esp, r eflags */ /* 9C : PUSHFD : rw esp, r eflags */
{{ OP_R | OP_W, REG_ESP_INDEX }, {{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_R, REG_FLAGS_INDEX }, {0,0}}; /* pushfd */ { OP_R, REG_FLAGS_INDEX }, {0,0}}; /* pushfd */
static op_implicit_list_t list_rdmsr[] = static op_implicit_list_t list_rdmsr[] =
/* 0F 32 : RDMSR : r ECX, w EDX, w EAX */ /* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
{{ OP_R, REG_DWORD_OFFSET + 1 }, {{ OP_R, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET + 2 }, { OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdmsr */ { OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdmsr */
static op_implicit_list_t list_rdpmc[] = static op_implicit_list_t list_rdpmc[] =
/* 0F 33 : RDPMC : r ECX, w EDX, w EAX */ /* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
{{ OP_R, REG_DWORD_OFFSET + 1 }, {{ OP_R, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET + 2 }, { OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdpmc */ { OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdpmc */
static op_implicit_list_t list_rdtsc[] = static op_implicit_list_t list_rdtsc[] =
/* 0F 31 : RDTSC : rw EDX, rw EAX */ /* 0F 31 : RDTSC : rw EDX, rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 }, {{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdtsc */ { OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdtsc */
static op_implicit_list_t list_rep[] = static op_implicit_list_t list_rep[] =
/* F3, F2 ... : REP : rw ECX */ /* F3, F2 ... : REP : rw ECX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* rep */ {{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* rep */
static op_implicit_list_t list_rsm[] = static op_implicit_list_t list_rsm[] =
/* 0F AA : RSM : r CR4, r CR0 */ /* 0F AA : RSM : r CR4, r CR0 */
{{ OP_R, REG_CTRL_OFFSET + 4 }, {{ OP_R, REG_CTRL_OFFSET + 4 },
{ OP_R, REG_CTRL_OFFSET }, {0,0}}; /* rsm */ { OP_R, REG_CTRL_OFFSET }, {0,0}}; /* rsm */
static op_implicit_list_t list_sahf[] = static op_implicit_list_t list_sahf[] =
/* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */ /* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sahf */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sahf */
static op_implicit_list_t list_sgdt[] = static op_implicit_list_t list_sgdt[] =
/* 0F : SGDT : r gdtr */ /* 0F : SGDT : r gdtr */
/* TODO: finish this! */ /* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sgdt */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sgdt */
static op_implicit_list_t list_sidt[] = static op_implicit_list_t list_sidt[] =
/* 0F : SIDT : r idtr */ /* 0F : SIDT : r idtr */
/* TODO: finish this! */ /* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sidt */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sidt */
static op_implicit_list_t list_sldt[] = static op_implicit_list_t list_sldt[] =
/* 0F : SLDT : r ldtr */ /* 0F : SLDT : r ldtr */
/* TODO: finish this! */ /* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sldt */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sldt */
static op_implicit_list_t list_smsw[] = static op_implicit_list_t list_smsw[] =
/* 0F : SMSW : r CR0 */ /* 0F : SMSW : r CR0 */
/* TODO: finish this! */ /* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* smsw */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* smsw */
static op_implicit_list_t list_stmxcsr[] = static op_implicit_list_t list_stmxcsr[] =
/* 0F AE : STMXCSR : r MXCSR */ /* 0F AE : STMXCSR : r MXCSR */
/* TODO: finish this! */ /* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* stmxcsr */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* stmxcsr */
static op_implicit_list_t list_str[] = static op_implicit_list_t list_str[] =
/* 0F 00 : STR : r TR (task register) */ /* 0F 00 : STR : r TR (task register) */
/* TODO: finish this! */ /* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* str */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* str */
static op_implicit_list_t list_sysenter[] = static op_implicit_list_t list_sysenter[] =
/* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags /* 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 */ * r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
/* TODO: finish this! */ /* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysenter */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysenter */
static op_implicit_list_t list_sysexit[] = static op_implicit_list_t list_sysexit[] =
/* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp /* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
* r sysenter_cs_msr */ * r sysenter_cs_msr */
/* TODO: finish this! */ /* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysexit */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysexit */
static op_implicit_list_t list_wrmsr[] = static op_implicit_list_t list_wrmsr[] =
/* 0F 30 : WRMST : r edx, r eax, r ecx */ /* 0F 30 : WRMST : r edx, r eax, r ecx */
/* TODO: finish this! */ /* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* wrmsr */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* wrmsr */
static op_implicit_list_t list_xlat[] = static op_implicit_list_t list_xlat[] =
/* D7 : XLAT : rw al r ebx (ptr) */ /* D7 : XLAT : rw al r ebx (ptr) */
/* TODO: finish this! */ /* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* xlat */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* xlat */
/* TODO: /* TODO:
* monitor 0f 01 c8 eax OP_R ecx OP_R edx OP_R * monitor 0f 01 c8 eax OP_R ecx OP_R edx OP_R
* mwait 0f 01 c9 eax OP_R ecx OP_R * mwait 0f 01 c9 eax OP_R ecx OP_R
*/ */
static op_implicit_list_t list_monitor[] = static op_implicit_list_t list_monitor[] =
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* monitor */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* monitor */
static op_implicit_list_t list_mwait[] = static op_implicit_list_t list_mwait[] =
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* mwait */ {{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* mwait */
op_implicit_list_t *op_implicit_list[] = { op_implicit_list_t *op_implicit_list[] = {
/* This is a list of implicit operands which are read/written by /* This is a list of implicit operands which are read/written by
* various x86 instructions. Note that modifications to the stack * various x86 instructions. Note that modifications to the stack
* register are mentioned here, but that additional information on * register are mentioned here, but that additional information on
* the effect an instruction has on the stack is contained in the * 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 * x86_insn_t 'stack_mod' and 'stack_mod_val' fields. Use of the
* eflags register, i.e. setting, clearing, and testing flags, is * eflags register, i.e. setting, clearing, and testing flags, is
* not recorded here but rather in the flags_set and flags_tested * not recorded here but rather in the flags_set and flags_tested
* fields of the x86_insn_t.*/ * fields of the x86_insn_t.*/
NULL, NULL,
list_aaa, list_aad, list_call, list_cbw, /* 1 - 4 */ list_aaa, list_aad, list_call, list_cbw, /* 1 - 4 */
list_cwde, list_clts, list_cmpxchg, list_cmpxchgb, /* 5 - 8 */ list_cwde, list_clts, list_cmpxchg, list_cmpxchgb, /* 5 - 8 */
list_cmpxchg8b, list_cpuid, list_cwd, list_daa, /* 9 - 12 */ list_cmpxchg8b, list_cpuid, list_cwd, list_daa, /* 9 - 12 */
list_idiv, list_div, list_enter, list_f2xm1, /* 13 - 16 */ list_idiv, list_div, list_enter, list_f2xm1, /* 13 - 16 */
list_fcom, list_fpatan, list_fprem, list_faddp, /* 17 - 20 */ list_fcom, list_fpatan, list_fprem, list_faddp, /* 17 - 20 */
list_fucompp, list_imul, list_mul, list_lahf, /* 21 - 24 */ list_fucompp, list_imul, list_mul, list_lahf, /* 21 - 24 */
list_ldmxcsr, list_leave, list_lgdt, list_lidt, /* 25 - 28 */ list_ldmxcsr, list_leave, list_lgdt, list_lidt, /* 25 - 28 */
list_lldt, list_lmsw, list_loop, list_ltr, /* 29 - 32 */ list_lldt, list_lmsw, list_loop, list_ltr, /* 29 - 32 */
list_pop, list_popad, list_popfd, list_pushad, /* 33 - 36 */ list_pop, list_popad, list_popfd, list_pushad, /* 33 - 36 */
list_pushfd, list_rdmsr, list_rdpmc, list_rdtsc, /* 37 - 40 */ list_pushfd, list_rdmsr, list_rdpmc, list_rdtsc, /* 37 - 40 */
/* NOTE: 'REP' is a hack since it is a prefix: if its position /* 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 */ * in the table changes, then change IDX_IMPLICIT_REP in the .h */
list_rep, list_rsm, list_sahf, list_sgdt, /* 41 - 44 */ list_rep, list_rsm, list_sahf, list_sgdt, /* 41 - 44 */
list_sidt, list_sldt, list_smsw, list_stmxcsr, /* 45 - 48 */ list_sidt, list_sldt, list_smsw, list_stmxcsr, /* 45 - 48 */
list_str, list_sysenter, list_sysexit, list_wrmsr, /* 49 - 52 */ list_str, list_sysenter, list_sysexit, list_wrmsr, /* 49 - 52 */
list_xlat, list_monitor, list_mwait, /* 53 - 55*/ list_xlat, list_monitor, list_mwait, /* 53 - 55*/
NULL /* end of list */ NULL /* end of list */
}; };
#define LAST_IMPL_IDX 55 #define LAST_IMPL_IDX 55
static void handle_impl_reg( x86_op_t *op, uint32_t val ) { static void handle_impl_reg( x86_op_t *op, uint32_t val ) {
x86_reg_t *reg = &op->data.reg; x86_reg_t *reg = &op->data.reg;
op->type = op_register; op->type = op_register;
ia32_handle_register( reg, (unsigned int) val ); ia32_handle_register( reg, (unsigned int) val );
switch (reg->size) { switch (reg->size) {
case 1: case 1:
op->datatype = op_byte; break; op->datatype = op_byte; break;
case 2: case 2:
op->datatype = op_word; break; op->datatype = op_word; break;
case 4: case 4:
op->datatype = op_dword; break; op->datatype = op_dword; break;
case 8: case 8:
op->datatype = op_qword; break; op->datatype = op_qword; break;
case 10: case 10:
op->datatype = op_extreal; break; op->datatype = op_extreal; break;
case 16: case 16:
op->datatype = op_dqword; break; op->datatype = op_dqword; break;
} }
return; return;
} }
/* 'impl_idx' is the value from the opcode table: between 1 and LAST_IMPL_IDX */ /* 'impl_idx' is the value from the opcode table: between 1 and LAST_IMPL_IDX */
/* returns number of operands added */ /* returns number of operands added */
unsigned int Ia32_Decoder::ia32_insn_implicit_ops( unsigned int impl_idx ) { unsigned int Ia32_Decoder::ia32_insn_implicit_ops( unsigned int impl_idx ) {
op_implicit_list_t *list; op_implicit_list_t *list;
x86_oplist_t * existing=0; x86_oplist_t * existing=0;
x86_op_t *op; x86_op_t *op;
unsigned int num = 0; unsigned int num = 0;
if (! impl_idx || impl_idx > LAST_IMPL_IDX ) { if (! impl_idx || impl_idx > LAST_IMPL_IDX ) {
return 0; return 0;
} }
for ( list = op_implicit_list[impl_idx]; list->type; list++, num++ ) { for ( list = op_implicit_list[impl_idx]; list->type; list++, num++ ) {
enum x86_op_access access = (enum x86_op_access) OP_PERM(list->type); enum x86_op_access access = (enum x86_op_access) OP_PERM(list->type);
x86_op_flags flags; x86_op_flags flags;
flags.whole = (OP_FLAGS(list->type) >> 12); flags.whole = (OP_FLAGS(list->type) >> 12);
op = NULL; op = NULL;
/* In some cases (MUL), EAX is an implicit operand hardcoded in /* In some cases (MUL), EAX is an implicit operand hardcoded in
* the instruction without being explicitly listed in assembly. * the instruction without being explicitly listed in assembly.
* For this situation, find the hardcoded operand and add the * For this situation, find the hardcoded operand and add the
* implied flag rather than adding a new implicit operand. */ * implied flag rather than adding a new implicit operand. */
existing=0; existing=0;
if (ia32_true_register_id(list->operand) == REG_DWORD_OFFSET) { if (ia32_true_register_id(list->operand) == REG_DWORD_OFFSET) {
for ( existing = m_decoded->operands; existing; existing = existing->next ) { for ( existing = m_decoded->operands; existing; existing = existing->next ) {
if (existing->op.type == op_register && if (existing->op.type == op_register &&
existing->op.data.reg.id == list->operand) { existing->op.data.reg.id == list->operand) {
op = &existing->op; op = &existing->op;
break; break;
} }
} }
} }
if (!op) { if (!op) {
op = m_decoded->x86_operand_new(); op = m_decoded->x86_operand_new();
/* all implicit operands are registers */ /* all implicit operands are registers */
handle_impl_reg( op, list->operand ); handle_impl_reg( op, list->operand );
/* decrement the 'explicit count' incremented by default in /* decrement the 'explicit count' incremented by default in
* x86_operand_new */ * x86_operand_new */
m_decoded->explicit_count = m_decoded->explicit_count -1; m_decoded->explicit_count = m_decoded->explicit_count -1;
} }
if (!op) { if (!op) {
return num; /* gah! return early */ return num; /* gah! return early */
} }
op->access = x86_op_access((int)op->access | (int)access); op->access = x86_op_access((int)op->access | (int)access);
op->flags.whole |= flags.whole; op->flags.whole |= flags.whole;
op->flags.op_implied=true; op->flags.op_implied=true;
} }
return num; return num;
} }

View File

@ -543,8 +543,7 @@ size_t Ia32_Decoder::handle_insn_suffix( unsigned char *buf, size_t buf_len,
ia32_insn_t *sfx_insn; ia32_insn_t *sfx_insn;
size_t size; size_t size;
unsigned int prefixes = 0; 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, size = ia32_table_lookup( buf, buf_len, raw_insn->table, &sfx_insn,
&prefixes ); &prefixes );
if (size == INVALID_INSN || sfx_insn->mnem_flag == INS_INVALID ) { if (size == INVALID_INSN || sfx_insn->mnem_flag == INS_INVALID ) {

View File

@ -9,8 +9,8 @@ extern ia32_table_desc_t *ia32_tables;
extern ia32_settings_t ia32_settings; extern ia32_settings_t ia32_settings;
extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len, extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
unsigned int table, ia32_insn_t **raw_insn, unsigned int table, ia32_insn_t **raw_insn,
unsigned int *prefixes ); unsigned int *prefixes );
/* -------------------------------- ModR/M, SIB */ /* -------------------------------- ModR/M, SIB */
@ -65,249 +65,249 @@ static void byte_decode(unsigned char b, struct modRM_byte *modrm) {
#else #else
static inline void byte_decode(unsigned char b, struct modRM_byte *modrm) { static inline void byte_decode(unsigned char b, struct modRM_byte *modrm) {
#endif #endif
/* generic bitfield-packing routine */ /* generic bitfield-packing routine */
modrm->mod = b >> 6; /* top 2 bits */ modrm->mod = b >> 6; /* top 2 bits */
modrm->reg = (b & 56) >> 3; /* middle 3 bits */ modrm->reg = (b & 56) >> 3; /* middle 3 bits */
modrm->rm = b & 7; /* bottom 3 bits */ modrm->rm = b & 7; /* bottom 3 bits */
} }
static int ia32_invariant_modrm( unsigned char *in, unsigned char *out, static int ia32_invariant_modrm( unsigned char *in, unsigned char *out,
unsigned int mode_16, x86_invariant_op_t *op) { unsigned int mode_16, x86_invariant_op_t *op) {
struct modRM_byte modrm; struct modRM_byte modrm;
struct SIB_byte sib; struct SIB_byte sib;
unsigned char *c, *cin; unsigned char *c, *cin;
unsigned short *s; unsigned short *s;
unsigned int *i; unsigned int *i;
int size = 0; /* modrm byte is already counted */ 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 */ out[0] = in[0]; /* save modrm byte */
cin = &in[1]; cin = &in[1];
c = &out[1]; c = &out[1];
s = (unsigned short *)&out[1]; s = (unsigned short *)&out[1];
i = (unsigned int *)&out[1]; i = (unsigned int *)&out[1];
op->type = op_expression; op->type = op_expression;
op->flags.op_pointer = true; //|= op_pointer; op->flags.op_pointer = true; //|= op_pointer;
if ( ! mode_16 && modrm.rm == MODRM_RM_SIB && if ( ! mode_16 && modrm.rm == MODRM_RM_SIB &&
modrm.mod != MODRM_MOD_NOEA ) { modrm.mod != MODRM_MOD_NOEA ) {
size ++; size ++;
byte_decode(*cin, (struct modRM_byte *)(void*)&sib); byte_decode(*cin, (struct modRM_byte *)(void*)&sib);
out[1] = in[1]; /* save sib byte */ out[1] = in[1]; /* save sib byte */
cin = &in[2]; cin = &in[2];
c = &out[2]; c = &out[2];
s = (unsigned short *)&out[2]; s = (unsigned short *)&out[2];
i = (unsigned int *)&out[2]; i = (unsigned int *)&out[2];
if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) { if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) {
/* disp 32 is variant! */ /* disp 32 is variant! */
memset( i, X86_WILDCARD_BYTE, 4 ); memset( i, X86_WILDCARD_BYTE, 4 );
size += 4; size += 4;
} }
} }
if (! modrm.mod && modrm.rm == 101) { if (! modrm.mod && modrm.rm == 101) {
if ( mode_16 ) { /* straight RVA in disp */ if ( mode_16 ) { /* straight RVA in disp */
memset( s, X86_WILDCARD_BYTE, 2 ); memset( s, X86_WILDCARD_BYTE, 2 );
size += 2; size += 2;
} else { } else {
memset( i, X86_WILDCARD_BYTE, 2 ); memset( i, X86_WILDCARD_BYTE, 2 );
size += 4; size += 4;
} }
} else if (modrm.mod && modrm.mod < 3) { } else if (modrm.mod && modrm.mod < 3) {
if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */ if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */
*c = *cin; *c = *cin;
size += 1; size += 1;
} else if ( mode_16 ) { } else if ( mode_16 ) {
*s = (* ((unsigned short *) cin)); *s = (* ((unsigned short *) cin));
size += 2; size += 2;
} else { } else {
*i = (*((unsigned int *) cin)); *i = (*((unsigned int *) cin));
size += 4; size += 4;
} }
} else if ( modrm.mod == 3 ) { } else if ( modrm.mod == 3 ) {
op->type = op_register; op->type = op_register;
op->flags.op_pointer = false;// &= ~op_pointer; op->flags.op_pointer = false;// &= ~op_pointer;
} }
return (size); return (size);
} }
static int ia32_decode_invariant( unsigned char *buf, size_t /*buf_len*/, static int ia32_decode_invariant( unsigned char *buf, size_t /*buf_len*/,
ia32_insn_t *t, unsigned char *out, ia32_insn_t *t, unsigned char *out,
unsigned int prefixes, x86_invariant_t *inv) { unsigned int prefixes, x86_invariant_t *inv) {
unsigned int addr_size, op_size, mode_16; unsigned int addr_size, op_size, mode_16;
unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag }; unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag };
int x, type, bytes = 0, size = 0, modrm = 0; int x, type, bytes = 0, size = 0, modrm = 0;
/* set addressing mode */ /* set addressing mode */
if (ia32_settings.options & opt_16_bit) { if (ia32_settings.options & opt_16_bit) {
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2; op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2;
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2; addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2;
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1; mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1;
} else { } else {
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4; op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4;
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4; addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4;
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0; mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0;
} }
for (x = 0; x < 3; x++) { for (x = 0; x < 3; x++) {
inv->operands[x].access = (enum x86_op_access) OP_PERM(op_flags[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); inv->operands[x].flags.whole = (OP_FLAGS(op_flags[x]) >> 12);
//(enum x86_op_flags) (OP_FLAGS(op_flags[x]) >> 12); //(enum x86_op_flags) (OP_FLAGS(op_flags[x]) >> 12);
switch (op_flags[x] & OPTYPE_MASK) { switch (op_flags[x] & OPTYPE_MASK) {
case OPTYPE_c: case OPTYPE_c:
size = (op_size == 4) ? 2 : 1; size = (op_size == 4) ? 2 : 1;
break; break;
case OPTYPE_a: case OPTYPE_v: case OPTYPE_a: case OPTYPE_v:
size = (op_size == 4) ? 4 : 2; size = (op_size == 4) ? 4 : 2;
break; break;
case OPTYPE_p: case OPTYPE_p:
size = (op_size == 4) ? 6 : 4; size = (op_size == 4) ? 6 : 4;
break; break;
case OPTYPE_b: case OPTYPE_b:
size = 1; size = 1;
break; break;
case OPTYPE_w: case OPTYPE_w:
size = 2; size = 2;
break; break;
case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd: case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd:
case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv: case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv:
case OPTYPE_si: case OPTYPE_fx: case OPTYPE_si: case OPTYPE_fx:
size = 4; size = 4;
break; break;
case OPTYPE_s: case OPTYPE_s:
size = 6; size = 6;
break; break;
case OPTYPE_q: case OPTYPE_pi: case OPTYPE_q: case OPTYPE_pi:
size = 8; size = 8;
break; break;
case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss: case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss:
case OPTYPE_pd: case OPTYPE_sd: case OPTYPE_pd: case OPTYPE_sd:
size = 16; size = 16;
break; break;
case OPTYPE_m: case OPTYPE_m:
size = (addr_size == 4) ? 4 : 2; size = (addr_size == 4) ? 4 : 2;
break; break;
default: default:
break; break;
} }
type = op_flags[x] & ADDRMETH_MASK; type = op_flags[x] & ADDRMETH_MASK;
switch (type) { switch (type) {
case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q: case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q:
case ADDRMETH_R: case ADDRMETH_W: case ADDRMETH_R: case ADDRMETH_W:
modrm = 1; modrm = 1;
bytes += ia32_invariant_modrm( buf, out, bytes += ia32_invariant_modrm( buf, out,
mode_16, &inv->operands[x]); mode_16, &inv->operands[x]);
break; break;
case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G: case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G:
case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T: case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T:
case ADDRMETH_V: case ADDRMETH_V:
inv->operands[x].type = op_register; inv->operands[x].type = op_register;
modrm = 1; modrm = 1;
break; break;
case ADDRMETH_A: case ADDRMETH_O: case ADDRMETH_A: case ADDRMETH_O:
/* pad with xF4's */ /* pad with xF4's */
memset( &out[bytes + modrm], X86_WILDCARD_BYTE, memset( &out[bytes + modrm], X86_WILDCARD_BYTE,
size ); size );
bytes += size; bytes += size;
inv->operands[x].type = op_offset; inv->operands[x].type = op_offset;
if ( type == ADDRMETH_O ) { if ( type == ADDRMETH_O ) {
inv->operands[x].flags.op_signed = true; inv->operands[x].flags.op_signed = true;
inv->operands[x].flags.op_pointer = true; inv->operands[x].flags.op_pointer = true;
} }
break; break;
case ADDRMETH_I: case ADDRMETH_J: case ADDRMETH_I: case ADDRMETH_J:
/* grab imm value */ /* grab imm value */
if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) { if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) {
/* assume this is an address */ /* assume this is an address */
memset( &out[bytes + modrm], X86_WILDCARD_BYTE, size ); memset( &out[bytes + modrm], X86_WILDCARD_BYTE, size );
} else { } else {
memcpy( &out[bytes + modrm], &buf[bytes + modrm], size ); memcpy( &out[bytes + modrm], &buf[bytes + modrm], size );
} }
bytes += size; bytes += size;
if ( type == ADDRMETH_J ) { if ( type == ADDRMETH_J ) {
if ( size == 1 ) { if ( size == 1 ) {
inv->operands[x].type = op_relative_near; inv->operands[x].type = op_relative_near;
} else { } else {
inv->operands[x].type = op_relative_far; inv->operands[x].type = op_relative_far;
} }
inv->operands[x].flags.op_signed=true; inv->operands[x].flags.op_signed=true;
} else { } else {
inv->operands[x].type = op_immediate; inv->operands[x].type = op_immediate;
} }
break; break;
case ADDRMETH_F: case ADDRMETH_F:
inv->operands[x].type = op_register; inv->operands[x].type = op_register;
break; break;
case ADDRMETH_X: case ADDRMETH_X:
inv->operands[x].flags.op_signed=true; inv->operands[x].flags.op_signed=true;
inv->operands[x].flags.op_pointer=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_seg=(x86_op_flags::op_ds_seg)>>8;
inv->operands[x].flags.op_string=true; inv->operands[x].flags.op_string=true;
break; break;
case ADDRMETH_Y: case ADDRMETH_Y:
inv->operands[x].flags.op_signed=true; inv->operands[x].flags.op_signed=true;
inv->operands[x].flags.op_pointer=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_seg=x86_op_flags::op_es_seg>>8;
inv->operands[x].flags.op_string=true; inv->operands[x].flags.op_string=true;
break; break;
case ADDRMETH_RR: case ADDRMETH_RR:
inv->operands[x].type = op_register; inv->operands[x].type = op_register;
break; break;
case ADDRMETH_II: case ADDRMETH_II:
inv->operands[x].type = op_immediate; inv->operands[x].type = op_immediate;
break; break;
default: default:
inv->operands[x].type = op_unused; inv->operands[x].type = op_unused;
break; break;
} }
} }
return (bytes + modrm); return (bytes + modrm);
} }
size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len, size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len,
x86_invariant_t *inv ) { x86_invariant_t *inv ) {
ia32_insn_t *raw_insn = NULL; ia32_insn_t *raw_insn = NULL;
unsigned int prefixes=0; unsigned int prefixes=0;
unsigned int type; unsigned int type;
size_t size; size_t size;
/* Perform recursive table lookup starting with main table (0) */ /* Perform recursive table lookup starting with main table (0) */
size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes ); size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes );
if ( size == INVALID_INSN || size > buf_len ) { if ( size == INVALID_INSN || size > buf_len ) {
/* TODO: set errno */ /* TODO: set errno */
return 0; return 0;
} }
/* copy opcode bytes to buffer */ /* copy opcode bytes to buffer */
memcpy( inv->bytes, buf, size ); memcpy( inv->bytes, buf, size );
/* set mnemonic type and group */ /* set mnemonic type and group */
type = raw_insn->mnem_flag & ~INS_FLAG_MASK; type = raw_insn->mnem_flag & ~INS_FLAG_MASK;
inv->group = (x86_insn_t::x86_insn_group) ((INS_GROUP(type)) >> 12); inv->group = (x86_insn_t::x86_insn_group) ((INS_GROUP(type)) >> 12);
inv->type = (enum x86_insn_type) INS_TYPE(type); inv->type = (enum x86_insn_type) INS_TYPE(type);
/* handle operands */ /* handle operands */
size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn, size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn,
&buf[size - 1], prefixes, inv ); &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 ) { size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) {
x86_invariant_t inv; x86_invariant_t inv;
memset(&inv,0,sizeof(x86_invariant_t)); memset(&inv,0,sizeof(x86_invariant_t));
return( ia32_disasm_invariant( buf, buf_len, &inv ) ); return( ia32_disasm_invariant( buf, buf_len, &inv ) );
} }

View File

@ -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_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_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 }, { 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_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_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_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_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, "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 }, { 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_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_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_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, "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, "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_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_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_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_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, "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, "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_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, "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, "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_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 }
}; };

View File

@ -31,204 +31,204 @@
* of the MMX registers, so this aliasing is not 100% accurate. * of the MMX registers, so this aliasing is not 100% accurate.
* */ * */
static struct { static struct {
unsigned char alias; /* id of register this is an alias for */ unsigned char alias; /* id of register this is an alias for */
unsigned char shift; /* # of bits register must be shifted */ unsigned char shift; /* # of bits register must be shifted */
} ia32_reg_aliases[] = { } ia32_reg_aliases[] = {
{ 0,0 }, { 0,0 },
{ REG_DWORD_OFFSET, 0 }, /* al : 1 */ { REG_DWORD_OFFSET, 0 }, /* al : 1 */
{ REG_DWORD_OFFSET, 8 }, /* ah : 2 */ { REG_DWORD_OFFSET, 8 }, /* ah : 2 */
{ REG_DWORD_OFFSET, 0 }, /* ax : 3 */ { REG_DWORD_OFFSET, 0 }, /* ax : 3 */
{ REG_DWORD_OFFSET + 1, 0 }, /* cl : 4 */ { REG_DWORD_OFFSET + 1, 0 }, /* cl : 4 */
{ REG_DWORD_OFFSET + 1, 8 }, /* ch : 5 */ { REG_DWORD_OFFSET + 1, 8 }, /* ch : 5 */
{ REG_DWORD_OFFSET + 1, 0 }, /* cx : 6 */ { REG_DWORD_OFFSET + 1, 0 }, /* cx : 6 */
{ REG_DWORD_OFFSET + 2, 0 }, /* dl : 7 */ { REG_DWORD_OFFSET + 2, 0 }, /* dl : 7 */
{ REG_DWORD_OFFSET + 2, 8 }, /* dh : 8 */ { REG_DWORD_OFFSET + 2, 8 }, /* dh : 8 */
{ REG_DWORD_OFFSET + 2, 0 }, /* dx : 9 */ { REG_DWORD_OFFSET + 2, 0 }, /* dx : 9 */
{ REG_DWORD_OFFSET + 3, 0 }, /* bl : 10 */ { REG_DWORD_OFFSET + 3, 0 }, /* bl : 10 */
{ REG_DWORD_OFFSET + 3, 8 }, /* bh : 11 */ { REG_DWORD_OFFSET + 3, 8 }, /* bh : 11 */
{ REG_DWORD_OFFSET + 3, 0 }, /* bx : 12 */ { REG_DWORD_OFFSET + 3, 0 }, /* bx : 12 */
{ REG_DWORD_OFFSET + 4, 0 }, /* sp : 13 */ { REG_DWORD_OFFSET + 4, 0 }, /* sp : 13 */
{ REG_DWORD_OFFSET + 5, 0 }, /* bp : 14 */ { REG_DWORD_OFFSET + 5, 0 }, /* bp : 14 */
{ REG_DWORD_OFFSET + 6, 0 }, /* si : 15 */ { REG_DWORD_OFFSET + 6, 0 }, /* si : 15 */
{ REG_DWORD_OFFSET + 7, 0 }, /* di : 16 */ { REG_DWORD_OFFSET + 7, 0 }, /* di : 16 */
{ REG_EIP_INDEX, 0 }, /* ip : 17 */ { REG_EIP_INDEX, 0 }, /* ip : 17 */
{ REG_FPU_OFFSET, 0 }, /* mm0 : 18 */ { REG_FPU_OFFSET, 0 }, /* mm0 : 18 */
{ REG_FPU_OFFSET + 1, 0 }, /* mm1 : 19 */ { REG_FPU_OFFSET + 1, 0 }, /* mm1 : 19 */
{ REG_FPU_OFFSET + 2, 0 }, /* mm2 : 20 */ { REG_FPU_OFFSET + 2, 0 }, /* mm2 : 20 */
{ REG_FPU_OFFSET + 3, 0 }, /* mm3 : 21 */ { REG_FPU_OFFSET + 3, 0 }, /* mm3 : 21 */
{ REG_FPU_OFFSET + 4, 0 }, /* mm4 : 22 */ { REG_FPU_OFFSET + 4, 0 }, /* mm4 : 22 */
{ REG_FPU_OFFSET + 5, 0 }, /* mm5 : 23 */ { REG_FPU_OFFSET + 5, 0 }, /* mm5 : 23 */
{ REG_FPU_OFFSET + 6, 0 }, /* mm6 : 24 */ { REG_FPU_OFFSET + 6, 0 }, /* mm6 : 24 */
{ REG_FPU_OFFSET + 7, 0 } /* mm7 : 25 */ { REG_FPU_OFFSET + 7, 0 } /* mm7 : 25 */
}; };
/* REGISTER TABLE: size, type, and name of every register in the /* REGISTER TABLE: size, type, and name of every register in the
* CPU. Does not include MSRs since the are, after all, * CPU. Does not include MSRs since the are, after all,
* model specific. */ * model specific. */
static struct { static struct {
unsigned int size; unsigned int size;
enum x86_reg_type type; enum x86_reg_type type;
unsigned int alias; unsigned int alias;
char mnemonic[8]; char mnemonic[8];
} ia32_reg_table[NUM_X86_REGS + 2] = { } ia32_reg_table[NUM_X86_REGS + 2] = {
{ 0, reg_undef, 0, "" }, { 0, reg_undef, 0, "" },
/* REG_DWORD_OFFSET */ /* REG_DWORD_OFFSET */
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_ret), 0, "eax" }, { 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, (x86_reg_type)(reg_gen | reg_count), 0, "ecx" },
{ REG_DWORD_SIZE, reg_gen, 0, "edx" }, { REG_DWORD_SIZE, reg_gen, 0, "edx" },
{ REG_DWORD_SIZE, reg_gen, 0, "ebx" }, { REG_DWORD_SIZE, reg_gen, 0, "ebx" },
/* REG_ESP_INDEX */ /* REG_ESP_INDEX */
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_sp), 0, "esp" }, { 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_fp), 0, "ebp" },
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_src), 0, "esi" }, { 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_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_ret), 3, "ax" },
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_count), 6, "cx" }, { REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_count), 6, "cx" },
{ REG_WORD_SIZE, reg_gen, 9, "dx" }, { REG_WORD_SIZE, reg_gen, 9, "dx" },
{ REG_WORD_SIZE, reg_gen, 12, "bx" }, { 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_sp), 13, "sp" },
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_fp), 14, "bp" }, { 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_src), 15, "si" },
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_dest), 16, "di" }, { REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_dest), 16, "di" },
/* REG_BYTE_OFFSET */ /* REG_BYTE_OFFSET */
{ REG_BYTE_SIZE, reg_gen, 1, "al" }, { REG_BYTE_SIZE, reg_gen, 1, "al" },
{ REG_BYTE_SIZE, reg_gen, 4, "cl" }, { REG_BYTE_SIZE, reg_gen, 4, "cl" },
{ REG_BYTE_SIZE, reg_gen, 7, "dl" }, { REG_BYTE_SIZE, reg_gen, 7, "dl" },
{ REG_BYTE_SIZE, reg_gen, 10, "bl" }, { REG_BYTE_SIZE, reg_gen, 10, "bl" },
{ REG_BYTE_SIZE, reg_gen, 2, "ah" }, { REG_BYTE_SIZE, reg_gen, 2, "ah" },
{ REG_BYTE_SIZE, reg_gen, 5, "ch" }, { REG_BYTE_SIZE, reg_gen, 5, "ch" },
{ REG_BYTE_SIZE, reg_gen, 8, "dh" }, { REG_BYTE_SIZE, reg_gen, 8, "dh" },
{ REG_BYTE_SIZE, reg_gen, 11, "bh" }, { REG_BYTE_SIZE, reg_gen, 11, "bh" },
/* REG_MMX_OFFSET */ /* REG_MMX_OFFSET */
{ REG_MMX_SIZE, reg_simd, 18, "mm0" }, { REG_MMX_SIZE, reg_simd, 18, "mm0" },
{ REG_MMX_SIZE, reg_simd, 19, "mm1" }, { REG_MMX_SIZE, reg_simd, 19, "mm1" },
{ REG_MMX_SIZE, reg_simd, 20, "mm2" }, { REG_MMX_SIZE, reg_simd, 20, "mm2" },
{ REG_MMX_SIZE, reg_simd, 21, "mm3" }, { REG_MMX_SIZE, reg_simd, 21, "mm3" },
{ REG_MMX_SIZE, reg_simd, 22, "mm4" }, { REG_MMX_SIZE, reg_simd, 22, "mm4" },
{ REG_MMX_SIZE, reg_simd, 23, "mm5" }, { REG_MMX_SIZE, reg_simd, 23, "mm5" },
{ REG_MMX_SIZE, reg_simd, 24, "mm6" }, { REG_MMX_SIZE, reg_simd, 24, "mm6" },
{ REG_MMX_SIZE, reg_simd, 25, "mm7" }, { REG_MMX_SIZE, reg_simd, 25, "mm7" },
/* REG_SIMD_OFFSET */ /* REG_SIMD_OFFSET */
{ REG_SIMD_SIZE, reg_simd, 0, "xmm0" }, { REG_SIMD_SIZE, reg_simd, 0, "xmm0" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm1" }, { REG_SIMD_SIZE, reg_simd, 0, "xmm1" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm2" }, { REG_SIMD_SIZE, reg_simd, 0, "xmm2" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm3" }, { REG_SIMD_SIZE, reg_simd, 0, "xmm3" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm4" }, { REG_SIMD_SIZE, reg_simd, 0, "xmm4" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm5" }, { REG_SIMD_SIZE, reg_simd, 0, "xmm5" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm6" }, { REG_SIMD_SIZE, reg_simd, 0, "xmm6" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm7" }, { REG_SIMD_SIZE, reg_simd, 0, "xmm7" },
/* REG_DEBUG_OFFSET */ /* REG_DEBUG_OFFSET */
{ REG_DEBUG_SIZE, reg_sys, 0, "dr0" }, { REG_DEBUG_SIZE, reg_sys, 0, "dr0" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr1" }, { REG_DEBUG_SIZE, reg_sys, 0, "dr1" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr2" }, { REG_DEBUG_SIZE, reg_sys, 0, "dr2" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr3" }, { REG_DEBUG_SIZE, reg_sys, 0, "dr3" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr4" }, { REG_DEBUG_SIZE, reg_sys, 0, "dr4" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr5" }, { REG_DEBUG_SIZE, reg_sys, 0, "dr5" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr6" }, { REG_DEBUG_SIZE, reg_sys, 0, "dr6" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr7" }, { REG_DEBUG_SIZE, reg_sys, 0, "dr7" },
/* REG_CTRL_OFFSET */ /* REG_CTRL_OFFSET */
{ REG_CTRL_SIZE, reg_sys, 0, "cr0" }, { REG_CTRL_SIZE, reg_sys, 0, "cr0" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr1" }, { REG_CTRL_SIZE, reg_sys, 0, "cr1" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr2" }, { REG_CTRL_SIZE, reg_sys, 0, "cr2" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr3" }, { REG_CTRL_SIZE, reg_sys, 0, "cr3" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr4" }, { REG_CTRL_SIZE, reg_sys, 0, "cr4" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr5" }, { REG_CTRL_SIZE, reg_sys, 0, "cr5" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr6" }, { REG_CTRL_SIZE, reg_sys, 0, "cr6" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr7" }, { REG_CTRL_SIZE, reg_sys, 0, "cr7" },
/* REG_TEST_OFFSET */ /* REG_TEST_OFFSET */
{ REG_TEST_SIZE, reg_sys, 0, "tr0" }, { REG_TEST_SIZE, reg_sys, 0, "tr0" },
{ REG_TEST_SIZE, reg_sys, 0, "tr1" }, { REG_TEST_SIZE, reg_sys, 0, "tr1" },
{ REG_TEST_SIZE, reg_sys, 0, "tr2" }, { REG_TEST_SIZE, reg_sys, 0, "tr2" },
{ REG_TEST_SIZE, reg_sys, 0, "tr3" }, { REG_TEST_SIZE, reg_sys, 0, "tr3" },
{ REG_TEST_SIZE, reg_sys, 0, "tr4" }, { REG_TEST_SIZE, reg_sys, 0, "tr4" },
{ REG_TEST_SIZE, reg_sys, 0, "tr5" }, { REG_TEST_SIZE, reg_sys, 0, "tr5" },
{ REG_TEST_SIZE, reg_sys, 0, "tr6" }, { REG_TEST_SIZE, reg_sys, 0, "tr6" },
{ REG_TEST_SIZE, reg_sys, 0, "tr7" }, { REG_TEST_SIZE, reg_sys, 0, "tr7" },
/* REG_SEG_OFFSET */ /* REG_SEG_OFFSET */
{ REG_SEG_SIZE, reg_seg, 0, "es" }, { REG_SEG_SIZE, reg_seg, 0, "es" },
{ REG_SEG_SIZE, reg_seg, 0, "cs" }, { REG_SEG_SIZE, reg_seg, 0, "cs" },
{ REG_SEG_SIZE, reg_seg, 0, "ss" }, { REG_SEG_SIZE, reg_seg, 0, "ss" },
{ REG_SEG_SIZE, reg_seg, 0, "ds" }, { REG_SEG_SIZE, reg_seg, 0, "ds" },
{ REG_SEG_SIZE, reg_seg, 0, "fs" }, { REG_SEG_SIZE, reg_seg, 0, "fs" },
{ REG_SEG_SIZE, reg_seg, 0, "gs" }, { REG_SEG_SIZE, reg_seg, 0, "gs" },
/* REG_LDTR_INDEX */ /* REG_LDTR_INDEX */
{ REG_DWORD_SIZE, reg_sys, 0, "ldtr" }, { REG_DWORD_SIZE, reg_sys, 0, "ldtr" },
/* REG_GDTR_INDEX */ /* REG_GDTR_INDEX */
{ REG_DWORD_SIZE, reg_sys, 0, "gdtr" }, { REG_DWORD_SIZE, reg_sys, 0, "gdtr" },
/* REG_FPU_OFFSET */ /* REG_FPU_OFFSET */
{ REG_FPU_SIZE, reg_fpu, 0, "st(0)" }, { REG_FPU_SIZE, reg_fpu, 0, "st(0)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(1)" }, { REG_FPU_SIZE, reg_fpu, 0, "st(1)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(2)" }, { REG_FPU_SIZE, reg_fpu, 0, "st(2)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(3)" }, { REG_FPU_SIZE, reg_fpu, 0, "st(3)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(4)" }, { REG_FPU_SIZE, reg_fpu, 0, "st(4)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(5)" }, { REG_FPU_SIZE, reg_fpu, 0, "st(5)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(6)" }, { REG_FPU_SIZE, reg_fpu, 0, "st(6)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(7)" }, { REG_FPU_SIZE, reg_fpu, 0, "st(7)" },
/* REG_FLAGS_INDEX : 81 */ /* REG_FLAGS_INDEX : 81 */
{ REG_FLAGS_SIZE, reg_cond, 0, "eflags" }, { REG_FLAGS_SIZE, reg_cond, 0, "eflags" },
/* REG_FPCTRL_INDEX : 82*/ /* REG_FPCTRL_INDEX : 82*/
{ REG_FPCTRL_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fpctrl" }, { 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_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_FPTAG_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fptag" },
/* REG_EIP_INDEX : 85 */ /* REG_EIP_INDEX : 85 */
{ REG_EIP_SIZE, reg_pc, 0, "eip" }, { REG_EIP_SIZE, reg_pc, 0, "eip" },
/* REG_IP_INDEX : 86 */ /* REG_IP_INDEX : 86 */
{ REG_IP_SIZE, reg_pc, 17, "ip" }, { REG_IP_SIZE, reg_pc, 17, "ip" },
/* REG_IDTR_INDEX : 87 */ /* REG_IDTR_INDEX : 87 */
{ REG_DWORD_SIZE, reg_sys, 0, "idtr" }, { REG_DWORD_SIZE, reg_sys, 0, "idtr" },
/* REG_MXCSG_INDEX : SSE Control Reg : 88 */ /* REG_MXCSG_INDEX : SSE Control Reg : 88 */
{ REG_DWORD_SIZE, (x86_reg_type)(reg_sys | reg_simd), 0, "mxcsr" }, { REG_DWORD_SIZE, (x86_reg_type)(reg_sys | reg_simd), 0, "mxcsr" },
/* REG_TR_INDEX : Task Register : 89 */ /* REG_TR_INDEX : Task Register : 89 */
{ 16 + 64, reg_sys, 0, "tr" }, { 16 + 64, reg_sys, 0, "tr" },
/* REG_CSMSR_INDEX : SYSENTER_CS_MSR : 90 */ /* REG_CSMSR_INDEX : SYSENTER_CS_MSR : 90 */
{ REG_DWORD_SIZE, reg_sys, 0, "cs_msr" }, { REG_DWORD_SIZE, reg_sys, 0, "cs_msr" },
/* REG_ESPMSR_INDEX : SYSENTER_ESP_MSR : 91 */ /* REG_ESPMSR_INDEX : SYSENTER_ESP_MSR : 91 */
{ REG_DWORD_SIZE, reg_sys, 0, "esp_msr" }, { REG_DWORD_SIZE, reg_sys, 0, "esp_msr" },
/* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */ /* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */
{ REG_DWORD_SIZE, reg_sys, 0, "eip_msr" }, { REG_DWORD_SIZE, reg_sys, 0, "eip_msr" },
{ 0,reg_undef,0,{0} } { 0,reg_undef,0,"" }
}; };
static size_t sz_regtable = NUM_X86_REGS + 1; static size_t sz_regtable = NUM_X86_REGS + 1;
void ia32_handle_register( x86_reg_t *reg, size_t id ) { void ia32_handle_register( x86_reg_t *reg, size_t id ) {
unsigned int alias; unsigned int alias;
if (! id || id > sz_regtable ) { 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; 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 ia32_true_register_id( size_t id ) {
size_t reg; size_t reg;
if (! id || id > sz_regtable ) { if (! id || id > sz_regtable ) {
return 0; return 0;
} }
reg = id; reg = id;
if (ia32_reg_table[reg].alias) { if (ia32_reg_table[reg].alias) {
reg = ia32_reg_aliases[ia32_reg_table[reg].alias].alias; reg = ia32_reg_aliases[ia32_reg_table[reg].alias].alias;
} }
return reg; return reg;
} }

View File

@ -814,10 +814,9 @@ public:
* void x86_get_aliased_reg( x86_reg_t *alias_reg, x86_reg_t *output_reg ) * 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 * where 'alias_reg' is a reg operand and 'output_reg' is filled with the
* register that the operand is an alias for */ * register that the operand is an alias for */
/* //#define x86_get_aliased_reg( alias_reg, output_reg )
#define x86_get_aliased_reg( alias_reg, output_reg ) \ // x86_reg_from_id( alias_reg->alias, output_reg )
x86_reg_from_id( alias_reg->alias, output_reg )
*/
/* ================================== Invariant Instruction Representation */ /* ================================== Invariant Instruction Representation */
/* Invariant instructions are used for generating binary signatures; /* Invariant instructions are used for generating binary signatures;

View File

@ -9,8 +9,8 @@
#ifdef _MSC_VER #ifdef _MSC_VER
#define snprintf _snprintf #define snprintf _snprintf
#define inline __inline #define inline __inline
#endif #endif
void x86_insn_t::make_invalid(unsigned char *buf) 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 ); memcpy( bytes, buf, 1 );
} }
unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len, unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
uint32_t buf_rva, unsigned int offset, uint32_t buf_rva, unsigned int offset,
x86_insn_t *insn ){ x86_insn_t *insn ){
int len, size; int len, size;
unsigned char bytes[MAX_INSTRUCTION_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 */ * helps prevent buffer overruns at the end of a file */
memset( bytes, 0, MAX_INSTRUCTION_SIZE ); memset( bytes, 0, MAX_INSTRUCTION_SIZE );
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len : memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
MAX_INSTRUCTION_SIZE ); MAX_INSTRUCTION_SIZE );
/* actually do the disassembly */ /* actually do the disassembly */
/* TODO: allow switching when more disassemblers are added */ /* 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 X86_Disasm::x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
unsigned int offset, unsigned int len, unsigned int offset, unsigned int len,
DISASM_CALLBACK func, void *arg ) { DISASM_CALLBACK func, void *arg ) {
x86_insn_t insn; x86_insn_t insn;
unsigned int buf_len, size, count = 0, bytes = 0; unsigned int buf_len, size, count = 0, bytes = 0;
/* buf_len is implied by the arguments */ /* buf_len is implied by the arguments */
buf_len = len + offset; buf_len = len + offset;
while ( bytes < len ) { while ( bytes < len ) {
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes, size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
&insn ); &insn );
if ( size ) { if ( size ) {
/* invoke callback if it exists */ /* invoke callback if it exists */
if ( func ) { if ( func ) {
(*func)( &insn, arg ); (*func)( &insn, arg );
} }
bytes += size; bytes += size;
count ++; count ++;
} else { } else {
/* error */ /* error */
bytes++; /* try next byte */ bytes++; /* try next byte */
}
insn.x86_oplist_free();
} }
return( count ); insn.x86_oplist_free();
}
return( count );
} }
static inline int follow_insn_dest( x86_insn_t *insn ) { static inline int follow_insn_dest( x86_insn_t *insn ) {
if ( insn->type == insn_jmp || insn->type == insn_jcc || if ( insn->type == insn_jmp || insn->type == insn_jcc ||
insn->type == insn_call || insn->type == insn_callcc ) { insn->type == insn_call || insn->type == insn_callcc ) {
return(1); return(1);
} }
return(0); return(0);
} }
static inline int insn_doesnt_return( x86_insn_t *insn ) { 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 ){ static int32_t internal_resolver( x86_op_t *op, x86_insn_t *insn ){
int32_t next_addr = -1; int32_t next_addr = -1;
if ( x86_optype_is_address(op->type) ) { if ( x86_optype_is_address(op->type) ) {
next_addr = op->data.sdword; next_addr = op->data.sdword;
} else if ( op->type == op_relative_near ) { } else if ( op->type == op_relative_near ) {
next_addr = insn->addr + insn->size + op->data.relative_near; next_addr = insn->addr + insn->size + op->data.relative_near;
} else if ( op->type == op_relative_far ) { } else if ( op->type == op_relative_far ) {
next_addr = insn->addr + insn->size + op->data.relative_far; next_addr = insn->addr + insn->size + op->data.relative_far;
} }
return( next_addr ); return( next_addr );
} }
unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int buf_len, unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
uint32_t buf_rva, unsigned int offset, uint32_t buf_rva, unsigned int offset,
DISASM_CALLBACK func, void *arg, DISASM_CALLBACK func, void *arg,
DISASM_RESOLVER resolver, void *r_arg ){ DISASM_RESOLVER resolver, void *r_arg ){
x86_insn_t insn; x86_insn_t insn;
x86_op_t *op; x86_op_t *op;
int32_t next_addr; int32_t next_addr;
int32_t next_offset; int32_t next_offset;
unsigned int size, count = 0, bytes = 0, cont = 1; unsigned int size, count = 0, bytes = 0, cont = 1;
while ( cont && bytes < buf_len ) { while ( cont && bytes < buf_len ) {
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes, size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
&insn ); &insn );
if ( size ) { if ( size ) {
/* invoke callback if it exists */ /* invoke callback if it exists */
if ( func ) { if ( func ) {
(*func)( &insn, arg ); (*func)( &insn, arg );
} }
bytes += size; bytes += size;
count ++; count ++;
} else { } else {
/* error */ /* error */
bytes++; /* try next byte */ 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( );
} }
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 */ /* invariant instruction representation */
size_t x86_invariant_disasm( unsigned char *buf, int buf_len, size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
x86_invariant_t *inv ){ x86_invariant_t *inv ){
if (! buf || ! buf_len || ! inv ) { if (! buf || ! buf_len || ! inv ) {
return(0); 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 ) { size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len ) {
if (! buf || ! buf_len ) { if (! buf || ! buf_len ) {
return(0); return(0);
} }
return ia32_disasm_size(buf, buf_len); return ia32_disasm_size(buf, buf_len);
} }

View File

@ -16,16 +16,21 @@ class CIcodeRec;
struct BB; struct BB;
struct LOCAL_ID; struct LOCAL_ID;
struct interval; struct interval;
//TODO: consider default address value -> INVALID
struct TYPEADR_TYPE struct TYPEADR_TYPE
{ {
uint32_t ip; /* Out edge icode address */ uint32_t ip; /* Out edge icode address */
BB * BBptr; /* Out edge pointer to next BB */ BB * BBptr; /* Out edge pointer to next BB */
interval *intPtr; /* Out edge ptr to next interval*/ 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> struct BB : public llvm::ilist_node<BB>
{ {
private: private:
BB(const BB&); BB(const BB&);
BB() : nodeType(0),traversed(DFS_NONE), BB() : nodeType(0),traversed(DFS_NONE),
@ -76,7 +81,7 @@ public:
* derived graph Gi-1 */ * derived graph Gi-1 */
/* For live register analysis /* 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> liveUse; /* LiveUse(b) */
std::bitset<32> def; /* Def(b) */ std::bitset<32> def; /* Def(b) */
std::bitset<32> liveIn; /* LiveIn(b) */ std::bitset<32> liveIn; /* LiveIn(b) */
@ -90,9 +95,8 @@ public:
int ifFollow; /* node that ends the if */ int ifFollow; /* node that ends the if */
int loopType; /* Type of loop (if any) */ int loopType; /* Type of loop (if any) */
int latchNode; /* latching node of the loop */ int latchNode; /* latching node of the loop */
int numBackEdges; /* # of back edges */ size_t numBackEdges; /* # of back edges */
int loopHead; /* most nested loop head to which int loopHead; /* most nested loop head to which this node belongs (dfsLast) */
* thcis node belongs (dfsLast) */
int loopFollow; /* node that follows the loop */ int loopFollow; /* node that follows the loop */
int caseHead; /* most nested case to which this int caseHead; /* most nested case to which this
node belongs (dfsLast) */ node belongs (dfsLast) */
@ -100,8 +104,8 @@ public:
int index; /* Index, used in several ways */ 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(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 * CreateIntervalBB(Function *parent);
static BB * Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, 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 writeCode(int indLevel, Function *pProc, int *numLoc, int latchNode, int ifFollow);
void mergeFallThrough(CIcodeRec &Icode); void mergeFallThrough(CIcodeRec &Icode);
void dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last); void dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last);
@ -118,10 +122,15 @@ public:
bool valid() {return 0==(flg & INVALID_BB); } bool valid() {return 0==(flg & INVALID_BB); }
bool wasTraversedAtLevel(int l) const {return traversed==l;} bool wasTraversedAtLevel(int l) const {return traversed==l;}
ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond); 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); void RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode);
private: private:
bool FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at); bool FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at);

View File

@ -45,10 +45,10 @@ protected:
} boolExpr; } boolExpr;
public: public:
condNodeType m_type; /* Conditional Expression Node Type */ condNodeType m_type; /* Conditional Expression Node Type */
union _exprNode { /* Different cond expr nodes */ union _exprNode { /* Different cond expr nodes */
COND_EXPR *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/ COND_EXPR *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
IDENTTYPE ident; /* for IDENTIFIER */ IDENTTYPE ident; /* for IDENTIFIER */
} expr; } expr;
COND_EXPR *lhs() COND_EXPR *lhs()
{ {
@ -72,19 +72,19 @@ public:
} }
condOp op() const { return boolExpr.op;} condOp op() const { return boolExpr.op;}
public: public:
static COND_EXPR *idRegIdx(int idx, regType reg_type); static COND_EXPR * idRegIdx(int idx, regType reg_type);
static COND_EXPR *idKte(uint32_t kte, uint8_t size); static COND_EXPR * idKte(uint32_t kte, uint8_t size);
static COND_EXPR *idLoc(int off, LOCAL_ID *localId); static COND_EXPR * idLoc(int off, LOCAL_ID *localId);
static COND_EXPR *idReg(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym); static COND_EXPR * idReg(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym);
static COND_EXPR *idLongIdx(int idx); static COND_EXPR * idLongIdx(int idx);
static COND_EXPR *idOther(eReg seg, eReg regi, int16_t off); static COND_EXPR * idOther(eReg seg, eReg regi, int16_t off);
static COND_EXPR *idParam(int off, const STKFRAME *argSymtab); static COND_EXPR * idParam(int off, const STKFRAME *argSymtab);
static COND_EXPR *unary(condNodeType t, COND_EXPR *sub_expr); 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 * 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 * idFunc(Function *pproc, STKFRAME *args);
static COND_EXPR *idID(const ID *retVal, LOCAL_ID *locsym, iICODE ix_); 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 * 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 insertSubTreeLongReg(COND_EXPR *exp, COND_EXPR **tree, int longIdx);
static bool insertSubTreeReg(COND_EXPR *&tree, COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym); static bool insertSubTreeReg(COND_EXPR *&tree, COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
public: public:

View File

@ -23,6 +23,7 @@ struct SymbolCommon
}; };
struct SYM : public SymbolCommon struct SYM : public SymbolCommon
{ {
typedef uint32_t tLabel;
SYM() : label(0),flg(0) SYM() : label(0),flg(0)
{ {
@ -33,9 +34,10 @@ struct SYM : public SymbolCommon
/* STACK FRAME */ /* STACK FRAME */
struct STKSYM : public SymbolCommon struct STKSYM : public SymbolCommon
{ {
typedef int16_t tLabel;
COND_EXPR *actual; /* Expression tree of actual parameter */ COND_EXPR *actual; /* Expression tree of actual parameter */
COND_EXPR *regs; /* For register arguments only */ 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) */ uint8_t regOff; /* Offset is a register (e.g. SI, DI) */
bool hasMacro; /* This type needs a macro */ bool hasMacro; /* This type needs a macro */
std::string macro; /* Macro name */ std::string macro; /* Macro name */
@ -60,13 +62,13 @@ class SymbolTableCommon : public std::vector<T>
public: public:
typedef typename std::vector<T>::iterator iterator; typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_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(), auto iter = std::find_if(this->begin(),this->end(),
[lab](T &s)->bool {return s.label==lab;}); [lab](T &s)->bool {return s.label==lab;});
return iter; 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(), auto iter = std::find_if(this->begin(),this->end(),
[lab](const T &s)->bool {return s.label==lab;}); [lab](const T &s)->bool {return s.label==lab;});

View File

@ -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 start - basic block starts here, might be parent->Icode.end()
* @arg fin - last of basic block's instructions * @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; BB* pnewBB;
pnewBB = new BB; 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->immedDom = NO_DOM;
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail = pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE; pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
pnewBB->instructions = make_iterator_range(start,fin); pnewBB->instructions = r;
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);
/* Mark the basic block to which the icodes belong to, but only for /* 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(parent)
{ {
if (start != parent->Icode.end()) //setInBB should automatically handle if our range is empty
parent->Icode.SetInBB(pnewBB->instructions, pnewBB); parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
parent->heldBBs.push_back(pnewBB); parent->heldBBs.push_back(pnewBB);
parent->m_cfg.push_back(pnewBB); parent->m_cfg.push_back(pnewBB);
pnewBB->Parent = parent; 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++; stats.numBBbef++;
return pnewBB; 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 endOfParent = parent->Icode.end();
iICODE fin(parent->Icode.begin()); return Create(make_iterator_range(endOfParent,endOfParent),INTERVAL_NODE,parent);
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);
} }
static const char *const s_nodeType[] = {"branch", "if", "case", "fall", "return", "call", static const char *const s_nodeType[] = {"branch", "if", "case", "fall", "return", "call",

View File

@ -336,9 +336,7 @@ void Function::structLoops(derSeq *derivedG)
* h. Note that h is a case node. */ * h. Note that h is a case node. */
static bool successor (int s, int h, Function * pProc) static bool successor (int s, int h, Function * pProc)
{ {
BB * header; BB * header = pProc->m_dfsLast[h];
header = pProc->m_dfsLast[h];
auto iter = std::find_if(header->edges.begin(), auto iter = std::find_if(header->edges.begin(),
header->edges.end(), header->edges.end(),
[s](const TYPEADR_TYPE &te)->bool{ return te.BBptr->dfsLastNum == s;}); [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 */ /* Structures if statements */
void Function::structIfs () void Function::structIfs ()
{ {
size_t followInEdges; /* Largest # in-edges so far */
int curr, /* Index for linear scan of nodes */ int curr, /* Index for linear scan of nodes */
/*desc,*/ /* Index for descendant */ /*desc,*/ /* Index for descendant */
followInEdges, /* Largest # in-edges so far */
follow; /* Possible follow node */ follow; /* Possible follow node */
nodeList domDesc, /* List of nodes dominated by curr */ nodeList domDesc, /* List of nodes dominated by curr */
unresolved /* List of unresolved if nodes */ unresolved /* List of unresolved if nodes */

View File

@ -3,11 +3,17 @@
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
****************************************************************************/ ****************************************************************************/
#include "dcc.h"
#include <string.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 "graph.h"
#include "project.h" #include "project.h"
using namespace std;
using namespace boost;
extern Project g_proj; extern Project g_proj;
//static BB * rmJMP(Function * pProc, int marker, BB * pBB); //static BB * rmJMP(Function * pProc, int marker, BB * pBB);
//static void mergeFallThrough(Function * pProc, BB * pBB); //static void mergeFallThrough(Function * pProc, BB * pBB);
@ -33,116 +39,98 @@ void Function::createCFG()
BB * psBB; BB * psBB;
BB * pBB; BB * pBB;
iICODE pIcode = Icode.begin(); iICODE pIcode = Icode.begin();
iICODE iStart = Icode.begin();
stats.numBBbef = stats.numBBaft = 0; 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); iICODE nextIcode = ++iICODE(pIcode);
pBB = nullptr;
LLInst *ll = pIcode->ll(); 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 /* 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 if (nextIcode == Icode.end() and
(not ll->testFlags(TERMINATES)) and (not ll->testFlags(TERMINATES)) and
(not ll->match(iJMP)) and (not ll->match(iJMPF)) and (not ll->match(iJMP)) and (not ll->match(iJMPF)) and
(not ll->match(iRET)) and (not ll->match(iRETF))) (not ll->match(iRET)) and (not ll->match(iRETF)))
{ {
//pBB=BB::Create(start, ip, NOWHERE_NODE, 0, this); pBB=BB::Create(current_range, NOWHERE_NODE, this);
pBB=BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
} }
else
/* Only process icodes that have valid instructions */
else if (not ll->testFlags(NO_CODE) )
{
switch (ll->getOpcode()) { switch (ll->getOpcode()) {
case iJB: case iJBE: case iJAE: case iJA: case iJB: case iJBE: case iJAE: case iJA:
case iJL: case iJLE: case iJGE: case iJG: case iJL: case iJLE: case iJGE: case iJG:
case iJE: case iJNE: case iJS: case iJNS: case iJE: case iJNE: case iJS: case iJNS:
case iJO: case iJNO: case iJP: case iJNP: case iJO: case iJNO: case iJP: case iJNP:
case iJCXZ: case iJCXZ:
pBB = BB::Create(iStart, pIcode, TWO_BRANCH, 2, this); pBB = BB::Create(current_range, TWO_BRANCH, this);
CondJumps: CondJumps:
//start = ip + 1; pBB->addOutEdge(nextIcode->loc_ip);
iStart = ++iICODE(pIcode); /* This is checking for jumps off into nowhere */
pBB->edges[0].ip = (uint32_t)iStart->loc_ip; if ( not ll->testFlags(NO_LABEL) )
/* This is for jumps off into nowhere */ pBB->addOutEdge(ll->src().getImm2());
if ( ll->testFlags(NO_LABEL) )
{
pBB->edges.pop_back();
}
else
pBB->edges[1].ip = ll->src().getImm2();
break; break;
case iLOOP: case iLOOPE: case iLOOPNE: case iLOOP: case iLOOPE: case iLOOPNE:
//pBB = BB::Create(start, ip, LOOP_NODE, 2, this); pBB = BB::Create(current_range, LOOP_NODE, this);
pBB = BB::Create(iStart, pIcode, LOOP_NODE, 2, this);
goto CondJumps; goto CondJumps;
case iJMPF: case iJMP: case iJMPF: case iJMP:
if (ll->testFlags(SWITCH)) if (ll->testFlags(SWITCH))
{ {
//pBB = BB::Create(start, ip, MULTI_BRANCH, ll->caseTbl.numEntries, this); pBB = BB::Create(current_range, MULTI_BRANCH, this);
pBB = BB::Create(iStart, pIcode, MULTI_BRANCH, ll->caseTbl2.size(), this);
for (size_t i = 0; i < ll->caseTbl2.size(); i++) for (size_t i = 0; i < ll->caseTbl2.size(); i++)
pBB->edges[i].ip = ll->caseTbl2[i]; pBB->addOutEdge(ll->caseTbl2[i]);
hasCase = true; hasCase = true;
} }
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT 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(current_range, ONE_BRANCH, this);
pBB = BB::Create(iStart, pIcode, ONE_BRANCH, 1, this); pBB->addOutEdge(ll->src().getImm2());
pBB->edges[0].ip = ll->src().getImm2();
} }
else else
BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this); pBB = BB::Create(current_range, NOWHERE_NODE, this);
iStart = ++iICODE(pIcode);
break; break;
case iCALLF: case iCALL: case iCALLF: case iCALL:
{ {
Function * p = ll->src().proc.proc; Function * p = ll->src().proc.proc;
if (p) pBB = BB::Create(current_range, CALL_NODE, this);
i = ((p->flg) & TERMINATES) ? 0 : 1; if (p && not ((p->flg) & TERMINATES) )
else pBB->addOutEdge(nextIcode->loc_ip);
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;
}
break; break;
}
case iRET: case iRETF: case iRET: case iRETF:
//BB::Create(start, ip, RETURN_NODE, 0, this); pBB = BB::Create(current_range, RETURN_NODE, this);
BB::Create(iStart, pIcode, RETURN_NODE, 0, this);
iStart = ++iICODE(pIcode);
break; break;
default: default:
/* Check for exit to DOS */ /* Check for exit to DOS */
iICODE next1=++iICODE(pIcode);
if ( ll->testFlags(TERMINATES) ) if ( ll->testFlags(TERMINATES) )
{ {
pBB = BB::Create(iStart, pIcode, TERMINATE_NODE, 0, this); pBB = BB::Create(current_range, TERMINATE_NODE, this);
//pBB = BB::Create(start, ip, TERMINATE_NODE, 0, this);
iStart = ++iICODE(pIcode); // start = ip + 1;
} }
/* Check for a fall through */ /* 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(current_range, FALL_NODE, this);
pBB = BB::Create(iStart, pIcode, FALL_NODE, 1, this); pBB->addOutEdge(nextIcode->loc_ip);
iStart = ++iICODE(pIcode); // start = ip + 1;
pBB->addOutEdge(iStart->loc_ip);
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
} }
} }
break; 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(); auto iter=heldBBs.begin();
@ -160,14 +148,14 @@ CondJumps:
} }
auto iter2=std::find_if(heldBBs.begin(),heldBBs.end(), auto iter2=std::find_if(heldBBs.begin(),heldBBs.end(),
[ip](BB *psBB)->bool {return psBB->begin()->loc_ip==ip;}); [ip](BB *psBB)->bool {return psBB->begin()->loc_ip==ip;});
if(iter2==heldBBs.end()) if(iter2==heldBBs.end())
fatalError(NO_BB, ip, name.c_str()); fatalError(NO_BB, ip, name.c_str());
psBB = *iter2; psBB = *iter2;
pBB->edges[edeg_idx].BBptr = psBB; pBB->edges[edeg_idx].BBptr = psBB;
psBB->inEdges.push_back((BB *)nullptr); psBB->inEdges.push_back((BB *)nullptr);
}
} }
} }
}
void Function::markImpure() void Function::markImpure()
{ {
@ -350,33 +338,33 @@ void BB::mergeFallThrough( CIcodeRec &Icode)
auto iter=std::find_if(this->end(),pChild->begin(),[](ICODE &c) auto iter=std::find_if(this->end(),pChild->begin(),[](ICODE &c)
{return not c.ll()->testFlags(NO_CODE);}); {return not c.ll()->testFlags(NO_CODE);});
if (iter != pChild->begin()) 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)
break; break;
back().ll()->setFlags(NO_CODE);
nodeType = pChild->nodeType; back().invalidate();
instructions = boost::make_iterator_range(begin(),pChild->end()); nodeType = FALL_NODE;
pChild->front().ll()->clrFlags(TARGET); //instructions.advance_end(-1); //TODO: causes creation of empty BB
edges.swap(pChild->edges);
pChild->inEdges.clear();
pChild->edges.clear();
} }
traversed = DFS_MERGE; /* If there's no other edges into child can merge */
if (pChild->inEdges.size() != 1)
break;
/* Process all out edges recursively */ nodeType = pChild->nodeType;
for (size_t i = 0; i < edges.size(); i++) instructions = boost::make_iterator_range(begin(),pChild->end());
{ pChild->front().ll()->clrFlags(TARGET);
if (edges[i].BBptr->traversed != DFS_MERGE) edges.swap(pChild->edges);
edges[i].BBptr->mergeFallThrough(Icode);
} 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);
}
} }

View File

@ -12,7 +12,7 @@ OPTION option; /* Command line options */
Project *Project::s_instance = 0; Project *Project::s_instance = 0;
Project::Project() : callGraph(nullptr) Project::Project() : callGraph(nullptr)
{ {
memset(&prog,0,sizeof(prog));
} }
void Project::initialize() void Project::initialize()
{ {
@ -49,8 +49,7 @@ ilFunction Project::findByEntry(uint32_t entry)
{ {
/* Search procedure list for one with appropriate entry point */ /* Search procedure list for one with appropriate entry point */
ilFunction iter= std::find_if(pProcList.begin(),pProcList.end(), ilFunction iter= std::find_if(pProcList.begin(),pProcList.end(),
[entry](const Function &f) -> [entry](const Function &f) { return f.procEntry==entry; });
bool { return f.procEntry==entry; });
return iter; return iter;
} }

View File

@ -540,20 +540,19 @@ void Function::propLong()
for (size_t i = 0; i < localId.csym(); i++) for (size_t i = 0; i < localId.csym(); i++)
{ {
const ID &pLocId(localId.id_arr[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);
case STK_FRAME: break;
propLongStk (i, pLocId); case REG_FRAME:
break; propLongReg (i, pLocId);
case REG_FRAME: break;
propLongReg (i, pLocId); case GLB_FRAME:
break; propLongGlb (i, pLocId);
case GLB_FRAME: break;
propLongGlb (i, pLocId);
break;
}
} }
} }
} }

View File

@ -236,29 +236,23 @@ derSeq_Entry::~derSeq_Entry()
bool Function::nextOrderGraph (derSeq &derivedGi) bool Function::nextOrderGraph (derSeq &derivedGi)
{ {
interval *Ii; /* Interval being processed */ interval *Ii; /* Interval being processed */
BB *BBnode, /* New basic block of intervals */ BB *BBnode; /* New basic block of intervals */
//*curr, /* BB being checked for out edges */ bool sameGraph; /* Boolean, isomorphic graphs */
*succ /* Successor node */
;
//queue *listIi; /* List of intervals */
int i; /* Index to outEdges array */
/*j;*/ /* Index to successors */
boolT sameGraph; /* Boolean, isomorphic graphs */
/* Process Gi's intervals */ /* Process Gi's intervals */
derSeq_Entry &prev_entry(derivedGi.back()); derSeq_Entry &prev_entry(derivedGi.back());
derivedGi.push_back(derSeq_Entry()); derivedGi.push_back(derSeq_Entry());
derSeq_Entry &new_entry(derivedGi.back()); derSeq_Entry &new_entry(derivedGi.back());
Ii = prev_entry.Ii;
sameGraph = true; sameGraph = true;
BBnode = 0; BBnode = 0;
std::vector<BB *> bbs; 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 = BB::CreateIntervalBB(this);
BBnode = bbs.back();
BBnode->correspInt = Ii; BBnode->correspInt = Ii;
bbs.push_back(BBnode);
const queue &listIi(Ii->nodes); const queue &listIi(Ii->nodes);
/* Check for more than 1 interval */ /* Check for more than 1 interval */
@ -267,21 +261,17 @@ bool Function::nextOrderGraph (derSeq &derivedGi)
/* Find out edges */ /* 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++) BB *successor_node = curr->edges[j].BBptr;
{ if (successor_node->inInterval != curr->inInterval)
succ = curr->edges[j].BBptr; BBnode->addOutEdgeInterval(successor_node->inInterval);
if (succ->inInterval != curr->inInterval)
BBnode->edges[i++].intPtr = succ->inInterval;
}
} }
} }
/* Next interval */
Ii = Ii->next;
} }
/* Convert list of pointers to intervals into a real graph. /* Convert list of pointers to intervals into a real graph.
@ -303,7 +293,7 @@ bool Function::nextOrderGraph (derSeq &derivedGi)
(*iter)->inEdgeCount++; (*iter)->inEdgeCount++;
} }
} }
return (boolT)(! sameGraph); return not sameGraph;
} }

View File

@ -357,8 +357,7 @@ static void fixFloatEmulation(x86_insn_t &insn)
if ((wOp < 0x34) || (wOp > 0x3B)) if ((wOp < 0x34) || (wOp > 0x3B))
return; return;
uint8_t buf[16]; uint8_t buf[16];
/* This is a Borland/Microsoft floating point emulation instruction. /* This is a Borland/Microsoft floating point emulation instruction. Treat as if it is an ESC opcode */
Treat as if it is an ESC opcode */
int actual_valid_bytes=std::min(16U,prog.cbImage-insn.offset); int actual_valid_bytes=std::min(16U,prog.cbImage-insn.offset);
memcpy(buf,prog.Image+insn.offset,actual_valid_bytes); memcpy(buf,prog.Image+insn.offset,actual_valid_bytes);

View File

@ -1,6 +1,6 @@
#include "dcc.h"
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "dcc.h"
TEST(CowriteTest, HandlesZeroInput) { TEST(CowriteTest, HandlesZeroInput) {
EXPECT_EQ(1, 1); EXPECT_EQ(1, 1);

View File

@ -13,8 +13,8 @@ TEST(Project, NewProjectIsInitalized) {
TEST(Project, CreatedProjectHasValidNames) { TEST(Project, CreatedProjectHasValidNames) {
Project p; Project p;
std::vector<std::string> strs = {"./Project1.EXE","/home/Project2.EXE","/home/Pro ject3"}; 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> expected = {"Project1","Project2","Pro\\ ject3"};
for(size_t i=0; i<strs.size(); i++) for(size_t i=0; i<strs.size(); i++)
{ {
p.create(strs[i]); p.create(strs[i]);