removed most of clang warnings / errors

This commit is contained in:
Artur K
2012-03-29 22:02:25 +02:00
parent 9cc5202ff7
commit ba110a64cb
60 changed files with 4285 additions and 4085 deletions

View File

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

View File

@@ -240,7 +240,7 @@ void Ia32_Decoder::ia32_handle_prefix( unsigned int prefixes ) {
}
static void reg_32_to_16( x86_op_t *op, x86_insn_t *insn, void *arg ) {
static void reg_32_to_16( x86_op_t *op, x86_insn_t */*insn*/, void */*arg*/ ) {
/* if this is a 32-bit register and it is a general register ... */
if ( op->type == op_register && op->data.reg.size == 4 &&
@@ -539,12 +539,12 @@ size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
size_t Ia32_Decoder::handle_insn_suffix( unsigned char *buf, size_t buf_len,
ia32_insn_t *raw_insn ) {
ia32_table_desc_t *table_desc;
// ia32_table_desc_t *table_desc;
ia32_insn_t *sfx_insn;
size_t size;
unsigned int prefixes = 0;
table_desc = &ia32_tables[raw_insn->table];
// table_desc = &ia32_tables[raw_insn->table];
size = ia32_table_lookup( buf, buf_len, raw_insn->table, &sfx_insn,
&prefixes );
if (size == INVALID_INSN || sfx_insn->mnem_flag == INS_INVALID ) {

View File

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

View File

@@ -155,12 +155,12 @@ static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 3);
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
case MOD16_RM_BPSI:
op->flags.op_seg = x86_op_flags::op_ss_seg;
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 6);
break;
case MOD16_RM_BPDI:
op->flags.op_seg = x86_op_flags::op_ss_seg;
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
break;
@@ -172,7 +172,7 @@ static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
break;
case MOD16_RM_BP:
if ( modrm->mod != MOD16_MOD_NODISP ) {
op->flags.op_seg = x86_op_flags::op_ss_seg;
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
ia32_handle_register(&ea->base,
REG_WORD_OFFSET + 5);
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,17 +20,17 @@ static void apply_seg( x86_op_t *op, unsigned int prefixes ) {
switch ( prefixes & PREFIX_REG_MASK ) {
/* NOTE: that op->flags for segment override are not a bitfield */
case PREFIX_CS:
op->flags.op_seg = x86_op_flags::op_cs_seg; break;
op->flags.op_seg = x86_op_flags::op_cs_seg>>8; break;
case PREFIX_SS:
op->flags.op_seg = x86_op_flags::op_ss_seg; break;
op->flags.op_seg = x86_op_flags::op_ss_seg>>8; break;
case PREFIX_DS:
op->flags.op_seg = x86_op_flags::op_ds_seg; break;
op->flags.op_seg = x86_op_flags::op_ds_seg>>8; break;
case PREFIX_ES:
op->flags.op_seg = x86_op_flags::op_es_seg; break;
op->flags.op_seg = x86_op_flags::op_es_seg>>8; break;
case PREFIX_FS:
op->flags.op_seg = x86_op_flags::op_fs_seg; break;
op->flags.op_seg = x86_op_flags::op_fs_seg>>8; break;
case PREFIX_GS:
op->flags.op_seg = x86_op_flags::op_gs_seg; break;
op->flags.op_seg = x86_op_flags::op_gs_seg>>8; break;
}
return;
@@ -172,7 +172,7 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
case ADDRMETH_X: /* Memory addressed by DS:SI [string] */
op->type = op_expression;
op->flags.op_hardcode = true;
op->flags.op_seg = x86_op_flags::op_ds_seg;
op->flags.op_seg = x86_op_flags::op_ds_seg>>8;
op->flags.op_pointer = true;
op->flags.op_string = true;
ia32_handle_register( &op->data.expression.base,
@@ -181,7 +181,7 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
case ADDRMETH_Y: /* Memory addressed by ES:DI [string] */
op->type = op_expression;
op->flags.op_hardcode = true;
op->flags.op_seg = x86_op_flags::op_es_seg;
op->flags.op_seg = x86_op_flags::op_es_seg>>8;
op->flags.op_pointer = true;
op->flags.op_string = true;
ia32_handle_register( &op->data.expression.base,

View File

@@ -71,126 +71,126 @@ static struct {
unsigned int alias;
char mnemonic[8];
} ia32_reg_table[NUM_X86_REGS + 2] = {
{ 0, reg_undef, 0, "" },
/* REG_DWORD_OFFSET */
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_ret), 0, "eax" },
{ 0, reg_undef, 0, "" },
/* REG_DWORD_OFFSET */
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_ret), 0, "eax" },
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_count), 0, "ecx" },
{ REG_DWORD_SIZE, reg_gen, 0, "edx" },
{ REG_DWORD_SIZE, reg_gen, 0, "ebx" },
/* REG_ESP_INDEX */
{ REG_DWORD_SIZE, reg_gen, 0, "edx" },
{ REG_DWORD_SIZE, reg_gen, 0, "ebx" },
/* REG_ESP_INDEX */
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_sp), 0, "esp" },
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_fp), 0, "ebp" },
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_src), 0, "esi" },
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_dest), 0, "edi" },
/* REG_WORD_OFFSET */
/* REG_WORD_OFFSET */
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_ret), 3, "ax" },
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_count), 6, "cx" },
{ REG_WORD_SIZE, reg_gen, 9, "dx" },
{ REG_WORD_SIZE, reg_gen, 12, "bx" },
{ REG_WORD_SIZE, reg_gen, 9, "dx" },
{ REG_WORD_SIZE, reg_gen, 12, "bx" },
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_sp), 13, "sp" },
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_fp), 14, "bp" },
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_src), 15, "si" },
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_dest), 16, "di" },
/* REG_BYTE_OFFSET */
{ REG_BYTE_SIZE, reg_gen, 1, "al" },
{ REG_BYTE_SIZE, reg_gen, 4, "cl" },
{ REG_BYTE_SIZE, reg_gen, 7, "dl" },
{ REG_BYTE_SIZE, reg_gen, 10, "bl" },
{ REG_BYTE_SIZE, reg_gen, 2, "ah" },
{ REG_BYTE_SIZE, reg_gen, 5, "ch" },
{ REG_BYTE_SIZE, reg_gen, 8, "dh" },
{ REG_BYTE_SIZE, reg_gen, 11, "bh" },
/* REG_MMX_OFFSET */
{ REG_MMX_SIZE, reg_simd, 18, "mm0" },
{ REG_MMX_SIZE, reg_simd, 19, "mm1" },
{ REG_MMX_SIZE, reg_simd, 20, "mm2" },
{ REG_MMX_SIZE, reg_simd, 21, "mm3" },
{ REG_MMX_SIZE, reg_simd, 22, "mm4" },
{ REG_MMX_SIZE, reg_simd, 23, "mm5" },
{ REG_MMX_SIZE, reg_simd, 24, "mm6" },
{ REG_MMX_SIZE, reg_simd, 25, "mm7" },
/* REG_SIMD_OFFSET */
{ REG_SIMD_SIZE, reg_simd, 0, "xmm0" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm1" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm2" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm3" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm4" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm5" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm6" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm7" },
/* REG_DEBUG_OFFSET */
{ REG_DEBUG_SIZE, reg_sys, 0, "dr0" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr1" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr2" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr3" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr4" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr5" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr6" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr7" },
/* REG_CTRL_OFFSET */
{ REG_CTRL_SIZE, reg_sys, 0, "cr0" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr1" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr2" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr3" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr4" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr5" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr6" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr7" },
/* REG_TEST_OFFSET */
{ REG_TEST_SIZE, reg_sys, 0, "tr0" },
{ REG_TEST_SIZE, reg_sys, 0, "tr1" },
{ REG_TEST_SIZE, reg_sys, 0, "tr2" },
{ REG_TEST_SIZE, reg_sys, 0, "tr3" },
{ REG_TEST_SIZE, reg_sys, 0, "tr4" },
{ REG_TEST_SIZE, reg_sys, 0, "tr5" },
{ REG_TEST_SIZE, reg_sys, 0, "tr6" },
{ REG_TEST_SIZE, reg_sys, 0, "tr7" },
/* REG_SEG_OFFSET */
{ REG_SEG_SIZE, reg_seg, 0, "es" },
{ REG_SEG_SIZE, reg_seg, 0, "cs" },
{ REG_SEG_SIZE, reg_seg, 0, "ss" },
{ REG_SEG_SIZE, reg_seg, 0, "ds" },
{ REG_SEG_SIZE, reg_seg, 0, "fs" },
{ REG_SEG_SIZE, reg_seg, 0, "gs" },
/* REG_LDTR_INDEX */
{ REG_DWORD_SIZE, reg_sys, 0, "ldtr" },
/* REG_GDTR_INDEX */
{ REG_DWORD_SIZE, reg_sys, 0, "gdtr" },
/* REG_FPU_OFFSET */
{ REG_FPU_SIZE, reg_fpu, 0, "st(0)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(1)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(2)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(3)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(4)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(5)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(6)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(7)" },
/* REG_FLAGS_INDEX : 81 */
{ REG_FLAGS_SIZE, reg_cond, 0, "eflags" },
/* REG_FPCTRL_INDEX : 82*/
/* REG_BYTE_OFFSET */
{ REG_BYTE_SIZE, reg_gen, 1, "al" },
{ REG_BYTE_SIZE, reg_gen, 4, "cl" },
{ REG_BYTE_SIZE, reg_gen, 7, "dl" },
{ REG_BYTE_SIZE, reg_gen, 10, "bl" },
{ REG_BYTE_SIZE, reg_gen, 2, "ah" },
{ REG_BYTE_SIZE, reg_gen, 5, "ch" },
{ REG_BYTE_SIZE, reg_gen, 8, "dh" },
{ REG_BYTE_SIZE, reg_gen, 11, "bh" },
/* REG_MMX_OFFSET */
{ REG_MMX_SIZE, reg_simd, 18, "mm0" },
{ REG_MMX_SIZE, reg_simd, 19, "mm1" },
{ REG_MMX_SIZE, reg_simd, 20, "mm2" },
{ REG_MMX_SIZE, reg_simd, 21, "mm3" },
{ REG_MMX_SIZE, reg_simd, 22, "mm4" },
{ REG_MMX_SIZE, reg_simd, 23, "mm5" },
{ REG_MMX_SIZE, reg_simd, 24, "mm6" },
{ REG_MMX_SIZE, reg_simd, 25, "mm7" },
/* REG_SIMD_OFFSET */
{ REG_SIMD_SIZE, reg_simd, 0, "xmm0" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm1" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm2" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm3" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm4" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm5" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm6" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm7" },
/* REG_DEBUG_OFFSET */
{ REG_DEBUG_SIZE, reg_sys, 0, "dr0" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr1" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr2" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr3" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr4" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr5" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr6" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr7" },
/* REG_CTRL_OFFSET */
{ REG_CTRL_SIZE, reg_sys, 0, "cr0" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr1" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr2" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr3" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr4" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr5" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr6" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr7" },
/* REG_TEST_OFFSET */
{ REG_TEST_SIZE, reg_sys, 0, "tr0" },
{ REG_TEST_SIZE, reg_sys, 0, "tr1" },
{ REG_TEST_SIZE, reg_sys, 0, "tr2" },
{ REG_TEST_SIZE, reg_sys, 0, "tr3" },
{ REG_TEST_SIZE, reg_sys, 0, "tr4" },
{ REG_TEST_SIZE, reg_sys, 0, "tr5" },
{ REG_TEST_SIZE, reg_sys, 0, "tr6" },
{ REG_TEST_SIZE, reg_sys, 0, "tr7" },
/* REG_SEG_OFFSET */
{ REG_SEG_SIZE, reg_seg, 0, "es" },
{ REG_SEG_SIZE, reg_seg, 0, "cs" },
{ REG_SEG_SIZE, reg_seg, 0, "ss" },
{ REG_SEG_SIZE, reg_seg, 0, "ds" },
{ REG_SEG_SIZE, reg_seg, 0, "fs" },
{ REG_SEG_SIZE, reg_seg, 0, "gs" },
/* REG_LDTR_INDEX */
{ REG_DWORD_SIZE, reg_sys, 0, "ldtr" },
/* REG_GDTR_INDEX */
{ REG_DWORD_SIZE, reg_sys, 0, "gdtr" },
/* REG_FPU_OFFSET */
{ REG_FPU_SIZE, reg_fpu, 0, "st(0)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(1)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(2)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(3)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(4)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(5)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(6)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(7)" },
/* REG_FLAGS_INDEX : 81 */
{ REG_FLAGS_SIZE, reg_cond, 0, "eflags" },
/* REG_FPCTRL_INDEX : 82*/
{ REG_FPCTRL_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fpctrl" },
/* REG_FPSTATUS_INDEX : 83*/
/* REG_FPSTATUS_INDEX : 83*/
{ REG_FPSTATUS_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fpstat" },
/* REG_FPTAG_INDEX : 84 */
/* REG_FPTAG_INDEX : 84 */
{ REG_FPTAG_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fptag" },
/* REG_EIP_INDEX : 85 */
{ REG_EIP_SIZE, reg_pc, 0, "eip" },
/* REG_IP_INDEX : 86 */
{ REG_IP_SIZE, reg_pc, 17, "ip" },
/* REG_IDTR_INDEX : 87 */
{ REG_DWORD_SIZE, reg_sys, 0, "idtr" },
/* REG_MXCSG_INDEX : SSE Control Reg : 88 */
{ REG_DWORD_SIZE, (x86_reg_type)(reg_sys | reg_simd), 0, "mxcsr" },
/* REG_TR_INDEX : Task Register : 89 */
{ 16 + 64, reg_sys, 0, "tr" },
/* REG_CSMSR_INDEX : SYSENTER_CS_MSR : 90 */
{ REG_DWORD_SIZE, reg_sys, 0, "cs_msr" },
/* REG_ESPMSR_INDEX : SYSENTER_ESP_MSR : 91 */
{ REG_DWORD_SIZE, reg_sys, 0, "esp_msr" },
/* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */
{ REG_DWORD_SIZE, reg_sys, 0, "eip_msr" },
{ 0 }
};
/* REG_EIP_INDEX : 85 */
{ REG_EIP_SIZE, reg_pc, 0, "eip" },
/* REG_IP_INDEX : 86 */
{ REG_IP_SIZE, reg_pc, 17, "ip" },
/* REG_IDTR_INDEX : 87 */
{ REG_DWORD_SIZE, reg_sys, 0, "idtr" },
/* REG_MXCSG_INDEX : SSE Control Reg : 88 */
{ REG_DWORD_SIZE, (x86_reg_type)(reg_sys | reg_simd), 0, "mxcsr" },
/* REG_TR_INDEX : Task Register : 89 */
{ 16 + 64, reg_sys, 0, "tr" },
/* REG_CSMSR_INDEX : SYSENTER_CS_MSR : 90 */
{ REG_DWORD_SIZE, reg_sys, 0, "cs_msr" },
/* REG_ESPMSR_INDEX : SYSENTER_ESP_MSR : 91 */
{ REG_DWORD_SIZE, reg_sys, 0, "esp_msr" },
/* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */
{ REG_DWORD_SIZE, reg_sys, 0, "eip_msr" },
{ 0,reg_undef,0,{0} }
};
static size_t sz_regtable = NUM_X86_REGS + 1;

View File

@@ -89,7 +89,7 @@ enum x86_options { /* these can be ORed together */
opt_none= 0,
opt_ignore_nulls=1, /* ignore sequences of > 4 NULL bytes */
opt_16_bit=2, /* 16-bit/DOS disassembly */
opt_att_mnemonics=4, /* use AT&T syntax names for alternate opcode mnemonics */
opt_att_mnemonics=4 /* use AT&T syntax names for alternate opcode mnemonics */
};
/* ========================================= Instruction Representation */
@@ -133,12 +133,12 @@ enum x86_reg_type { /* NOTE: these may be ORed together */
/* x86_reg_t : an X86 CPU register */
struct x86_reg_t {
char name[MAX_REGNAME];
enum x86_reg_type type; /* what register is used for */
unsigned int size; /* size of register in bytes */
unsigned int id; /* register ID #, for quick compares */
unsigned int alias; /* ID of reg this is an alias for */
unsigned int shift; /* amount to shift aliased reg by */
char name[MAX_REGNAME];
enum x86_reg_type type; /* what register is used for */
unsigned int size; /* size of register in bytes */
unsigned int id; /* register ID #, for quick compares */
unsigned int alias; /* ID of reg this is an alias for */
unsigned int shift; /* amount to shift aliased reg by */
x86_reg_t * aliased_reg( ) {
x86_reg_t * reg = (x86_reg_t * )calloc( sizeof(x86_reg_t), 1 );
reg->x86_reg_from_id( id );
@@ -158,11 +158,11 @@ typedef struct {
/* x86_absolute_t : an X86 segment:offset address (descriptor) */
typedef struct {
unsigned short segment; /* loaded directly into CS */
union {
unsigned short off16; /* loaded directly into IP */
uint32_t off32; /* loaded directly into EIP */
} offset;
unsigned short segment; /* loaded directly into CS */
union {
unsigned short off16; /* loaded directly into IP */
uint32_t off32; /* loaded directly into EIP */
} offset;
} x86_absolute_t;
enum x86_op_type { /* mutually exclusive */
@@ -250,39 +250,43 @@ struct x86_op_flags { /* ORed together, but segs are mutually exclusive */
/* x86_op_t : an X86 instruction operand */
struct x86_op_t{
friend struct x86_insn_t;
enum x86_op_type type; /* operand type */
enum x86_op_datatype datatype; /* operand size */
enum x86_op_access access; /* operand access [RWX] */
x86_op_flags flags; /* misc flags */
union {
/* sizeof will have to work on these union members! */
/* immediate values */
char sbyte;
short sword;
int32_t sdword;
qword_t sqword;
unsigned char byte;
unsigned short word;
uint32_t dword;
qword_t qword;
float sreal;
double dreal;
/* misc large/non-native types */
unsigned char extreal[10];
unsigned char bcd[10];
qword_t dqword[2];
unsigned char simd[16];
unsigned char fpuenv[28];
/* offset from segment */
uint32_t offset;
x86_reg_t reg; /* ID of CPU register */
char relative_near; /* offsets from current insn */
int32_t relative_far;
x86_absolute_t absolute; /* segment:offset */
x86_ea_t expression; /* effective address [expression] */
} data;
/* this is needed to make formatting operands more sane */
void * insn; /* pointer to x86_insn_t owning operand */
enum x86_op_type type; /* operand type */
enum x86_op_datatype datatype; /* operand size */
enum x86_op_access access; /* operand access [RWX] */
x86_op_flags flags; /* misc flags */
union {
/* sizeof will have to work on these union members! */
/* immediate values */
char sbyte;
short sword;
int32_t sdword;
qword_t sqword;
unsigned char byte;
unsigned short word;
uint32_t dword;
qword_t qword;
float sreal;
double dreal;
/* misc large/non-native types */
unsigned char extreal[10];
unsigned char bcd[10];
qword_t dqword[2];
unsigned char simd[16];
unsigned char fpuenv[28];
/* offset from segment */
uint32_t offset;
/* ID of CPU register */
x86_reg_t reg;
/* offsets from current insn */
char relative_near;
int32_t relative_far;
/* segment:offset */
x86_absolute_t absolute;
/* effective address [expression] */
x86_ea_t expression;
} data;
/* this is needed to make formatting operands more sane */
void * insn; /* pointer to x86_insn_t owning operand */
size_t size()
{
return operand_size();
@@ -301,6 +305,7 @@ struct x86_op_t{
x86_op_t * copy()
{
x86_op_t *op = (x86_op_t *) calloc( sizeof(x86_op_t), 1 );
if ( op ) {
memcpy( op, this, sizeof(x86_op_t) );
}
@@ -439,7 +444,7 @@ enum x86_insn_note {
insn_note_smm = 2, /* "" in System Management Mode */
insn_note_serial = 4, /* Serializing instruction */
insn_note_nonswap = 8, /* Does not swap arguments in att-style formatting */
insn_note_nosuffix = 16, /* Does not have size suffix in att-style formatting */
insn_note_nosuffix = 16 /* Does not have size suffix in att-style formatting */
};
/* This specifies what effects the instruction has on the %eflags register */
@@ -520,7 +525,6 @@ enum x86_insn_prefix {
/* TODO: maybe provide insn_new/free(), and have disasm return new insn_t */
/* FOREACH types: these are used to limit the foreach results to
* operands which match a certain "type" (implicit or explicit)
* or which are accessed in certain ways (e.g. read or write). Note
@@ -572,8 +576,8 @@ private:
void x86_oplist_append(x86_oplist_t *op);
public:
/* information about the instruction */
uint32_t addr; /* load address */
uint32_t offset; /* offset into file/buffer */
uint32_t addr; /* load address */
uint32_t offset; /* offset into file/buffer */
x86_insn_group group; /* meta-type, e.g. INS_EXEC */
x86_insn_type type; /* type, e.g. INS_BRANCH */
x86_insn_note note; /* note, e.g. RING0 */
@@ -604,29 +608,36 @@ public:
void *block; /* code block containing this insn */
void *function; /* function containing this insn */
int tag; /* tag the insn as seen/processed */
x86_op_t * x86_operand_new();
size_t x86_operand_count( enum x86_op_foreach_type type );
x86_op_t *x86_operand_new();
/* convenience routine: returns count of operands matching 'type' */
size_t x86_operand_count( enum x86_op_foreach_type type );
/* accessor functions for the operands */
x86_op_t * x86_operand_1st( );
x86_op_t * x86_operand_2nd( );
x86_op_t * x86_operand_3rd( );
x86_op_t * x86_operand_1st( );
x86_op_t * x86_operand_2nd( );
x86_op_t * x86_operand_3rd( );
x86_op_t * get_dest();
int32_t x86_get_rel_offset( );
x86_op_t * x86_get_branch_target( );
x86_op_t * x86_get_imm( );
uint8_t * x86_get_raw_imm( );
int32_t x86_get_rel_offset( );
x86_op_t * x86_get_branch_target( );
x86_op_t * x86_get_imm( );
/* More accessor fuctions, this time for user-defined info... */
void x86_set_insn_addr( uint32_t addr );
int x86_format_mnemonic( char *buf, int len, enum x86_asm_format format);
int x86_format_insn( char *buf, int len, enum x86_asm_format);
void x86_oplist_free( );
uint8_t * x86_get_raw_imm( );
/* set the address (usually RVA) of the insn */
void x86_set_insn_addr( uint32_t addr );
/* format (sprintf) an instruction mnemonic into 'buf' using specified syntax */
int x86_format_mnemonic( char *buf, int len, enum x86_asm_format format);
int x86_format_insn( char *buf, int len, enum x86_asm_format);
void x86_oplist_free( );
/* returns 0 if an instruction is invalid, 1 if valid */
bool is_valid( );
uint32_t x86_get_address( );
void make_invalid(unsigned char *buf);
void make_invalid(unsigned char *buf);
/* instruction tagging: these routines allow the programmer to mark
* instructions as "seen" in a DFS, for example. libdisasm does not use
* the tag field.*/
/* set insn->tag to 1 */
void x86_tag_insn( );
/* return insn->tag */
int x86_insn_is_tagged();
/* set insn->tag to 0 */
void x86_untag_insn();
@@ -803,9 +814,10 @@ public:
* void x86_get_aliased_reg( x86_reg_t *alias_reg, x86_reg_t *output_reg )
* where 'alias_reg' is a reg operand and 'output_reg' is filled with the
* register that the operand is an alias for */
//#define x86_get_aliased_reg( alias_reg, output_reg ) \
// x86_reg_from_id( alias_reg->alias, output_reg )
/*
#define x86_get_aliased_reg( alias_reg, output_reg ) \
x86_reg_from_id( alias_reg->alias, output_reg )
*/
/* ================================== Invariant Instruction Representation */
/* Invariant instructions are used for generating binary signatures;

View File

@@ -52,7 +52,7 @@ unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
/* copy enough bytes for disassembly into buffer : this
* helps prevent buffer overruns at the end of a file */
memset( bytes, 0, MAX_INSTRUCTION_SIZE );
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
MAX_INSTRUCTION_SIZE );
/* actually do the disassembly */
@@ -104,7 +104,7 @@ unsigned int X86_Disasm::x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
bytes++; /* try next byte */
}
insn.x86_oplist_free();
insn.x86_oplist_free();
}
return( count );
@@ -127,9 +127,9 @@ static int32_t internal_resolver( x86_op_t *op, x86_insn_t *insn ){
if ( x86_optype_is_address(op->type) ) {
next_addr = op->data.sdword;
} else if ( op->type == op_relative_near ) {
next_addr = insn->addr + insn->size + op->data.relative_near;
next_addr = insn->addr + insn->size + op->data.relative_near;
} else if ( op->type == op_relative_far ) {
next_addr = insn->addr + insn->size + op->data.relative_far;
next_addr = insn->addr + insn->size + op->data.relative_far;
}
return( next_addr );
}
@@ -141,7 +141,7 @@ unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int bu
x86_insn_t insn;
x86_op_t *op;
int32_t next_addr;
uint32_t next_offset;
int32_t next_offset;
unsigned int size, count = 0, bytes = 0, cont = 1;
while ( cont && bytes < buf_len ) {
@@ -175,8 +175,8 @@ unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int bu
if (next_addr != -1 ) {
next_offset = next_addr - buf_rva;
/* if offset is in this buffer... */
if ( next_offset >= 0 &&
next_offset < buf_len ) {
if ( next_offset >= 0 && next_offset < int(buf_len) )
{
/* go ahead and disassemble */
count += x86_disasm_forward( buf,
buf_len,
@@ -197,24 +197,24 @@ unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int bu
cont = 0;
}
insn.x86_oplist_free( );
insn.x86_oplist_free( );
}
return( count );
}
/* invariant instruction representation */
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
x86_invariant_t *inv ){
if (! buf || ! buf_len || ! inv ) {
return(0);
}
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
x86_invariant_t *inv ){
if (! buf || ! buf_len || ! inv ) {
return(0);
}
return ia32_disasm_invariant(buf, buf_len, inv);
return ia32_disasm_invariant(buf, buf_len, inv);
}
size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len ) {
if (! buf || ! buf_len ) {
return(0);
}
if (! buf || ! buf_len ) {
return(0);
}
return ia32_disasm_size(buf, buf_len);
return ia32_disasm_size(buf, buf_len);
}

View File

@@ -46,7 +46,7 @@
} \
} while( 0 )
static char *prefix_strings[] = {
static const char *prefix_strings[] = {
"", /* no prefix */
"repz ", /* the trailing spaces make it easy to prepend to mnemonic */
"repnz ",
@@ -115,7 +115,7 @@ static void get_operand_data_str( x86_op_t *op, char *str, int len ){
static void get_operand_regtype_str( int regtype, char *str, int len )
{
static struct {
char *name;
const char *name;
int value;
} operand_regtypes[] = {
{"reg_gen" , 0x00001},
@@ -284,7 +284,7 @@ static int format_expr( x86_ea_t *ea, char *buf, int len,
static int format_seg( x86_op_t *op, char *buf, int len,
enum x86_asm_format format ) {
int len_orig = len;
char *reg = "";
const char *reg = "";
if (! op || ! buf || ! len || ! op->flags.whole) {
return(0);
@@ -295,8 +295,9 @@ static int format_seg( x86_op_t *op, char *buf, int len,
if (! (int) op->flags.op_seg) {
return(0);
}
switch (op->flags.op_seg) {
uint16_t seg_ov=uint16_t(op->flags.op_seg)<<8;
switch (seg_ov)
{
case x86_op_flags::op_es_seg: reg = "es"; break;
case x86_op_flags::op_cs_seg: reg = "cs"; break;
case x86_op_flags::op_ss_seg: reg = "ss"; break;
@@ -328,9 +329,9 @@ static int format_seg( x86_op_t *op, char *buf, int len,
return( len_orig - len ); /* return length of appended string */
}
static char *get_operand_datatype_str( x86_op_t *op ){
static const char *get_operand_datatype_str( x86_op_t *op ){
static char *types[] = {
static const char *types[] = {
"sbyte", /* 0 */
"sword",
"sqword",
@@ -405,7 +406,7 @@ static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
int len) {
static struct {
char *name;
const char *name;
int value;
} insn_flags[] = {
{ "carry_set ", 0x0001 },
@@ -440,9 +441,9 @@ static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
return( len_orig - len );
}
static char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
static const char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
static char *types[] = {
static const char *types[] = {
"", // 0
"controlflow",// 1
"arithmetic", // 2
@@ -467,10 +468,10 @@ static char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
return types[gp];
}
static char *get_insn_type_str( enum x86_insn_type type ) {
static const char *get_insn_type_str( enum x86_insn_type type ) {
static struct {
char *name;
const char *name;
int value;
} types[] = {
/* insn_controlflow */
@@ -592,8 +593,8 @@ static char *get_insn_type_str( enum x86_insn_type type ) {
return "";
}
static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
static char *intel[] = {
static const char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
static const char *intel[] = {
"", // 0
"8086", // 1
"80286", // 2
@@ -620,8 +621,8 @@ static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
return "";
}
static char *get_insn_isa_str( enum x86_insn_isa isa ) {
static char *subset[] = {
static const char *get_insn_isa_str( enum x86_insn_isa isa ) {
static const char *subset[] = {
NULL, // 0
"General Purpose", // 1
"Floating Point", // 2
@@ -880,11 +881,11 @@ static int format_operand_xml( x86_op_t *op, x86_insn_t *insn, char *buf,
return( strlen( buf ) );
}
static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf,
static int format_operand_raw( x86_op_t *op, x86_insn_t */*insn*/, char *buf,
int len){
char str[MAX_OP_RAW_STRING];
char *datatype = get_operand_datatype_str(op);
const char *datatype = get_operand_datatype_str(op);
switch (op->type) {
case op_register:
@@ -1042,7 +1043,7 @@ char * x86_op_t::format( enum x86_asm_format format ) {
static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
int size = 0;
char *suffix;
const char *suffix;
if (! insn || ! buf || ! len )
return(0);
@@ -1094,7 +1095,6 @@ static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
return ( strlen( buf ) );
}
/** format (sprintf) an instruction mnemonic into 'buf' using specified syntax */
int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
enum x86_asm_format format){
char str[MAX_OP_STRING];
@@ -1137,7 +1137,7 @@ static int format_insn_note(x86_insn_t *insn, char *buf, int len){
return( len_orig - len );
}
static int format_raw_insn( x86_insn_t *insn, char *buf, int len ){
static int format_raw_insn( x86_insn_t *insn, char *buf, size_t len ){
struct op_string opstr = { buf, len };
int i;

View File

@@ -17,7 +17,6 @@ int x86_insn_is_valid( x86_insn_t *insn ) {
return 0;
}
/** \returns false if an instruction is invalid, true if valid */
bool x86_insn_t::is_valid( )
{
if ( this && this->type != insn_invalid && this->size > 0 )
@@ -203,13 +202,12 @@ size_t x86_op_t::operand_size() {
return(4); /* default size */
}
/** set the address (usually RVA) of the insn */
void x86_insn_t::x86_set_insn_addr( uint32_t _addr ) {
addr = _addr;
}
void x86_insn_t::x86_set_insn_offset( unsigned int offset ){
offset = offset;
void x86_insn_t::x86_set_insn_offset( unsigned int _offset ){
offset = _offset;
}
void x86_insn_t::x86_set_insn_function( void * func ){
@@ -220,7 +218,6 @@ void x86_insn_t::x86_set_insn_block( void * _block ){
block = _block;
}
/** set insn->tag to 1 */
void x86_insn_t::x86_tag_insn(){
tag = 1;
}
@@ -229,7 +226,6 @@ void x86_insn_t::x86_untag_insn(){
tag = 0;
}
/** \return insn->tag */
int x86_insn_t::x86_insn_is_tagged(){
return tag;
}

View File

@@ -4,31 +4,31 @@
void x86_insn_t::x86_oplist_append( x86_oplist_t *op ) {
x86_oplist_t *list;
x86_oplist_t *list;
assert(this);
list = operands;
if (! list ) {
operand_count = 1;
/* Note that we have no way of knowing if this is an
list = operands;
if (! list ) {
operand_count = 1;
/* Note that we have no way of knowing if this is an
* exlicit operand or not, since the caller fills
* the x86_op_t after we return. We increase the
* explicit count automatically, and ia32_insn_implicit_ops
* decrements it */
explicit_count = 1;
operands = op;
explicit_count = 1;
operands = op;
return;
}
/* get to end of list */
for ( ; list->next; list = list->next )
;
operand_count = operand_count + 1;
explicit_count = explicit_count + 1;
list->next = op;
return;
}
/* get to end of list */
for ( ; list->next; list = list->next )
;
operand_count = operand_count + 1;
explicit_count = explicit_count + 1;
list->next = op;
return;
}
bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
@@ -48,7 +48,7 @@ bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
return (in & (insn_dir_set | insn_dir_clear))!=0;
case insn_eflag_sign:
return (in & (insn_sign_set | insn_sign_clear | insn_zero_set_or_sign_ne_oflow |
insn_sign_eq_oflow | insn_sign_ne_oflow))!=0;
insn_sign_eq_oflow | insn_sign_ne_oflow))!=0;
case insn_eflag_parity:
return (in & (insn_parity_set | insn_parity_clear))!=0;
}
@@ -56,31 +56,31 @@ bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
}
x86_op_t * x86_insn_t::x86_operand_new( ) {
x86_oplist_t *op;
x86_oplist_t *op;
assert(this);
op = (x86_oplist_t *)calloc( sizeof(x86_oplist_t), 1 );
op->op.insn = this;
x86_oplist_append( op );
return( &(op->op) );
op = (x86_oplist_t *)calloc( sizeof(x86_oplist_t), 1 );
op->op.insn = this;
x86_oplist_append( op );
return( &(op->op) );
}
/** free the operand list associated with an instruction -- useful for
* preventing memory leaks when free()ing an x86_insn_t */
void x86_insn_t::x86_oplist_free( )
{
x86_oplist_t *op, *list;
x86_oplist_t *op, *list;
assert(this);
for ( list = operands; list; ) {
op = list;
list = list->next;
free(op);
}
for ( list = operands; list; ) {
op = list;
list = list->next;
free(op);
}
operands = NULL;
operand_count = 0;
explicit_count = 0;
operands = NULL;
operand_count = 0;
explicit_count = 0;
return;
return;
}
/* ================================================== LIBDISASM API */
@@ -88,122 +88,121 @@ void x86_insn_t::x86_oplist_free( )
enum... yet one more confusing thing in the API */
int x86_insn_t::x86_operand_foreach( x86_operand_fn func, void *arg, enum x86_op_foreach_type type )
{
x86_oplist_t *list;
char _explicit = 1, implicit = 1;
x86_oplist_t *list;
char _explicit = 1, implicit = 1;
assert(this);
if ( ! func ) {
return 0;
}
if ( ! func ) {
return 0;
}
/* note: explicit and implicit can be ORed together to
/* note: explicit and implicit can be ORed together to
* allow an "all" limited by access type, even though the
* user is stupid to do this since it is default behavior :) */
if ( (type & op_explicit) && ! (type & op_implicit) ) {
implicit = 0;
}
if ( (type & op_implicit) && ! (type & op_explicit) ) {
_explicit = 0;
}
type = (x86_op_foreach_type)((int)type & 0x0F); /* mask out explicit/implicit operands */
for ( list = operands; list; list = list->next ) {
if (! implicit && (list->op.flags.op_implied) ) {
/* operand is implicit */
continue;
if ( (type & op_explicit) && ! (type & op_implicit) ) {
implicit = 0;
}
if ( (type & op_implicit) && ! (type & op_explicit) ) {
_explicit = 0;
}
if (! _explicit && ! (list->op.flags.op_implied) ) {
/* operand is not implicit */
continue;
type = (x86_op_foreach_type)((int)type & 0x0F); /* mask out explicit/implicit operands */
for ( list = operands; list; list = list->next ) {
if (! implicit && (list->op.flags.op_implied) ) {
/* operand is implicit */
continue;
}
if (! _explicit && ! (list->op.flags.op_implied) ) {
/* operand is not implicit */
continue;
}
switch ( type ) {
case op_any:
break;
case op_dest:
if (! (list->op.access & op_write) ) {
continue;
}
break;
case op_src:
if (! (list->op.access & op_read) ) {
continue;
}
break;
case op_ro:
if (! (list->op.access & op_read) ||
(list->op.access & op_write ) ) {
continue;
}
break;
case op_wo:
if (! (list->op.access & op_write) ||
(list->op.access & op_read ) ) {
continue;
}
break;
case op_xo:
if (! (list->op.access & op_execute) ) {
continue;
}
break;
case op_rw:
if (! (list->op.access & op_write) ||
! (list->op.access & op_read ) ) {
continue;
}
break;
case op_implicit: case op_explicit: /* make gcc happy */
break;
}
/* any non-continue ends up here: invoke the callback */
(*func)( &list->op, this, arg );
}
switch ( type ) {
case op_any:
break;
case op_dest:
if (! (list->op.access & op_write) ) {
continue;
}
break;
case op_src:
if (! (list->op.access & op_read) ) {
continue;
}
break;
case op_ro:
if (! (list->op.access & op_read) ||
(list->op.access & op_write ) ) {
continue;
}
break;
case op_wo:
if (! (list->op.access & op_write) ||
(list->op.access & op_read ) ) {
continue;
}
break;
case op_xo:
if (! (list->op.access & op_execute) ) {
continue;
}
break;
case op_rw:
if (! (list->op.access & op_write) ||
! (list->op.access & op_read ) ) {
continue;
}
break;
case op_implicit: case op_explicit: /* make gcc happy */
break;
}
/* any non-continue ends up here: invoke the callback */
(*func)( &list->op, this, arg );
}
return 1;
return 1;
}
static void count_operand( x86_op_t *op, x86_insn_t *insn, void *arg ) {
size_t * count = (size_t *) arg;
*count = *count + 1;
static void count_operand( x86_op_t */*op*/, x86_insn_t */*insn*/, void *arg ) {
size_t * count = (size_t *) arg;
*count = *count + 1;
}
/** convenience routine: returns count of operands matching 'type' */
size_t x86_insn_t::x86_operand_count( enum x86_op_foreach_type type ) {
size_t count = 0;
size_t count = 0;
/* save us a list traversal for common counts... */
if ( type == op_any ) {
return operand_count;
} else if ( type == op_explicit ) {
return explicit_count;
}
/* save us a list traversal for common counts... */
if ( type == op_any ) {
return operand_count;
} else if ( type == op_explicit ) {
return explicit_count;
}
x86_operand_foreach( count_operand, &count, type );
return count;
x86_operand_foreach( count_operand, &count, type );
return count;
}
/* accessor functions */
x86_op_t * x86_insn_t::x86_operand_1st() {
if (! explicit_count ) {
return NULL;
}
if (! explicit_count ) {
return NULL;
}
return &(operands->op);
return &(operands->op);
}
x86_op_t * x86_insn_t::x86_operand_2nd( ) {
if ( explicit_count < 2 ) {
return NULL;
}
if ( explicit_count < 2 ) {
return NULL;
}
return &(operands->next->op);
return &(operands->next->op);
}
x86_op_t * x86_insn_t::x86_operand_3rd( ) {
if ( explicit_count < 3 ) {
return NULL;
}
return &(operands->next->next->op);
if ( explicit_count < 3 ) {
return NULL;
}
return &(operands->next->next->op);
}