removed most of clang warnings / errors
This commit is contained in:
parent
9cc5202ff7
commit
ba110a64cb
4
.gitignore
vendored
4
.gitignore
vendored
@ -4,4 +4,6 @@ tests/prev
|
||||
tests/outputs/*
|
||||
tests/errors
|
||||
*.autosave
|
||||
bld*
|
||||
bld*
|
||||
*.user
|
||||
*.idb
|
||||
|
||||
666
3rd_party/libdisasm/ia32_implicit.cpp
vendored
666
3rd_party/libdisasm/ia32_implicit.cpp
vendored
@ -5,7 +5,7 @@
|
||||
#include "ia32_reg.h"
|
||||
#include "x86_operand_list.h"
|
||||
|
||||
/* Conventions: Register operands which are aliases of another register
|
||||
/* Conventions: Register operands which are aliases of another register
|
||||
* operand (e.g. AX in one operand and AL in another) assume that the
|
||||
* operands are different registers and that alias tracking will resolve
|
||||
* data flow. This means that something like
|
||||
@ -13,412 +13,412 @@
|
||||
* would have 'write only' access for AX and 'read only' access for AL,
|
||||
* even though both AL and AX are read and written */
|
||||
typedef struct {
|
||||
uint32_t type;
|
||||
uint32_t operand;
|
||||
uint32_t type;
|
||||
uint32_t operand;
|
||||
} op_implicit_list_t;
|
||||
|
||||
static op_implicit_list_t list_aaa[] =
|
||||
/* 37 : AAA : rw AL */
|
||||
/* 3F : AAS : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* aaa */
|
||||
static op_implicit_list_t list_aaa[] =
|
||||
/* 37 : AAA : rw AL */
|
||||
/* 3F : AAS : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* aaa */
|
||||
|
||||
static op_implicit_list_t list_aad[] =
|
||||
/* D5 0A, D5 (ib) : AAD : rw AX */
|
||||
/* D4 0A, D4 (ib) : AAM : rw AX */
|
||||
{{ OP_R | OP_W, REG_WORD_OFFSET }, {0}}; /* aad */
|
||||
static op_implicit_list_t list_aad[] =
|
||||
/* D5 0A, D5 (ib) : AAD : rw AX */
|
||||
/* D4 0A, D4 (ib) : AAM : rw AX */
|
||||
{{ OP_R | OP_W, REG_WORD_OFFSET }, {0,0}}; /* aad */
|
||||
|
||||
static op_implicit_list_t list_call[] =
|
||||
/* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
|
||||
/* C2, C3, CA, CB : RET : rw ESP, rw EIP */
|
||||
{{ OP_R | OP_W, REG_EIP_INDEX },
|
||||
{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* call, ret */
|
||||
static op_implicit_list_t list_call[] =
|
||||
/* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
|
||||
/* C2, C3, CA, CB : RET : rw ESP, rw EIP */
|
||||
{{ OP_R | OP_W, REG_EIP_INDEX },
|
||||
{ OP_R | OP_W, REG_ESP_INDEX }, {0,0}}; /* call, ret */
|
||||
|
||||
static op_implicit_list_t list_cbw[] =
|
||||
/* 98 : CBW : r AL, rw AX */
|
||||
{{ OP_R | OP_W, REG_WORD_OFFSET },
|
||||
{ OP_R, REG_BYTE_OFFSET}, {0}}; /* cbw */
|
||||
static op_implicit_list_t list_cbw[] =
|
||||
/* 98 : CBW : r AL, rw AX */
|
||||
{{ OP_R | OP_W, REG_WORD_OFFSET },
|
||||
{ OP_R, REG_BYTE_OFFSET}, {0,0}}; /* cbw */
|
||||
|
||||
static op_implicit_list_t list_cwde[] =
|
||||
/* 98 : CWDE : r AX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_R, REG_WORD_OFFSET }, {0}}; /* cwde */
|
||||
static op_implicit_list_t list_cwde[] =
|
||||
/* 98 : CWDE : r AX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_R, REG_WORD_OFFSET }, {0,0}}; /* cwde */
|
||||
|
||||
static op_implicit_list_t list_clts[] =
|
||||
/* 0F 06 : CLTS : rw CR0 */
|
||||
{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0}}; /* clts */
|
||||
static op_implicit_list_t list_clts[] =
|
||||
/* 0F 06 : CLTS : rw CR0 */
|
||||
{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0,0}}; /* clts */
|
||||
|
||||
static op_implicit_list_t list_cmpxchg[] =
|
||||
/* 0F B0 : CMPXCHG : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* cmpxchg */
|
||||
static op_implicit_list_t list_cmpxchg[] =
|
||||
/* 0F B0 : CMPXCHG : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* cmpxchg */
|
||||
|
||||
static op_implicit_list_t list_cmpxchgb[] =
|
||||
/* 0F B1 : CMPXCHG : rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* cmpxchg */
|
||||
static op_implicit_list_t list_cmpxchgb[] =
|
||||
/* 0F B1 : CMPXCHG : rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* cmpxchg */
|
||||
|
||||
static op_implicit_list_t list_cmpxchg8b[] =
|
||||
/* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 3 }, {0}}; /* cmpxchg8b */
|
||||
static op_implicit_list_t list_cmpxchg8b[] =
|
||||
/* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cmpxchg8b */
|
||||
|
||||
static op_implicit_list_t list_cpuid[] =
|
||||
/* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 3 }, {0}}; /* cpuid */
|
||||
static op_implicit_list_t list_cpuid[] =
|
||||
/* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cpuid */
|
||||
|
||||
static op_implicit_list_t list_cwd[] =
|
||||
/* 99 : CWD/CWQ : rw EAX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* cwd */
|
||||
static op_implicit_list_t list_cwd[] =
|
||||
/* 99 : CWD/CWQ : rw EAX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* cwd */
|
||||
|
||||
static op_implicit_list_t list_daa[] =
|
||||
/* 27 : DAA : rw AL */
|
||||
/* 2F : DAS : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* daa */
|
||||
static op_implicit_list_t list_daa[] =
|
||||
/* 27 : DAA : rw AL */
|
||||
/* 2F : DAS : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* daa */
|
||||
|
||||
static op_implicit_list_t list_idiv[] =
|
||||
/* F6 : DIV, IDIV : r AX, w AL, w AH */
|
||||
/* FIXED: first op was EAX, not Aw. TODO: verify! */
|
||||
{{ OP_R, REG_WORD_OFFSET },
|
||||
{ OP_W, REG_BYTE_OFFSET },
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* div */
|
||||
static op_implicit_list_t list_idiv[] =
|
||||
/* F6 : DIV, IDIV : r AX, w AL, w AH */
|
||||
/* FIXED: first op was EAX, not Aw. TODO: verify! */
|
||||
{{ OP_R, REG_WORD_OFFSET },
|
||||
{ OP_W, REG_BYTE_OFFSET },
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* div */
|
||||
|
||||
static op_implicit_list_t list_div[] =
|
||||
/* F7 : DIV, IDIV : rw EDX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* div */
|
||||
static op_implicit_list_t list_div[] =
|
||||
/* F7 : DIV, IDIV : rw EDX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* div */
|
||||
|
||||
static op_implicit_list_t list_enter[] =
|
||||
/* C8 : ENTER : rw ESP w EBP */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 4 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 5 }, {0}}; /* enter */
|
||||
static op_implicit_list_t list_enter[] =
|
||||
/* C8 : ENTER : rw ESP w EBP */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 4 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 5 }, {0,0}}; /* enter */
|
||||
|
||||
static op_implicit_list_t list_f2xm1[] =
|
||||
/* D9 F0 : F2XM1 : rw ST(0) */
|
||||
/* D9 E1 : FABS : rw ST(0) */
|
||||
/* D9 E0 : FCHS : rw ST(0) */
|
||||
/* D9 FF : FCOS : rw ST(0)*/
|
||||
/* D8, DA : FDIV : rw ST(0) */
|
||||
/* D8, DA : FDIVR : rw ST(0) */
|
||||
/* D9 F2 : FPTAN : rw ST(0) */
|
||||
/* D9 FC : FRNDINT : rw ST(0) */
|
||||
/* D9 FB : FSINCOS : rw ST(0) */
|
||||
/* D9 FE : FSIN : rw ST(0) */
|
||||
/* D9 FA : FSQRT : rw ST(0) */
|
||||
/* D9 F4 : FXTRACT : rw ST(0) */
|
||||
{{ OP_R | OP_W, REG_FPU_OFFSET }, {0}}; /* f2xm1 */
|
||||
static op_implicit_list_t list_f2xm1[] =
|
||||
/* D9 F0 : F2XM1 : rw ST(0) */
|
||||
/* D9 E1 : FABS : rw ST(0) */
|
||||
/* D9 E0 : FCHS : rw ST(0) */
|
||||
/* D9 FF : FCOS : rw ST(0)*/
|
||||
/* D8, DA : FDIV : rw ST(0) */
|
||||
/* D8, DA : FDIVR : rw ST(0) */
|
||||
/* D9 F2 : FPTAN : rw ST(0) */
|
||||
/* D9 FC : FRNDINT : rw ST(0) */
|
||||
/* D9 FB : FSINCOS : rw ST(0) */
|
||||
/* D9 FE : FSIN : rw ST(0) */
|
||||
/* D9 FA : FSQRT : rw ST(0) */
|
||||
/* D9 F4 : FXTRACT : rw ST(0) */
|
||||
{{ OP_R | OP_W, REG_FPU_OFFSET }, {0,0}}; /* f2xm1 */
|
||||
|
||||
static op_implicit_list_t list_fcom[] =
|
||||
/* D8, DC, DE D9 : FCOM : r ST(0) */
|
||||
/* DE, DA : FICOM : r ST(0) */
|
||||
/* DF, D8 : FIST : r ST(0) */
|
||||
/* D9 E4 : FTST : r ST(0) */
|
||||
/* D9 E5 : FXAM : r ST(0) */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0}}; /* fcom */
|
||||
static op_implicit_list_t list_fcom[] =
|
||||
/* D8, DC, DE D9 : FCOM : r ST(0) */
|
||||
/* DE, DA : FICOM : r ST(0) */
|
||||
/* DF, D8 : FIST : r ST(0) */
|
||||
/* D9 E4 : FTST : r ST(0) */
|
||||
/* D9 E5 : FXAM : r ST(0) */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fcom */
|
||||
|
||||
static op_implicit_list_t list_fpatan[] =
|
||||
/* D9 F3 : FPATAN : r ST(0), rw ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0}}; /* fpatan */
|
||||
static op_implicit_list_t list_fpatan[] =
|
||||
/* D9 F3 : FPATAN : r ST(0), rw ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fpatan */
|
||||
|
||||
static op_implicit_list_t list_fprem[] =
|
||||
/* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
|
||||
/* D9 FD : FSCALE : rw ST(0), r ST(1) */
|
||||
{{ OP_R | OP_W, REG_FPU_OFFSET },
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fprem */
|
||||
static op_implicit_list_t list_fprem[] =
|
||||
/* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
|
||||
/* D9 FD : FSCALE : rw ST(0), r ST(1) */
|
||||
{{ OP_R | OP_W, REG_FPU_OFFSET },
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fprem */
|
||||
|
||||
static op_implicit_list_t list_faddp[] =
|
||||
/* DE C1 : FADDP : r ST(0), rw ST(1) */
|
||||
/* DE E9 : FSUBP : r ST(0), rw ST(1) */
|
||||
/* D9 F1 : FYL2X : r ST(0), rw ST(1) */
|
||||
/* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET },
|
||||
{ OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0}}; /* faddp */
|
||||
static op_implicit_list_t list_faddp[] =
|
||||
/* DE C1 : FADDP : r ST(0), rw ST(1) */
|
||||
/* DE E9 : FSUBP : r ST(0), rw ST(1) */
|
||||
/* D9 F1 : FYL2X : r ST(0), rw ST(1) */
|
||||
/* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET },
|
||||
{ OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0,0}}; /* faddp */
|
||||
|
||||
static op_implicit_list_t list_fucompp[] =
|
||||
/* DA E9 : FUCOMPP : r ST(0), r ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET },
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fucompp */
|
||||
static op_implicit_list_t list_fucompp[] =
|
||||
/* DA E9 : FUCOMPP : r ST(0), r ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET },
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fucompp */
|
||||
|
||||
static op_implicit_list_t list_imul[] =
|
||||
/* F6 : IMUL : r AL, w AX */
|
||||
/* F6 : MUL : r AL, w AX */
|
||||
{{ OP_R, REG_BYTE_OFFSET },
|
||||
{ OP_W, REG_WORD_OFFSET }, {0}}; /* imul */
|
||||
static op_implicit_list_t list_imul[] =
|
||||
/* F6 : IMUL : r AL, w AX */
|
||||
/* F6 : MUL : r AL, w AX */
|
||||
{{ OP_R, REG_BYTE_OFFSET },
|
||||
{ OP_W, REG_WORD_OFFSET }, {0,0}}; /* imul */
|
||||
|
||||
static op_implicit_list_t list_mul[] =
|
||||
/* F7 : IMUL : rw EAX, w EDX */
|
||||
/* F7 : MUL : rw EAX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* imul */
|
||||
static op_implicit_list_t list_mul[] =
|
||||
/* F7 : IMUL : rw EAX, w EDX */
|
||||
/* F7 : MUL : rw EAX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* imul */
|
||||
|
||||
static op_implicit_list_t list_lahf[] =
|
||||
/* 9F : LAHF : r EFLAGS, w AH */
|
||||
{{ OP_R, REG_FLAGS_INDEX },
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* lahf */
|
||||
static op_implicit_list_t list_lahf[] =
|
||||
/* 9F : LAHF : r EFLAGS, w AH */
|
||||
{{ OP_R, REG_FLAGS_INDEX },
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* lahf */
|
||||
|
||||
static op_implicit_list_t list_ldmxcsr[] =
|
||||
/* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
|
||||
{{ OP_W, REG_MXCSG_INDEX }, {0}}; /* ldmxcsr */
|
||||
static op_implicit_list_t list_ldmxcsr[] =
|
||||
/* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
|
||||
{{ OP_W, REG_MXCSG_INDEX }, {0,0}}; /* ldmxcsr */
|
||||
|
||||
static op_implicit_list_t list_leave[] =
|
||||
/* C9 : LEAVE : rw ESP, w EBP */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_DWORD_OFFSET + 5 }, {0}}; /* leave */
|
||||
static op_implicit_list_t list_leave[] =
|
||||
/* C9 : LEAVE : rw ESP, w EBP */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_DWORD_OFFSET + 5 }, {0,0}}; /* leave */
|
||||
|
||||
static op_implicit_list_t list_lgdt[] =
|
||||
/* 0F 01 : LGDT : w GDTR */
|
||||
{{ OP_W, REG_GDTR_INDEX }, {0}}; /* lgdt */
|
||||
static op_implicit_list_t list_lgdt[] =
|
||||
/* 0F 01 : LGDT : w GDTR */
|
||||
{{ OP_W, REG_GDTR_INDEX }, {0,0}}; /* lgdt */
|
||||
|
||||
static op_implicit_list_t list_lidt[] =
|
||||
/* 0F 01 : LIDT : w IDTR */
|
||||
{{ OP_W, REG_IDTR_INDEX }, {0}}; /* lidt */
|
||||
static op_implicit_list_t list_lidt[] =
|
||||
/* 0F 01 : LIDT : w IDTR */
|
||||
{{ OP_W, REG_IDTR_INDEX }, {0,0}}; /* lidt */
|
||||
|
||||
static op_implicit_list_t list_lldt[] =
|
||||
/* 0F 00 : LLDT : w LDTR */
|
||||
{{ OP_W, REG_LDTR_INDEX }, {0}}; /* lldt */
|
||||
static op_implicit_list_t list_lldt[] =
|
||||
/* 0F 00 : LLDT : w LDTR */
|
||||
{{ OP_W, REG_LDTR_INDEX }, {0,0}}; /* lldt */
|
||||
|
||||
static op_implicit_list_t list_lmsw[] =
|
||||
/* 0F 01 : LMSW : w CR0 */
|
||||
{{ OP_W, REG_CTRL_OFFSET }, {0}}; /* lmsw */
|
||||
static op_implicit_list_t list_lmsw[] =
|
||||
/* 0F 01 : LMSW : w CR0 */
|
||||
{{ OP_W, REG_CTRL_OFFSET }, {0,0}}; /* lmsw */
|
||||
|
||||
static op_implicit_list_t list_loop[] =
|
||||
/* E0, E1, E2 : LOOP : rw ECX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* loop */
|
||||
static op_implicit_list_t list_loop[] =
|
||||
/* E0, E1, E2 : LOOP : rw ECX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* loop */
|
||||
|
||||
static op_implicit_list_t list_ltr[] =
|
||||
/* 0F 00 : LTR : w Task Register */
|
||||
{{ OP_W, REG_TR_INDEX }, {0}}; /* ltr */
|
||||
static op_implicit_list_t list_ltr[] =
|
||||
/* 0F 00 : LTR : w Task Register */
|
||||
{{ OP_W, REG_TR_INDEX }, {0,0}}; /* ltr */
|
||||
|
||||
static op_implicit_list_t list_pop[] =
|
||||
/* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */
|
||||
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* pop, push */
|
||||
static op_implicit_list_t list_pop[] =
|
||||
/* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */
|
||||
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX }, {0,0}}; /* pop, push */
|
||||
|
||||
static op_implicit_list_t list_popad[] =
|
||||
/* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_DWORD_OFFSET + 7 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 6 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 5 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 3 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* popad */
|
||||
static op_implicit_list_t list_popad[] =
|
||||
/* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_DWORD_OFFSET + 7 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 6 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 5 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 3 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* popad */
|
||||
|
||||
static op_implicit_list_t list_popfd[] =
|
||||
/* 9D : POPFD : rw esp, w eflags */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_FLAGS_INDEX }, {0}}; /* popfd */
|
||||
static op_implicit_list_t list_popfd[] =
|
||||
/* 9D : POPFD : rw esp, w eflags */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_FLAGS_INDEX }, {0,0}}; /* popfd */
|
||||
|
||||
static op_implicit_list_t list_pushad[] =
|
||||
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
|
||||
/* 60 : PUSHAD : rw esp, r eax ecx edx ebx esp ebp esi edi */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_R, REG_DWORD_OFFSET },
|
||||
{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 3 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 5 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 6 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 7 }, {0}}; /* pushad */
|
||||
static op_implicit_list_t list_pushad[] =
|
||||
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
|
||||
/* 60 : PUSHAD : rw esp, r eax ecx edx ebx esp ebp esi edi */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_R, REG_DWORD_OFFSET },
|
||||
{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 3 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 5 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 6 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 7 }, {0,0}}; /* pushad */
|
||||
|
||||
static op_implicit_list_t list_pushfd[] =
|
||||
/* 9C : PUSHFD : rw esp, r eflags */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_R, REG_FLAGS_INDEX }, {0}}; /* pushfd */
|
||||
static op_implicit_list_t list_pushfd[] =
|
||||
/* 9C : PUSHFD : rw esp, r eflags */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_R, REG_FLAGS_INDEX }, {0,0}}; /* pushfd */
|
||||
|
||||
static op_implicit_list_t list_rdmsr[] =
|
||||
/* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
|
||||
{{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* rdmsr */
|
||||
static op_implicit_list_t list_rdmsr[] =
|
||||
/* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
|
||||
{{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdmsr */
|
||||
|
||||
static op_implicit_list_t list_rdpmc[] =
|
||||
/* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
|
||||
{{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* rdpmc */
|
||||
static op_implicit_list_t list_rdpmc[] =
|
||||
/* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
|
||||
{{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdpmc */
|
||||
|
||||
static op_implicit_list_t list_rdtsc[] =
|
||||
/* 0F 31 : RDTSC : rw EDX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* rdtsc */
|
||||
static op_implicit_list_t list_rdtsc[] =
|
||||
/* 0F 31 : RDTSC : rw EDX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdtsc */
|
||||
|
||||
static op_implicit_list_t list_rep[] =
|
||||
/* F3, F2 ... : REP : rw ECX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* rep */
|
||||
static op_implicit_list_t list_rep[] =
|
||||
/* F3, F2 ... : REP : rw ECX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* rep */
|
||||
|
||||
static op_implicit_list_t list_rsm[] =
|
||||
/* 0F AA : RSM : r CR4, r CR0 */
|
||||
{{ OP_R, REG_CTRL_OFFSET + 4 },
|
||||
{ OP_R, REG_CTRL_OFFSET }, {0}}; /* rsm */
|
||||
static op_implicit_list_t list_rsm[] =
|
||||
/* 0F AA : RSM : r CR4, r CR0 */
|
||||
{{ OP_R, REG_CTRL_OFFSET + 4 },
|
||||
{ OP_R, REG_CTRL_OFFSET }, {0,0}}; /* rsm */
|
||||
|
||||
static op_implicit_list_t list_sahf[] =
|
||||
/* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sahf */
|
||||
static op_implicit_list_t list_sahf[] =
|
||||
/* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sahf */
|
||||
|
||||
static op_implicit_list_t list_sgdt[] =
|
||||
/* 0F : SGDT : r gdtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sgdt */
|
||||
static op_implicit_list_t list_sgdt[] =
|
||||
/* 0F : SGDT : r gdtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sgdt */
|
||||
|
||||
static op_implicit_list_t list_sidt[] =
|
||||
/* 0F : SIDT : r idtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sidt */
|
||||
static op_implicit_list_t list_sidt[] =
|
||||
/* 0F : SIDT : r idtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sidt */
|
||||
|
||||
static op_implicit_list_t list_sldt[] =
|
||||
/* 0F : SLDT : r ldtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sldt */
|
||||
static op_implicit_list_t list_sldt[] =
|
||||
/* 0F : SLDT : r ldtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sldt */
|
||||
|
||||
static op_implicit_list_t list_smsw[] =
|
||||
/* 0F : SMSW : r CR0 */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* smsw */
|
||||
static op_implicit_list_t list_smsw[] =
|
||||
/* 0F : SMSW : r CR0 */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* smsw */
|
||||
|
||||
static op_implicit_list_t list_stmxcsr[] =
|
||||
/* 0F AE : STMXCSR : r MXCSR */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* stmxcsr */
|
||||
static op_implicit_list_t list_stmxcsr[] =
|
||||
/* 0F AE : STMXCSR : r MXCSR */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* stmxcsr */
|
||||
|
||||
static op_implicit_list_t list_str[] =
|
||||
/* 0F 00 : STR : r TR (task register) */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* str */
|
||||
static op_implicit_list_t list_str[] =
|
||||
/* 0F 00 : STR : r TR (task register) */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* str */
|
||||
|
||||
static op_implicit_list_t list_sysenter[] =
|
||||
/* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags
|
||||
* r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysenter */
|
||||
static op_implicit_list_t list_sysenter[] =
|
||||
/* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags
|
||||
* r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysenter */
|
||||
|
||||
static op_implicit_list_t list_sysexit[] =
|
||||
/* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
|
||||
* r sysenter_cs_msr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysexit */
|
||||
static op_implicit_list_t list_sysexit[] =
|
||||
/* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
|
||||
* r sysenter_cs_msr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysexit */
|
||||
|
||||
static op_implicit_list_t list_wrmsr[] =
|
||||
/* 0F 30 : WRMST : r edx, r eax, r ecx */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* wrmsr */
|
||||
static op_implicit_list_t list_wrmsr[] =
|
||||
/* 0F 30 : WRMST : r edx, r eax, r ecx */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* wrmsr */
|
||||
|
||||
static op_implicit_list_t list_xlat[] =
|
||||
/* D7 : XLAT : rw al r ebx (ptr) */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* xlat */
|
||||
static op_implicit_list_t list_xlat[] =
|
||||
/* D7 : XLAT : rw al r ebx (ptr) */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* xlat */
|
||||
/* TODO:
|
||||
* monitor 0f 01 c8 eax OP_R ecx OP_R edx OP_R
|
||||
* mwait 0f 01 c9 eax OP_R ecx OP_R
|
||||
*/
|
||||
static op_implicit_list_t list_monitor[] =
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* monitor */
|
||||
static op_implicit_list_t list_mwait[] =
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* mwait */
|
||||
static op_implicit_list_t list_monitor[] =
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* monitor */
|
||||
static op_implicit_list_t list_mwait[] =
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* mwait */
|
||||
|
||||
op_implicit_list_t *op_implicit_list[] = {
|
||||
/* This is a list of implicit operands which are read/written by
|
||||
* various x86 instructions. Note that modifications to the stack
|
||||
* register are mentioned here, but that additional information on
|
||||
* the effect an instruction has on the stack is contained in the
|
||||
* x86_insn_t 'stack_mod' and 'stack_mod_val' fields. Use of the
|
||||
* eflags register, i.e. setting, clearing, and testing flags, is
|
||||
* not recorded here but rather in the flags_set and flags_tested
|
||||
* fields of the x86_insn_t.*/
|
||||
NULL,
|
||||
list_aaa, list_aad, list_call, list_cbw, /* 1 - 4 */
|
||||
list_cwde, list_clts, list_cmpxchg, list_cmpxchgb, /* 5 - 8 */
|
||||
list_cmpxchg8b, list_cpuid, list_cwd, list_daa, /* 9 - 12 */
|
||||
list_idiv, list_div, list_enter, list_f2xm1, /* 13 - 16 */
|
||||
list_fcom, list_fpatan, list_fprem, list_faddp, /* 17 - 20 */
|
||||
list_fucompp, list_imul, list_mul, list_lahf, /* 21 - 24 */
|
||||
list_ldmxcsr, list_leave, list_lgdt, list_lidt, /* 25 - 28 */
|
||||
list_lldt, list_lmsw, list_loop, list_ltr, /* 29 - 32 */
|
||||
list_pop, list_popad, list_popfd, list_pushad, /* 33 - 36 */
|
||||
list_pushfd, list_rdmsr, list_rdpmc, list_rdtsc, /* 37 - 40 */
|
||||
/* NOTE: 'REP' is a hack since it is a prefix: if its position
|
||||
* in the table changes, then change IDX_IMPLICIT_REP in the .h */
|
||||
list_rep, list_rsm, list_sahf, list_sgdt, /* 41 - 44 */
|
||||
list_sidt, list_sldt, list_smsw, list_stmxcsr, /* 45 - 48 */
|
||||
list_str, list_sysenter, list_sysexit, list_wrmsr, /* 49 - 52 */
|
||||
list_xlat, list_monitor, list_mwait, /* 53 - 55*/
|
||||
NULL /* end of list */
|
||||
};
|
||||
/* This is a list of implicit operands which are read/written by
|
||||
* various x86 instructions. Note that modifications to the stack
|
||||
* register are mentioned here, but that additional information on
|
||||
* the effect an instruction has on the stack is contained in the
|
||||
* x86_insn_t 'stack_mod' and 'stack_mod_val' fields. Use of the
|
||||
* eflags register, i.e. setting, clearing, and testing flags, is
|
||||
* not recorded here but rather in the flags_set and flags_tested
|
||||
* fields of the x86_insn_t.*/
|
||||
NULL,
|
||||
list_aaa, list_aad, list_call, list_cbw, /* 1 - 4 */
|
||||
list_cwde, list_clts, list_cmpxchg, list_cmpxchgb, /* 5 - 8 */
|
||||
list_cmpxchg8b, list_cpuid, list_cwd, list_daa, /* 9 - 12 */
|
||||
list_idiv, list_div, list_enter, list_f2xm1, /* 13 - 16 */
|
||||
list_fcom, list_fpatan, list_fprem, list_faddp, /* 17 - 20 */
|
||||
list_fucompp, list_imul, list_mul, list_lahf, /* 21 - 24 */
|
||||
list_ldmxcsr, list_leave, list_lgdt, list_lidt, /* 25 - 28 */
|
||||
list_lldt, list_lmsw, list_loop, list_ltr, /* 29 - 32 */
|
||||
list_pop, list_popad, list_popfd, list_pushad, /* 33 - 36 */
|
||||
list_pushfd, list_rdmsr, list_rdpmc, list_rdtsc, /* 37 - 40 */
|
||||
/* NOTE: 'REP' is a hack since it is a prefix: if its position
|
||||
* in the table changes, then change IDX_IMPLICIT_REP in the .h */
|
||||
list_rep, list_rsm, list_sahf, list_sgdt, /* 41 - 44 */
|
||||
list_sidt, list_sldt, list_smsw, list_stmxcsr, /* 45 - 48 */
|
||||
list_str, list_sysenter, list_sysexit, list_wrmsr, /* 49 - 52 */
|
||||
list_xlat, list_monitor, list_mwait, /* 53 - 55*/
|
||||
NULL /* end of list */
|
||||
};
|
||||
|
||||
#define LAST_IMPL_IDX 55
|
||||
|
||||
static void handle_impl_reg( x86_op_t *op, uint32_t val ) {
|
||||
x86_reg_t *reg = &op->data.reg;
|
||||
op->type = op_register;
|
||||
ia32_handle_register( reg, (unsigned int) val );
|
||||
switch (reg->size) {
|
||||
case 1:
|
||||
op->datatype = op_byte; break;
|
||||
case 2:
|
||||
op->datatype = op_word; break;
|
||||
case 4:
|
||||
op->datatype = op_dword; break;
|
||||
case 8:
|
||||
op->datatype = op_qword; break;
|
||||
case 10:
|
||||
op->datatype = op_extreal; break;
|
||||
case 16:
|
||||
op->datatype = op_dqword; break;
|
||||
}
|
||||
return;
|
||||
x86_reg_t *reg = &op->data.reg;
|
||||
op->type = op_register;
|
||||
ia32_handle_register( reg, (unsigned int) val );
|
||||
switch (reg->size) {
|
||||
case 1:
|
||||
op->datatype = op_byte; break;
|
||||
case 2:
|
||||
op->datatype = op_word; break;
|
||||
case 4:
|
||||
op->datatype = op_dword; break;
|
||||
case 8:
|
||||
op->datatype = op_qword; break;
|
||||
case 10:
|
||||
op->datatype = op_extreal; break;
|
||||
case 16:
|
||||
op->datatype = op_dqword; break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* 'impl_idx' is the value from the opcode table: between 1 and LAST_IMPL_IDX */
|
||||
/* returns number of operands added */
|
||||
unsigned int Ia32_Decoder::ia32_insn_implicit_ops( unsigned int impl_idx ) {
|
||||
op_implicit_list_t *list;
|
||||
x86_oplist_t * existing=0;
|
||||
x86_op_t *op;
|
||||
unsigned int num = 0;
|
||||
op_implicit_list_t *list;
|
||||
x86_oplist_t * existing=0;
|
||||
x86_op_t *op;
|
||||
unsigned int num = 0;
|
||||
|
||||
if (! impl_idx || impl_idx > LAST_IMPL_IDX ) {
|
||||
return 0;
|
||||
}
|
||||
if (! impl_idx || impl_idx > LAST_IMPL_IDX ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( list = op_implicit_list[impl_idx]; list->type; list++, num++ ) {
|
||||
enum x86_op_access access = (enum x86_op_access) OP_PERM(list->type);
|
||||
x86_op_flags flags;
|
||||
for ( list = op_implicit_list[impl_idx]; list->type; list++, num++ ) {
|
||||
enum x86_op_access access = (enum x86_op_access) OP_PERM(list->type);
|
||||
x86_op_flags flags;
|
||||
flags.whole = (OP_FLAGS(list->type) >> 12);
|
||||
|
||||
op = NULL;
|
||||
/* In some cases (MUL), EAX is an implicit operand hardcoded in
|
||||
op = NULL;
|
||||
/* In some cases (MUL), EAX is an implicit operand hardcoded in
|
||||
* the instruction without being explicitly listed in assembly.
|
||||
* For this situation, find the hardcoded operand and add the
|
||||
* implied flag rather than adding a new implicit operand. */
|
||||
existing=0;
|
||||
if (ia32_true_register_id(list->operand) == REG_DWORD_OFFSET) {
|
||||
for ( existing = m_decoded->operands; existing; existing = existing->next ) {
|
||||
if (existing->op.type == op_register &&
|
||||
existing->op.data.reg.id == list->operand) {
|
||||
op = &existing->op;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!op) {
|
||||
op = m_decoded->x86_operand_new();
|
||||
/* all implicit operands are registers */
|
||||
handle_impl_reg( op, list->operand );
|
||||
/* decrement the 'explicit count' incremented by default in
|
||||
* x86_operand_new */
|
||||
m_decoded->explicit_count = m_decoded->explicit_count -1;
|
||||
}
|
||||
if (!op) {
|
||||
return num; /* gah! return early */
|
||||
}
|
||||
op->access = x86_op_access((int)op->access | (int)access);
|
||||
op->flags.whole |= flags.whole;
|
||||
op->flags.op_implied=true;
|
||||
}
|
||||
|
||||
return num;
|
||||
existing=0;
|
||||
if (ia32_true_register_id(list->operand) == REG_DWORD_OFFSET) {
|
||||
for ( existing = m_decoded->operands; existing; existing = existing->next ) {
|
||||
if (existing->op.type == op_register &&
|
||||
existing->op.data.reg.id == list->operand) {
|
||||
op = &existing->op;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!op) {
|
||||
op = m_decoded->x86_operand_new();
|
||||
/* all implicit operands are registers */
|
||||
handle_impl_reg( op, list->operand );
|
||||
/* decrement the 'explicit count' incremented by default in
|
||||
* x86_operand_new */
|
||||
m_decoded->explicit_count = m_decoded->explicit_count -1;
|
||||
}
|
||||
if (!op) {
|
||||
return num; /* gah! return early */
|
||||
}
|
||||
op->access = x86_op_access((int)op->access | (int)access);
|
||||
op->flags.whole |= flags.whole;
|
||||
op->flags.op_implied=true;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
6
3rd_party/libdisasm/ia32_insn.cpp
vendored
6
3rd_party/libdisasm/ia32_insn.cpp
vendored
@ -240,7 +240,7 @@ void Ia32_Decoder::ia32_handle_prefix( unsigned int prefixes ) {
|
||||
}
|
||||
|
||||
|
||||
static void reg_32_to_16( x86_op_t *op, x86_insn_t *insn, void *arg ) {
|
||||
static void reg_32_to_16( x86_op_t *op, x86_insn_t */*insn*/, void */*arg*/ ) {
|
||||
|
||||
/* if this is a 32-bit register and it is a general register ... */
|
||||
if ( op->type == op_register && op->data.reg.size == 4 &&
|
||||
@ -539,12 +539,12 @@ size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
|
||||
|
||||
size_t Ia32_Decoder::handle_insn_suffix( unsigned char *buf, size_t buf_len,
|
||||
ia32_insn_t *raw_insn ) {
|
||||
ia32_table_desc_t *table_desc;
|
||||
// ia32_table_desc_t *table_desc;
|
||||
ia32_insn_t *sfx_insn;
|
||||
size_t size;
|
||||
unsigned int prefixes = 0;
|
||||
|
||||
table_desc = &ia32_tables[raw_insn->table];
|
||||
// table_desc = &ia32_tables[raw_insn->table];
|
||||
size = ia32_table_lookup( buf, buf_len, raw_insn->table, &sfx_insn,
|
||||
&prefixes );
|
||||
if (size == INVALID_INSN || sfx_insn->mnem_flag == INS_INVALID ) {
|
||||
|
||||
421
3rd_party/libdisasm/ia32_invariant.cpp
vendored
421
3rd_party/libdisasm/ia32_invariant.cpp
vendored
@ -9,8 +9,8 @@ extern ia32_table_desc_t *ia32_tables;
|
||||
extern ia32_settings_t ia32_settings;
|
||||
|
||||
extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
|
||||
unsigned int table, ia32_insn_t **raw_insn,
|
||||
unsigned int *prefixes );
|
||||
unsigned int table, ia32_insn_t **raw_insn,
|
||||
unsigned int *prefixes );
|
||||
|
||||
|
||||
/* -------------------------------- ModR/M, SIB */
|
||||
@ -47,10 +47,10 @@ extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
|
||||
#define SIB_SCALE_NOBASE 0x00
|
||||
|
||||
/* Convenience struct for modR/M bitfield */
|
||||
struct modRM_byte {
|
||||
struct modRM_byte {
|
||||
unsigned int mod : 2;
|
||||
unsigned int reg : 3;
|
||||
unsigned int rm : 3;
|
||||
unsigned int rm : 3;
|
||||
};
|
||||
|
||||
/* Convenience struct for SIB bitfield */
|
||||
@ -65,248 +65,249 @@ static void byte_decode(unsigned char b, struct modRM_byte *modrm) {
|
||||
#else
|
||||
static inline void byte_decode(unsigned char b, struct modRM_byte *modrm) {
|
||||
#endif
|
||||
/* generic bitfield-packing routine */
|
||||
/* generic bitfield-packing routine */
|
||||
|
||||
modrm->mod = b >> 6; /* top 2 bits */
|
||||
modrm->reg = (b & 56) >> 3; /* middle 3 bits */
|
||||
modrm->rm = b & 7; /* bottom 3 bits */
|
||||
modrm->mod = b >> 6; /* top 2 bits */
|
||||
modrm->reg = (b & 56) >> 3; /* middle 3 bits */
|
||||
modrm->rm = b & 7; /* bottom 3 bits */
|
||||
}
|
||||
static int ia32_invariant_modrm( unsigned char *in, unsigned char *out,
|
||||
unsigned int mode_16, x86_invariant_op_t *op) {
|
||||
struct modRM_byte modrm;
|
||||
struct SIB_byte sib;
|
||||
unsigned char *c, *cin;
|
||||
unsigned short *s;
|
||||
unsigned int *i;
|
||||
int size = 0; /* modrm byte is already counted */
|
||||
unsigned int mode_16, x86_invariant_op_t *op) {
|
||||
struct modRM_byte modrm;
|
||||
struct SIB_byte sib;
|
||||
unsigned char *c, *cin;
|
||||
unsigned short *s;
|
||||
unsigned int *i;
|
||||
int size = 0; /* modrm byte is already counted */
|
||||
|
||||
|
||||
byte_decode(*in, &modrm); /* get bitfields */
|
||||
byte_decode(*in, &modrm); /* get bitfields */
|
||||
|
||||
out[0] = in[0]; /* save modrm byte */
|
||||
cin = &in[1];
|
||||
c = &out[1];
|
||||
s = (unsigned short *)&out[1];
|
||||
i = (unsigned int *)&out[1];
|
||||
out[0] = in[0]; /* save modrm byte */
|
||||
cin = &in[1];
|
||||
c = &out[1];
|
||||
s = (unsigned short *)&out[1];
|
||||
i = (unsigned int *)&out[1];
|
||||
|
||||
op->type = op_expression;
|
||||
op->flags.op_pointer = true; //|= op_pointer;
|
||||
if ( ! mode_16 && modrm.rm == MODRM_RM_SIB &&
|
||||
modrm.mod != MODRM_MOD_NOEA ) {
|
||||
size ++;
|
||||
byte_decode(*cin, (struct modRM_byte *)(void*)&sib);
|
||||
op->type = op_expression;
|
||||
op->flags.op_pointer = true; //|= op_pointer;
|
||||
if ( ! mode_16 && modrm.rm == MODRM_RM_SIB &&
|
||||
modrm.mod != MODRM_MOD_NOEA ) {
|
||||
size ++;
|
||||
byte_decode(*cin, (struct modRM_byte *)(void*)&sib);
|
||||
|
||||
out[1] = in[1]; /* save sib byte */
|
||||
cin = &in[2];
|
||||
c = &out[2];
|
||||
s = (unsigned short *)&out[2];
|
||||
i = (unsigned int *)&out[2];
|
||||
out[1] = in[1]; /* save sib byte */
|
||||
cin = &in[2];
|
||||
c = &out[2];
|
||||
s = (unsigned short *)&out[2];
|
||||
i = (unsigned int *)&out[2];
|
||||
|
||||
if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) {
|
||||
/* disp 32 is variant! */
|
||||
memset( i, X86_WILDCARD_BYTE, 4 );
|
||||
size += 4;
|
||||
}
|
||||
}
|
||||
if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) {
|
||||
/* disp 32 is variant! */
|
||||
memset( i, X86_WILDCARD_BYTE, 4 );
|
||||
size += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (! modrm.mod && modrm.rm == 101) {
|
||||
if ( mode_16 ) { /* straight RVA in disp */
|
||||
memset( s, X86_WILDCARD_BYTE, 2 );
|
||||
size += 2;
|
||||
} else {
|
||||
memset( i, X86_WILDCARD_BYTE, 2 );
|
||||
size += 4;
|
||||
}
|
||||
} else if (modrm.mod && modrm.mod < 3) {
|
||||
if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */
|
||||
*c = *cin;
|
||||
size += 1;
|
||||
} else if ( mode_16 ) {
|
||||
*s = (* ((unsigned short *) cin));
|
||||
size += 2;
|
||||
} else {
|
||||
*i = (*((unsigned int *) cin));
|
||||
size += 4;
|
||||
}
|
||||
} else if ( modrm.mod == 3 ) {
|
||||
op->type = op_register;
|
||||
op->flags.op_pointer = false;// &= ~op_pointer;
|
||||
}
|
||||
if (! modrm.mod && modrm.rm == 101) {
|
||||
if ( mode_16 ) { /* straight RVA in disp */
|
||||
memset( s, X86_WILDCARD_BYTE, 2 );
|
||||
size += 2;
|
||||
} else {
|
||||
memset( i, X86_WILDCARD_BYTE, 2 );
|
||||
size += 4;
|
||||
}
|
||||
} else if (modrm.mod && modrm.mod < 3) {
|
||||
if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */
|
||||
*c = *cin;
|
||||
size += 1;
|
||||
} else if ( mode_16 ) {
|
||||
*s = (* ((unsigned short *) cin));
|
||||
size += 2;
|
||||
} else {
|
||||
*i = (*((unsigned int *) cin));
|
||||
size += 4;
|
||||
}
|
||||
} else if ( modrm.mod == 3 ) {
|
||||
op->type = op_register;
|
||||
op->flags.op_pointer = false;// &= ~op_pointer;
|
||||
}
|
||||
|
||||
return (size);
|
||||
return (size);
|
||||
}
|
||||
|
||||
|
||||
static int ia32_decode_invariant( unsigned char *buf, size_t buf_len,
|
||||
ia32_insn_t *t, unsigned char *out,
|
||||
unsigned int prefixes, x86_invariant_t *inv) {
|
||||
static int ia32_decode_invariant( unsigned char *buf, size_t /*buf_len*/,
|
||||
ia32_insn_t *t, unsigned char *out,
|
||||
unsigned int prefixes, x86_invariant_t *inv) {
|
||||
|
||||
unsigned int addr_size, op_size, mode_16;
|
||||
unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag };
|
||||
int x, type, bytes = 0, size = 0, modrm = 0;
|
||||
unsigned int addr_size, op_size, mode_16;
|
||||
unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag };
|
||||
int x, type, bytes = 0, size = 0, modrm = 0;
|
||||
|
||||
/* set addressing mode */
|
||||
if (ia32_settings.options & opt_16_bit) {
|
||||
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2;
|
||||
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2;
|
||||
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1;
|
||||
} else {
|
||||
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4;
|
||||
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4;
|
||||
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0;
|
||||
}
|
||||
/* set addressing mode */
|
||||
if (ia32_settings.options & opt_16_bit) {
|
||||
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2;
|
||||
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2;
|
||||
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1;
|
||||
} else {
|
||||
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4;
|
||||
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4;
|
||||
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0;
|
||||
}
|
||||
|
||||
for (x = 0; x < 3; x++) {
|
||||
inv->operands[x].access = (enum x86_op_access) OP_PERM(op_flags[x]);
|
||||
inv->operands[x].flags.whole = (OP_FLAGS(op_flags[x]) >> 12);
|
||||
for (x = 0; x < 3; x++) {
|
||||
inv->operands[x].access = (enum x86_op_access) OP_PERM(op_flags[x]);
|
||||
inv->operands[x].flags.whole = (OP_FLAGS(op_flags[x]) >> 12);
|
||||
//(enum x86_op_flags) (OP_FLAGS(op_flags[x]) >> 12);
|
||||
|
||||
switch (op_flags[x] & OPTYPE_MASK) {
|
||||
case OPTYPE_c:
|
||||
size = (op_size == 4) ? 2 : 1;
|
||||
break;
|
||||
case OPTYPE_a: case OPTYPE_v:
|
||||
size = (op_size == 4) ? 4 : 2;
|
||||
break;
|
||||
case OPTYPE_p:
|
||||
size = (op_size == 4) ? 6 : 4;
|
||||
break;
|
||||
case OPTYPE_b:
|
||||
size = 1;
|
||||
break;
|
||||
case OPTYPE_w:
|
||||
size = 2;
|
||||
break;
|
||||
case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd:
|
||||
case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv:
|
||||
case OPTYPE_si: case OPTYPE_fx:
|
||||
size = 4;
|
||||
break;
|
||||
case OPTYPE_s:
|
||||
size = 6;
|
||||
break;
|
||||
case OPTYPE_q: case OPTYPE_pi:
|
||||
size = 8;
|
||||
break;
|
||||
case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss:
|
||||
case OPTYPE_pd: case OPTYPE_sd:
|
||||
size = 16;
|
||||
break;
|
||||
case OPTYPE_m:
|
||||
size = (addr_size == 4) ? 4 : 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (op_flags[x] & OPTYPE_MASK) {
|
||||
case OPTYPE_c:
|
||||
size = (op_size == 4) ? 2 : 1;
|
||||
break;
|
||||
case OPTYPE_a: case OPTYPE_v:
|
||||
size = (op_size == 4) ? 4 : 2;
|
||||
break;
|
||||
case OPTYPE_p:
|
||||
size = (op_size == 4) ? 6 : 4;
|
||||
break;
|
||||
case OPTYPE_b:
|
||||
size = 1;
|
||||
break;
|
||||
case OPTYPE_w:
|
||||
size = 2;
|
||||
break;
|
||||
case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd:
|
||||
case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv:
|
||||
case OPTYPE_si: case OPTYPE_fx:
|
||||
size = 4;
|
||||
break;
|
||||
case OPTYPE_s:
|
||||
size = 6;
|
||||
break;
|
||||
case OPTYPE_q: case OPTYPE_pi:
|
||||
size = 8;
|
||||
break;
|
||||
case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss:
|
||||
case OPTYPE_pd: case OPTYPE_sd:
|
||||
size = 16;
|
||||
break;
|
||||
case OPTYPE_m:
|
||||
size = (addr_size == 4) ? 4 : 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
type = op_flags[x] & ADDRMETH_MASK;
|
||||
switch (type) {
|
||||
case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q:
|
||||
case ADDRMETH_R: case ADDRMETH_W:
|
||||
modrm = 1;
|
||||
bytes += ia32_invariant_modrm( buf, out,
|
||||
mode_16, &inv->operands[x]);
|
||||
break;
|
||||
case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G:
|
||||
case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T:
|
||||
case ADDRMETH_V:
|
||||
inv->operands[x].type = op_register;
|
||||
modrm = 1;
|
||||
break;
|
||||
case ADDRMETH_A: case ADDRMETH_O:
|
||||
/* pad with xF4's */
|
||||
memset( &out[bytes + modrm], X86_WILDCARD_BYTE,
|
||||
size );
|
||||
bytes += size;
|
||||
inv->operands[x].type = op_offset;
|
||||
if ( type == ADDRMETH_O ) {
|
||||
inv->operands[x].flags.op_signed = true;
|
||||
type = op_flags[x] & ADDRMETH_MASK;
|
||||
switch (type) {
|
||||
case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q:
|
||||
case ADDRMETH_R: case ADDRMETH_W:
|
||||
modrm = 1;
|
||||
bytes += ia32_invariant_modrm( buf, out,
|
||||
mode_16, &inv->operands[x]);
|
||||
break;
|
||||
case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G:
|
||||
case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T:
|
||||
case ADDRMETH_V:
|
||||
inv->operands[x].type = op_register;
|
||||
modrm = 1;
|
||||
break;
|
||||
case ADDRMETH_A: case ADDRMETH_O:
|
||||
/* pad with xF4's */
|
||||
memset( &out[bytes + modrm], X86_WILDCARD_BYTE,
|
||||
size );
|
||||
bytes += size;
|
||||
inv->operands[x].type = op_offset;
|
||||
if ( type == ADDRMETH_O ) {
|
||||
inv->operands[x].flags.op_signed = true;
|
||||
inv->operands[x].flags.op_pointer = true;
|
||||
}
|
||||
break;
|
||||
case ADDRMETH_I: case ADDRMETH_J:
|
||||
/* grab imm value */
|
||||
if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) {
|
||||
/* assume this is an address */
|
||||
memset( &out[bytes + modrm], X86_WILDCARD_BYTE, size );
|
||||
} else {
|
||||
memcpy( &out[bytes + modrm], &buf[bytes + modrm], size );
|
||||
}
|
||||
|
||||
bytes += size;
|
||||
if ( type == ADDRMETH_J ) {
|
||||
if ( size == 1 ) {
|
||||
inv->operands[x].type = op_relative_near;
|
||||
} else {
|
||||
inv->operands[x].type = op_relative_far;
|
||||
}
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
} else {
|
||||
inv->operands[x].type = op_immediate;
|
||||
}
|
||||
break;
|
||||
case ADDRMETH_F:
|
||||
inv->operands[x].type = op_register;
|
||||
break;
|
||||
case ADDRMETH_X:
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
inv->operands[x].flags.op_pointer=true;
|
||||
inv->operands[x].flags.op_seg=x86_op_flags::op_ds_seg;
|
||||
}
|
||||
break;
|
||||
case ADDRMETH_I: case ADDRMETH_J:
|
||||
/* grab imm value */
|
||||
if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) {
|
||||
/* assume this is an address */
|
||||
memset( &out[bytes + modrm], X86_WILDCARD_BYTE, size );
|
||||
} else {
|
||||
memcpy( &out[bytes + modrm], &buf[bytes + modrm], size );
|
||||
}
|
||||
|
||||
bytes += size;
|
||||
if ( type == ADDRMETH_J ) {
|
||||
if ( size == 1 ) {
|
||||
inv->operands[x].type = op_relative_near;
|
||||
} else {
|
||||
inv->operands[x].type = op_relative_far;
|
||||
}
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
} else {
|
||||
inv->operands[x].type = op_immediate;
|
||||
}
|
||||
break;
|
||||
case ADDRMETH_F:
|
||||
inv->operands[x].type = op_register;
|
||||
break;
|
||||
case ADDRMETH_X:
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
inv->operands[x].flags.op_pointer=true;
|
||||
inv->operands[x].flags.op_seg=(x86_op_flags::op_ds_seg)>>8;
|
||||
inv->operands[x].flags.op_string=true;
|
||||
break;
|
||||
case ADDRMETH_Y:
|
||||
break;
|
||||
case ADDRMETH_Y:
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
inv->operands[x].flags.op_pointer=true;
|
||||
inv->operands[x].flags.op_seg=x86_op_flags::op_es_seg;
|
||||
inv->operands[x].flags.op_seg=x86_op_flags::op_es_seg>>8;
|
||||
inv->operands[x].flags.op_string=true;
|
||||
break;
|
||||
case ADDRMETH_RR:
|
||||
inv->operands[x].type = op_register;
|
||||
break;
|
||||
case ADDRMETH_II:
|
||||
inv->operands[x].type = op_immediate;
|
||||
break;
|
||||
default:
|
||||
inv->operands[x].type = op_unused;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ADDRMETH_RR:
|
||||
inv->operands[x].type = op_register;
|
||||
break;
|
||||
case ADDRMETH_II:
|
||||
inv->operands[x].type = op_immediate;
|
||||
break;
|
||||
default:
|
||||
inv->operands[x].type = op_unused;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (bytes + modrm);
|
||||
return (bytes + modrm);
|
||||
}
|
||||
|
||||
size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len,
|
||||
x86_invariant_t *inv ) {
|
||||
ia32_insn_t *raw_insn = NULL;
|
||||
unsigned int prefixes=0;
|
||||
unsigned int type;
|
||||
size_t size;
|
||||
|
||||
/* Perform recursive table lookup starting with main table (0) */
|
||||
size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes );
|
||||
if ( size == INVALID_INSN || size > buf_len ) {
|
||||
/* TODO: set errno */
|
||||
return 0;
|
||||
}
|
||||
size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len,
|
||||
x86_invariant_t *inv ) {
|
||||
ia32_insn_t *raw_insn = NULL;
|
||||
unsigned int prefixes=0;
|
||||
unsigned int type;
|
||||
size_t size;
|
||||
|
||||
/* copy opcode bytes to buffer */
|
||||
memcpy( inv->bytes, buf, size );
|
||||
/* Perform recursive table lookup starting with main table (0) */
|
||||
size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes );
|
||||
if ( size == INVALID_INSN || size > buf_len ) {
|
||||
/* TODO: set errno */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set mnemonic type and group */
|
||||
type = raw_insn->mnem_flag & ~INS_FLAG_MASK;
|
||||
/* copy opcode bytes to buffer */
|
||||
memcpy( inv->bytes, buf, size );
|
||||
|
||||
/* set mnemonic type and group */
|
||||
type = raw_insn->mnem_flag & ~INS_FLAG_MASK;
|
||||
inv->group = (x86_insn_t::x86_insn_group) ((INS_GROUP(type)) >> 12);
|
||||
inv->type = (enum x86_insn_type) INS_TYPE(type);
|
||||
|
||||
/* handle operands */
|
||||
size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn,
|
||||
&buf[size - 1], prefixes, inv );
|
||||
/* handle operands */
|
||||
size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn,
|
||||
&buf[size - 1], prefixes, inv );
|
||||
|
||||
inv->size = size;
|
||||
inv->size = size;
|
||||
|
||||
return size; /* return size of instruction in bytes */
|
||||
return size; /* return size of instruction in bytes */
|
||||
}
|
||||
|
||||
size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) {
|
||||
x86_invariant_t inv = { {0} };
|
||||
return( ia32_disasm_invariant( buf, buf_len, &inv ) );
|
||||
x86_invariant_t inv;
|
||||
memset(&inv,0,sizeof(x86_invariant_t));
|
||||
return( ia32_disasm_invariant( buf, buf_len, &inv ) );
|
||||
}
|
||||
|
||||
6
3rd_party/libdisasm/ia32_modrm.cpp
vendored
6
3rd_party/libdisasm/ia32_modrm.cpp
vendored
@ -155,12 +155,12 @@ static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
|
||||
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 3);
|
||||
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
|
||||
case MOD16_RM_BPSI:
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
|
||||
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
|
||||
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 6);
|
||||
break;
|
||||
case MOD16_RM_BPDI:
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
|
||||
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
|
||||
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
|
||||
break;
|
||||
@ -172,7 +172,7 @@ static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
|
||||
break;
|
||||
case MOD16_RM_BP:
|
||||
if ( modrm->mod != MOD16_MOD_NODISP ) {
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
|
||||
ia32_handle_register(&ea->base,
|
||||
REG_WORD_OFFSET + 5);
|
||||
}
|
||||
|
||||
5144
3rd_party/libdisasm/ia32_opcode_tables.cpp
vendored
5144
3rd_party/libdisasm/ia32_opcode_tables.cpp
vendored
File diff suppressed because it is too large
Load Diff
16
3rd_party/libdisasm/ia32_operand.cpp
vendored
16
3rd_party/libdisasm/ia32_operand.cpp
vendored
@ -20,17 +20,17 @@ static void apply_seg( x86_op_t *op, unsigned int prefixes ) {
|
||||
switch ( prefixes & PREFIX_REG_MASK ) {
|
||||
/* NOTE: that op->flags for segment override are not a bitfield */
|
||||
case PREFIX_CS:
|
||||
op->flags.op_seg = x86_op_flags::op_cs_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_cs_seg>>8; break;
|
||||
case PREFIX_SS:
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8; break;
|
||||
case PREFIX_DS:
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg>>8; break;
|
||||
case PREFIX_ES:
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg>>8; break;
|
||||
case PREFIX_FS:
|
||||
op->flags.op_seg = x86_op_flags::op_fs_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_fs_seg>>8; break;
|
||||
case PREFIX_GS:
|
||||
op->flags.op_seg = x86_op_flags::op_gs_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_gs_seg>>8; break;
|
||||
}
|
||||
|
||||
return;
|
||||
@ -172,7 +172,7 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
|
||||
case ADDRMETH_X: /* Memory addressed by DS:SI [string] */
|
||||
op->type = op_expression;
|
||||
op->flags.op_hardcode = true;
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg>>8;
|
||||
op->flags.op_pointer = true;
|
||||
op->flags.op_string = true;
|
||||
ia32_handle_register( &op->data.expression.base,
|
||||
@ -181,7 +181,7 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
|
||||
case ADDRMETH_Y: /* Memory addressed by ES:DI [string] */
|
||||
op->type = op_expression;
|
||||
op->flags.op_hardcode = true;
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg>>8;
|
||||
op->flags.op_pointer = true;
|
||||
op->flags.op_string = true;
|
||||
ia32_handle_register( &op->data.expression.base,
|
||||
|
||||
212
3rd_party/libdisasm/ia32_reg.cpp
vendored
212
3rd_party/libdisasm/ia32_reg.cpp
vendored
@ -71,126 +71,126 @@ static struct {
|
||||
unsigned int alias;
|
||||
char mnemonic[8];
|
||||
} ia32_reg_table[NUM_X86_REGS + 2] = {
|
||||
{ 0, reg_undef, 0, "" },
|
||||
/* REG_DWORD_OFFSET */
|
||||
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_ret), 0, "eax" },
|
||||
{ 0, reg_undef, 0, "" },
|
||||
/* REG_DWORD_OFFSET */
|
||||
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_ret), 0, "eax" },
|
||||
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_count), 0, "ecx" },
|
||||
{ REG_DWORD_SIZE, reg_gen, 0, "edx" },
|
||||
{ REG_DWORD_SIZE, reg_gen, 0, "ebx" },
|
||||
/* REG_ESP_INDEX */
|
||||
{ REG_DWORD_SIZE, reg_gen, 0, "edx" },
|
||||
{ REG_DWORD_SIZE, reg_gen, 0, "ebx" },
|
||||
/* REG_ESP_INDEX */
|
||||
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_sp), 0, "esp" },
|
||||
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_fp), 0, "ebp" },
|
||||
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_src), 0, "esi" },
|
||||
{ REG_DWORD_SIZE, (x86_reg_type)(reg_gen | reg_dest), 0, "edi" },
|
||||
/* REG_WORD_OFFSET */
|
||||
/* REG_WORD_OFFSET */
|
||||
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_ret), 3, "ax" },
|
||||
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_count), 6, "cx" },
|
||||
{ REG_WORD_SIZE, reg_gen, 9, "dx" },
|
||||
{ REG_WORD_SIZE, reg_gen, 12, "bx" },
|
||||
{ REG_WORD_SIZE, reg_gen, 9, "dx" },
|
||||
{ REG_WORD_SIZE, reg_gen, 12, "bx" },
|
||||
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_sp), 13, "sp" },
|
||||
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_fp), 14, "bp" },
|
||||
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_src), 15, "si" },
|
||||
{ REG_WORD_SIZE, (x86_reg_type)(reg_gen | reg_dest), 16, "di" },
|
||||
/* REG_BYTE_OFFSET */
|
||||
{ REG_BYTE_SIZE, reg_gen, 1, "al" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 4, "cl" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 7, "dl" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 10, "bl" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 2, "ah" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 5, "ch" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 8, "dh" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 11, "bh" },
|
||||
/* REG_MMX_OFFSET */
|
||||
{ REG_MMX_SIZE, reg_simd, 18, "mm0" },
|
||||
{ REG_MMX_SIZE, reg_simd, 19, "mm1" },
|
||||
{ REG_MMX_SIZE, reg_simd, 20, "mm2" },
|
||||
{ REG_MMX_SIZE, reg_simd, 21, "mm3" },
|
||||
{ REG_MMX_SIZE, reg_simd, 22, "mm4" },
|
||||
{ REG_MMX_SIZE, reg_simd, 23, "mm5" },
|
||||
{ REG_MMX_SIZE, reg_simd, 24, "mm6" },
|
||||
{ REG_MMX_SIZE, reg_simd, 25, "mm7" },
|
||||
/* REG_SIMD_OFFSET */
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm0" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm1" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm2" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm3" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm4" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm5" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm6" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm7" },
|
||||
/* REG_DEBUG_OFFSET */
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr0" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr1" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr2" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr3" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr4" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr5" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr6" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr7" },
|
||||
/* REG_CTRL_OFFSET */
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr0" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr1" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr2" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr3" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr4" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr5" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr6" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr7" },
|
||||
/* REG_TEST_OFFSET */
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr0" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr1" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr2" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr3" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr4" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr5" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr6" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr7" },
|
||||
/* REG_SEG_OFFSET */
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "es" },
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "cs" },
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "ss" },
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "ds" },
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "fs" },
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "gs" },
|
||||
/* REG_LDTR_INDEX */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "ldtr" },
|
||||
/* REG_GDTR_INDEX */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "gdtr" },
|
||||
/* REG_FPU_OFFSET */
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(0)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(1)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(2)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(3)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(4)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(5)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(6)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(7)" },
|
||||
/* REG_FLAGS_INDEX : 81 */
|
||||
{ REG_FLAGS_SIZE, reg_cond, 0, "eflags" },
|
||||
/* REG_FPCTRL_INDEX : 82*/
|
||||
/* REG_BYTE_OFFSET */
|
||||
{ REG_BYTE_SIZE, reg_gen, 1, "al" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 4, "cl" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 7, "dl" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 10, "bl" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 2, "ah" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 5, "ch" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 8, "dh" },
|
||||
{ REG_BYTE_SIZE, reg_gen, 11, "bh" },
|
||||
/* REG_MMX_OFFSET */
|
||||
{ REG_MMX_SIZE, reg_simd, 18, "mm0" },
|
||||
{ REG_MMX_SIZE, reg_simd, 19, "mm1" },
|
||||
{ REG_MMX_SIZE, reg_simd, 20, "mm2" },
|
||||
{ REG_MMX_SIZE, reg_simd, 21, "mm3" },
|
||||
{ REG_MMX_SIZE, reg_simd, 22, "mm4" },
|
||||
{ REG_MMX_SIZE, reg_simd, 23, "mm5" },
|
||||
{ REG_MMX_SIZE, reg_simd, 24, "mm6" },
|
||||
{ REG_MMX_SIZE, reg_simd, 25, "mm7" },
|
||||
/* REG_SIMD_OFFSET */
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm0" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm1" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm2" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm3" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm4" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm5" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm6" },
|
||||
{ REG_SIMD_SIZE, reg_simd, 0, "xmm7" },
|
||||
/* REG_DEBUG_OFFSET */
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr0" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr1" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr2" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr3" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr4" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr5" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr6" },
|
||||
{ REG_DEBUG_SIZE, reg_sys, 0, "dr7" },
|
||||
/* REG_CTRL_OFFSET */
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr0" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr1" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr2" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr3" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr4" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr5" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr6" },
|
||||
{ REG_CTRL_SIZE, reg_sys, 0, "cr7" },
|
||||
/* REG_TEST_OFFSET */
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr0" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr1" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr2" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr3" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr4" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr5" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr6" },
|
||||
{ REG_TEST_SIZE, reg_sys, 0, "tr7" },
|
||||
/* REG_SEG_OFFSET */
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "es" },
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "cs" },
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "ss" },
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "ds" },
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "fs" },
|
||||
{ REG_SEG_SIZE, reg_seg, 0, "gs" },
|
||||
/* REG_LDTR_INDEX */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "ldtr" },
|
||||
/* REG_GDTR_INDEX */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "gdtr" },
|
||||
/* REG_FPU_OFFSET */
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(0)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(1)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(2)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(3)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(4)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(5)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(6)" },
|
||||
{ REG_FPU_SIZE, reg_fpu, 0, "st(7)" },
|
||||
/* REG_FLAGS_INDEX : 81 */
|
||||
{ REG_FLAGS_SIZE, reg_cond, 0, "eflags" },
|
||||
/* REG_FPCTRL_INDEX : 82*/
|
||||
{ REG_FPCTRL_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fpctrl" },
|
||||
/* REG_FPSTATUS_INDEX : 83*/
|
||||
/* REG_FPSTATUS_INDEX : 83*/
|
||||
{ REG_FPSTATUS_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fpstat" },
|
||||
/* REG_FPTAG_INDEX : 84 */
|
||||
/* REG_FPTAG_INDEX : 84 */
|
||||
{ REG_FPTAG_SIZE, (x86_reg_type)(reg_fpu | reg_sys), 0, "fptag" },
|
||||
/* REG_EIP_INDEX : 85 */
|
||||
{ REG_EIP_SIZE, reg_pc, 0, "eip" },
|
||||
/* REG_IP_INDEX : 86 */
|
||||
{ REG_IP_SIZE, reg_pc, 17, "ip" },
|
||||
/* REG_IDTR_INDEX : 87 */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "idtr" },
|
||||
/* REG_MXCSG_INDEX : SSE Control Reg : 88 */
|
||||
{ REG_DWORD_SIZE, (x86_reg_type)(reg_sys | reg_simd), 0, "mxcsr" },
|
||||
/* REG_TR_INDEX : Task Register : 89 */
|
||||
{ 16 + 64, reg_sys, 0, "tr" },
|
||||
/* REG_CSMSR_INDEX : SYSENTER_CS_MSR : 90 */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "cs_msr" },
|
||||
/* REG_ESPMSR_INDEX : SYSENTER_ESP_MSR : 91 */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "esp_msr" },
|
||||
/* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "eip_msr" },
|
||||
{ 0 }
|
||||
};
|
||||
/* REG_EIP_INDEX : 85 */
|
||||
{ REG_EIP_SIZE, reg_pc, 0, "eip" },
|
||||
/* REG_IP_INDEX : 86 */
|
||||
{ REG_IP_SIZE, reg_pc, 17, "ip" },
|
||||
/* REG_IDTR_INDEX : 87 */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "idtr" },
|
||||
/* REG_MXCSG_INDEX : SSE Control Reg : 88 */
|
||||
{ REG_DWORD_SIZE, (x86_reg_type)(reg_sys | reg_simd), 0, "mxcsr" },
|
||||
/* REG_TR_INDEX : Task Register : 89 */
|
||||
{ 16 + 64, reg_sys, 0, "tr" },
|
||||
/* REG_CSMSR_INDEX : SYSENTER_CS_MSR : 90 */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "cs_msr" },
|
||||
/* REG_ESPMSR_INDEX : SYSENTER_ESP_MSR : 91 */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "esp_msr" },
|
||||
/* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "eip_msr" },
|
||||
{ 0,reg_undef,0,{0} }
|
||||
};
|
||||
|
||||
|
||||
static size_t sz_regtable = NUM_X86_REGS + 1;
|
||||
|
||||
144
3rd_party/libdisasm/libdis.h
vendored
144
3rd_party/libdisasm/libdis.h
vendored
@ -89,7 +89,7 @@ enum x86_options { /* these can be ORed together */
|
||||
opt_none= 0,
|
||||
opt_ignore_nulls=1, /* ignore sequences of > 4 NULL bytes */
|
||||
opt_16_bit=2, /* 16-bit/DOS disassembly */
|
||||
opt_att_mnemonics=4, /* use AT&T syntax names for alternate opcode mnemonics */
|
||||
opt_att_mnemonics=4 /* use AT&T syntax names for alternate opcode mnemonics */
|
||||
};
|
||||
|
||||
/* ========================================= Instruction Representation */
|
||||
@ -133,12 +133,12 @@ enum x86_reg_type { /* NOTE: these may be ORed together */
|
||||
|
||||
/* x86_reg_t : an X86 CPU register */
|
||||
struct x86_reg_t {
|
||||
char name[MAX_REGNAME];
|
||||
enum x86_reg_type type; /* what register is used for */
|
||||
unsigned int size; /* size of register in bytes */
|
||||
unsigned int id; /* register ID #, for quick compares */
|
||||
unsigned int alias; /* ID of reg this is an alias for */
|
||||
unsigned int shift; /* amount to shift aliased reg by */
|
||||
char name[MAX_REGNAME];
|
||||
enum x86_reg_type type; /* what register is used for */
|
||||
unsigned int size; /* size of register in bytes */
|
||||
unsigned int id; /* register ID #, for quick compares */
|
||||
unsigned int alias; /* ID of reg this is an alias for */
|
||||
unsigned int shift; /* amount to shift aliased reg by */
|
||||
x86_reg_t * aliased_reg( ) {
|
||||
x86_reg_t * reg = (x86_reg_t * )calloc( sizeof(x86_reg_t), 1 );
|
||||
reg->x86_reg_from_id( id );
|
||||
@ -158,11 +158,11 @@ typedef struct {
|
||||
|
||||
/* x86_absolute_t : an X86 segment:offset address (descriptor) */
|
||||
typedef struct {
|
||||
unsigned short segment; /* loaded directly into CS */
|
||||
union {
|
||||
unsigned short off16; /* loaded directly into IP */
|
||||
uint32_t off32; /* loaded directly into EIP */
|
||||
} offset;
|
||||
unsigned short segment; /* loaded directly into CS */
|
||||
union {
|
||||
unsigned short off16; /* loaded directly into IP */
|
||||
uint32_t off32; /* loaded directly into EIP */
|
||||
} offset;
|
||||
} x86_absolute_t;
|
||||
|
||||
enum x86_op_type { /* mutually exclusive */
|
||||
@ -250,39 +250,43 @@ struct x86_op_flags { /* ORed together, but segs are mutually exclusive */
|
||||
/* x86_op_t : an X86 instruction operand */
|
||||
struct x86_op_t{
|
||||
friend struct x86_insn_t;
|
||||
enum x86_op_type type; /* operand type */
|
||||
enum x86_op_datatype datatype; /* operand size */
|
||||
enum x86_op_access access; /* operand access [RWX] */
|
||||
x86_op_flags flags; /* misc flags */
|
||||
union {
|
||||
/* sizeof will have to work on these union members! */
|
||||
/* immediate values */
|
||||
char sbyte;
|
||||
short sword;
|
||||
int32_t sdword;
|
||||
qword_t sqword;
|
||||
unsigned char byte;
|
||||
unsigned short word;
|
||||
uint32_t dword;
|
||||
qword_t qword;
|
||||
float sreal;
|
||||
double dreal;
|
||||
/* misc large/non-native types */
|
||||
unsigned char extreal[10];
|
||||
unsigned char bcd[10];
|
||||
qword_t dqword[2];
|
||||
unsigned char simd[16];
|
||||
unsigned char fpuenv[28];
|
||||
/* offset from segment */
|
||||
uint32_t offset;
|
||||
x86_reg_t reg; /* ID of CPU register */
|
||||
char relative_near; /* offsets from current insn */
|
||||
int32_t relative_far;
|
||||
x86_absolute_t absolute; /* segment:offset */
|
||||
x86_ea_t expression; /* effective address [expression] */
|
||||
} data;
|
||||
/* this is needed to make formatting operands more sane */
|
||||
void * insn; /* pointer to x86_insn_t owning operand */
|
||||
enum x86_op_type type; /* operand type */
|
||||
enum x86_op_datatype datatype; /* operand size */
|
||||
enum x86_op_access access; /* operand access [RWX] */
|
||||
x86_op_flags flags; /* misc flags */
|
||||
union {
|
||||
/* sizeof will have to work on these union members! */
|
||||
/* immediate values */
|
||||
char sbyte;
|
||||
short sword;
|
||||
int32_t sdword;
|
||||
qword_t sqword;
|
||||
unsigned char byte;
|
||||
unsigned short word;
|
||||
uint32_t dword;
|
||||
qword_t qword;
|
||||
float sreal;
|
||||
double dreal;
|
||||
/* misc large/non-native types */
|
||||
unsigned char extreal[10];
|
||||
unsigned char bcd[10];
|
||||
qword_t dqword[2];
|
||||
unsigned char simd[16];
|
||||
unsigned char fpuenv[28];
|
||||
/* offset from segment */
|
||||
uint32_t offset;
|
||||
/* ID of CPU register */
|
||||
x86_reg_t reg;
|
||||
/* offsets from current insn */
|
||||
char relative_near;
|
||||
int32_t relative_far;
|
||||
/* segment:offset */
|
||||
x86_absolute_t absolute;
|
||||
/* effective address [expression] */
|
||||
x86_ea_t expression;
|
||||
} data;
|
||||
/* this is needed to make formatting operands more sane */
|
||||
void * insn; /* pointer to x86_insn_t owning operand */
|
||||
size_t size()
|
||||
{
|
||||
return operand_size();
|
||||
@ -301,6 +305,7 @@ struct x86_op_t{
|
||||
x86_op_t * copy()
|
||||
{
|
||||
x86_op_t *op = (x86_op_t *) calloc( sizeof(x86_op_t), 1 );
|
||||
|
||||
if ( op ) {
|
||||
memcpy( op, this, sizeof(x86_op_t) );
|
||||
}
|
||||
@ -439,7 +444,7 @@ enum x86_insn_note {
|
||||
insn_note_smm = 2, /* "" in System Management Mode */
|
||||
insn_note_serial = 4, /* Serializing instruction */
|
||||
insn_note_nonswap = 8, /* Does not swap arguments in att-style formatting */
|
||||
insn_note_nosuffix = 16, /* Does not have size suffix in att-style formatting */
|
||||
insn_note_nosuffix = 16 /* Does not have size suffix in att-style formatting */
|
||||
};
|
||||
|
||||
/* This specifies what effects the instruction has on the %eflags register */
|
||||
@ -520,7 +525,6 @@ enum x86_insn_prefix {
|
||||
|
||||
|
||||
/* TODO: maybe provide insn_new/free(), and have disasm return new insn_t */
|
||||
|
||||
/* FOREACH types: these are used to limit the foreach results to
|
||||
* operands which match a certain "type" (implicit or explicit)
|
||||
* or which are accessed in certain ways (e.g. read or write). Note
|
||||
@ -572,8 +576,8 @@ private:
|
||||
void x86_oplist_append(x86_oplist_t *op);
|
||||
public:
|
||||
/* information about the instruction */
|
||||
uint32_t addr; /* load address */
|
||||
uint32_t offset; /* offset into file/buffer */
|
||||
uint32_t addr; /* load address */
|
||||
uint32_t offset; /* offset into file/buffer */
|
||||
x86_insn_group group; /* meta-type, e.g. INS_EXEC */
|
||||
x86_insn_type type; /* type, e.g. INS_BRANCH */
|
||||
x86_insn_note note; /* note, e.g. RING0 */
|
||||
@ -604,29 +608,36 @@ public:
|
||||
void *block; /* code block containing this insn */
|
||||
void *function; /* function containing this insn */
|
||||
int tag; /* tag the insn as seen/processed */
|
||||
x86_op_t * x86_operand_new();
|
||||
size_t x86_operand_count( enum x86_op_foreach_type type );
|
||||
x86_op_t *x86_operand_new();
|
||||
/* convenience routine: returns count of operands matching 'type' */
|
||||
size_t x86_operand_count( enum x86_op_foreach_type type );
|
||||
/* accessor functions for the operands */
|
||||
x86_op_t * x86_operand_1st( );
|
||||
x86_op_t * x86_operand_2nd( );
|
||||
x86_op_t * x86_operand_3rd( );
|
||||
x86_op_t * x86_operand_1st( );
|
||||
x86_op_t * x86_operand_2nd( );
|
||||
x86_op_t * x86_operand_3rd( );
|
||||
x86_op_t * get_dest();
|
||||
int32_t x86_get_rel_offset( );
|
||||
x86_op_t * x86_get_branch_target( );
|
||||
x86_op_t * x86_get_imm( );
|
||||
uint8_t * x86_get_raw_imm( );
|
||||
int32_t x86_get_rel_offset( );
|
||||
x86_op_t * x86_get_branch_target( );
|
||||
x86_op_t * x86_get_imm( );
|
||||
/* More accessor fuctions, this time for user-defined info... */
|
||||
void x86_set_insn_addr( uint32_t addr );
|
||||
int x86_format_mnemonic( char *buf, int len, enum x86_asm_format format);
|
||||
int x86_format_insn( char *buf, int len, enum x86_asm_format);
|
||||
void x86_oplist_free( );
|
||||
uint8_t * x86_get_raw_imm( );
|
||||
/* set the address (usually RVA) of the insn */
|
||||
void x86_set_insn_addr( uint32_t addr );
|
||||
/* format (sprintf) an instruction mnemonic into 'buf' using specified syntax */
|
||||
int x86_format_mnemonic( char *buf, int len, enum x86_asm_format format);
|
||||
int x86_format_insn( char *buf, int len, enum x86_asm_format);
|
||||
void x86_oplist_free( );
|
||||
/* returns 0 if an instruction is invalid, 1 if valid */
|
||||
bool is_valid( );
|
||||
uint32_t x86_get_address( );
|
||||
void make_invalid(unsigned char *buf);
|
||||
void make_invalid(unsigned char *buf);
|
||||
/* instruction tagging: these routines allow the programmer to mark
|
||||
* instructions as "seen" in a DFS, for example. libdisasm does not use
|
||||
* the tag field.*/
|
||||
/* set insn->tag to 1 */
|
||||
void x86_tag_insn( );
|
||||
|
||||
/* return insn->tag */
|
||||
int x86_insn_is_tagged();
|
||||
/* set insn->tag to 0 */
|
||||
void x86_untag_insn();
|
||||
@ -803,9 +814,10 @@ public:
|
||||
* void x86_get_aliased_reg( x86_reg_t *alias_reg, x86_reg_t *output_reg )
|
||||
* where 'alias_reg' is a reg operand and 'output_reg' is filled with the
|
||||
* register that the operand is an alias for */
|
||||
//#define x86_get_aliased_reg( alias_reg, output_reg ) \
|
||||
// x86_reg_from_id( alias_reg->alias, output_reg )
|
||||
|
||||
/*
|
||||
#define x86_get_aliased_reg( alias_reg, output_reg ) \
|
||||
x86_reg_from_id( alias_reg->alias, output_reg )
|
||||
*/
|
||||
|
||||
/* ================================== Invariant Instruction Representation */
|
||||
/* Invariant instructions are used for generating binary signatures;
|
||||
|
||||
36
3rd_party/libdisasm/x86_disasm.cpp
vendored
36
3rd_party/libdisasm/x86_disasm.cpp
vendored
@ -52,7 +52,7 @@ unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
|
||||
/* copy enough bytes for disassembly into buffer : this
|
||||
* helps prevent buffer overruns at the end of a file */
|
||||
memset( bytes, 0, MAX_INSTRUCTION_SIZE );
|
||||
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
|
||||
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
|
||||
MAX_INSTRUCTION_SIZE );
|
||||
|
||||
/* actually do the disassembly */
|
||||
@ -104,7 +104,7 @@ unsigned int X86_Disasm::x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
|
||||
bytes++; /* try next byte */
|
||||
}
|
||||
|
||||
insn.x86_oplist_free();
|
||||
insn.x86_oplist_free();
|
||||
}
|
||||
|
||||
return( count );
|
||||
@ -127,9 +127,9 @@ static int32_t internal_resolver( x86_op_t *op, x86_insn_t *insn ){
|
||||
if ( x86_optype_is_address(op->type) ) {
|
||||
next_addr = op->data.sdword;
|
||||
} else if ( op->type == op_relative_near ) {
|
||||
next_addr = insn->addr + insn->size + op->data.relative_near;
|
||||
next_addr = insn->addr + insn->size + op->data.relative_near;
|
||||
} else if ( op->type == op_relative_far ) {
|
||||
next_addr = insn->addr + insn->size + op->data.relative_far;
|
||||
next_addr = insn->addr + insn->size + op->data.relative_far;
|
||||
}
|
||||
return( next_addr );
|
||||
}
|
||||
@ -141,7 +141,7 @@ unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int bu
|
||||
x86_insn_t insn;
|
||||
x86_op_t *op;
|
||||
int32_t next_addr;
|
||||
uint32_t next_offset;
|
||||
int32_t next_offset;
|
||||
unsigned int size, count = 0, bytes = 0, cont = 1;
|
||||
|
||||
while ( cont && bytes < buf_len ) {
|
||||
@ -175,8 +175,8 @@ unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int bu
|
||||
if (next_addr != -1 ) {
|
||||
next_offset = next_addr - buf_rva;
|
||||
/* if offset is in this buffer... */
|
||||
if ( next_offset >= 0 &&
|
||||
next_offset < buf_len ) {
|
||||
if ( next_offset >= 0 && next_offset < int(buf_len) )
|
||||
{
|
||||
/* go ahead and disassemble */
|
||||
count += x86_disasm_forward( buf,
|
||||
buf_len,
|
||||
@ -197,24 +197,24 @@ unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int bu
|
||||
cont = 0;
|
||||
}
|
||||
|
||||
insn.x86_oplist_free( );
|
||||
insn.x86_oplist_free( );
|
||||
}
|
||||
return( count );
|
||||
}
|
||||
|
||||
/* invariant instruction representation */
|
||||
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
|
||||
x86_invariant_t *inv ){
|
||||
if (! buf || ! buf_len || ! inv ) {
|
||||
return(0);
|
||||
}
|
||||
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
|
||||
x86_invariant_t *inv ){
|
||||
if (! buf || ! buf_len || ! inv ) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
return ia32_disasm_invariant(buf, buf_len, inv);
|
||||
return ia32_disasm_invariant(buf, buf_len, inv);
|
||||
}
|
||||
size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len ) {
|
||||
if (! buf || ! buf_len ) {
|
||||
return(0);
|
||||
}
|
||||
if (! buf || ! buf_len ) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
return ia32_disasm_size(buf, buf_len);
|
||||
return ia32_disasm_size(buf, buf_len);
|
||||
}
|
||||
|
||||
42
3rd_party/libdisasm/x86_format.cpp
vendored
42
3rd_party/libdisasm/x86_format.cpp
vendored
@ -46,7 +46,7 @@
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
static char *prefix_strings[] = {
|
||||
static const char *prefix_strings[] = {
|
||||
"", /* no prefix */
|
||||
"repz ", /* the trailing spaces make it easy to prepend to mnemonic */
|
||||
"repnz ",
|
||||
@ -115,7 +115,7 @@ static void get_operand_data_str( x86_op_t *op, char *str, int len ){
|
||||
static void get_operand_regtype_str( int regtype, char *str, int len )
|
||||
{
|
||||
static struct {
|
||||
char *name;
|
||||
const char *name;
|
||||
int value;
|
||||
} operand_regtypes[] = {
|
||||
{"reg_gen" , 0x00001},
|
||||
@ -284,7 +284,7 @@ static int format_expr( x86_ea_t *ea, char *buf, int len,
|
||||
static int format_seg( x86_op_t *op, char *buf, int len,
|
||||
enum x86_asm_format format ) {
|
||||
int len_orig = len;
|
||||
char *reg = "";
|
||||
const char *reg = "";
|
||||
|
||||
if (! op || ! buf || ! len || ! op->flags.whole) {
|
||||
return(0);
|
||||
@ -295,8 +295,9 @@ static int format_seg( x86_op_t *op, char *buf, int len,
|
||||
if (! (int) op->flags.op_seg) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
switch (op->flags.op_seg) {
|
||||
uint16_t seg_ov=uint16_t(op->flags.op_seg)<<8;
|
||||
switch (seg_ov)
|
||||
{
|
||||
case x86_op_flags::op_es_seg: reg = "es"; break;
|
||||
case x86_op_flags::op_cs_seg: reg = "cs"; break;
|
||||
case x86_op_flags::op_ss_seg: reg = "ss"; break;
|
||||
@ -328,9 +329,9 @@ static int format_seg( x86_op_t *op, char *buf, int len,
|
||||
return( len_orig - len ); /* return length of appended string */
|
||||
}
|
||||
|
||||
static char *get_operand_datatype_str( x86_op_t *op ){
|
||||
static const char *get_operand_datatype_str( x86_op_t *op ){
|
||||
|
||||
static char *types[] = {
|
||||
static const char *types[] = {
|
||||
"sbyte", /* 0 */
|
||||
"sword",
|
||||
"sqword",
|
||||
@ -405,7 +406,7 @@ static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
|
||||
int len) {
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
const char *name;
|
||||
int value;
|
||||
} insn_flags[] = {
|
||||
{ "carry_set ", 0x0001 },
|
||||
@ -440,9 +441,9 @@ static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
|
||||
return( len_orig - len );
|
||||
}
|
||||
|
||||
static char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
|
||||
static const char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
|
||||
|
||||
static char *types[] = {
|
||||
static const char *types[] = {
|
||||
"", // 0
|
||||
"controlflow",// 1
|
||||
"arithmetic", // 2
|
||||
@ -467,10 +468,10 @@ static char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
|
||||
return types[gp];
|
||||
}
|
||||
|
||||
static char *get_insn_type_str( enum x86_insn_type type ) {
|
||||
static const char *get_insn_type_str( enum x86_insn_type type ) {
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
const char *name;
|
||||
int value;
|
||||
} types[] = {
|
||||
/* insn_controlflow */
|
||||
@ -592,8 +593,8 @@ static char *get_insn_type_str( enum x86_insn_type type ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
|
||||
static char *intel[] = {
|
||||
static const char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
|
||||
static const char *intel[] = {
|
||||
"", // 0
|
||||
"8086", // 1
|
||||
"80286", // 2
|
||||
@ -620,8 +621,8 @@ static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static char *get_insn_isa_str( enum x86_insn_isa isa ) {
|
||||
static char *subset[] = {
|
||||
static const char *get_insn_isa_str( enum x86_insn_isa isa ) {
|
||||
static const char *subset[] = {
|
||||
NULL, // 0
|
||||
"General Purpose", // 1
|
||||
"Floating Point", // 2
|
||||
@ -880,11 +881,11 @@ static int format_operand_xml( x86_op_t *op, x86_insn_t *insn, char *buf,
|
||||
return( strlen( buf ) );
|
||||
}
|
||||
|
||||
static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf,
|
||||
static int format_operand_raw( x86_op_t *op, x86_insn_t */*insn*/, char *buf,
|
||||
int len){
|
||||
|
||||
char str[MAX_OP_RAW_STRING];
|
||||
char *datatype = get_operand_datatype_str(op);
|
||||
const char *datatype = get_operand_datatype_str(op);
|
||||
|
||||
switch (op->type) {
|
||||
case op_register:
|
||||
@ -1042,7 +1043,7 @@ char * x86_op_t::format( enum x86_asm_format format ) {
|
||||
|
||||
static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
|
||||
int size = 0;
|
||||
char *suffix;
|
||||
const char *suffix;
|
||||
|
||||
if (! insn || ! buf || ! len )
|
||||
return(0);
|
||||
@ -1094,7 +1095,6 @@ static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
|
||||
return ( strlen( buf ) );
|
||||
}
|
||||
|
||||
/** format (sprintf) an instruction mnemonic into 'buf' using specified syntax */
|
||||
int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
|
||||
enum x86_asm_format format){
|
||||
char str[MAX_OP_STRING];
|
||||
@ -1137,7 +1137,7 @@ static int format_insn_note(x86_insn_t *insn, char *buf, int len){
|
||||
return( len_orig - len );
|
||||
}
|
||||
|
||||
static int format_raw_insn( x86_insn_t *insn, char *buf, int len ){
|
||||
static int format_raw_insn( x86_insn_t *insn, char *buf, size_t len ){
|
||||
struct op_string opstr = { buf, len };
|
||||
int i;
|
||||
|
||||
|
||||
8
3rd_party/libdisasm/x86_insn.cpp
vendored
8
3rd_party/libdisasm/x86_insn.cpp
vendored
@ -17,7 +17,6 @@ int x86_insn_is_valid( x86_insn_t *insn ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \returns false if an instruction is invalid, true if valid */
|
||||
bool x86_insn_t::is_valid( )
|
||||
{
|
||||
if ( this && this->type != insn_invalid && this->size > 0 )
|
||||
@ -203,13 +202,12 @@ size_t x86_op_t::operand_size() {
|
||||
return(4); /* default size */
|
||||
}
|
||||
|
||||
/** set the address (usually RVA) of the insn */
|
||||
void x86_insn_t::x86_set_insn_addr( uint32_t _addr ) {
|
||||
addr = _addr;
|
||||
}
|
||||
|
||||
void x86_insn_t::x86_set_insn_offset( unsigned int offset ){
|
||||
offset = offset;
|
||||
void x86_insn_t::x86_set_insn_offset( unsigned int _offset ){
|
||||
offset = _offset;
|
||||
}
|
||||
|
||||
void x86_insn_t::x86_set_insn_function( void * func ){
|
||||
@ -220,7 +218,6 @@ void x86_insn_t::x86_set_insn_block( void * _block ){
|
||||
block = _block;
|
||||
}
|
||||
|
||||
/** set insn->tag to 1 */
|
||||
void x86_insn_t::x86_tag_insn(){
|
||||
tag = 1;
|
||||
}
|
||||
@ -229,7 +226,6 @@ void x86_insn_t::x86_untag_insn(){
|
||||
tag = 0;
|
||||
}
|
||||
|
||||
/** \return insn->tag */
|
||||
int x86_insn_t::x86_insn_is_tagged(){
|
||||
return tag;
|
||||
}
|
||||
|
||||
249
3rd_party/libdisasm/x86_operand_list.cpp
vendored
249
3rd_party/libdisasm/x86_operand_list.cpp
vendored
@ -4,31 +4,31 @@
|
||||
|
||||
|
||||
void x86_insn_t::x86_oplist_append( x86_oplist_t *op ) {
|
||||
x86_oplist_t *list;
|
||||
x86_oplist_t *list;
|
||||
assert(this);
|
||||
|
||||
list = operands;
|
||||
if (! list ) {
|
||||
operand_count = 1;
|
||||
/* Note that we have no way of knowing if this is an
|
||||
list = operands;
|
||||
if (! list ) {
|
||||
operand_count = 1;
|
||||
/* Note that we have no way of knowing if this is an
|
||||
* exlicit operand or not, since the caller fills
|
||||
* the x86_op_t after we return. We increase the
|
||||
* explicit count automatically, and ia32_insn_implicit_ops
|
||||
* decrements it */
|
||||
explicit_count = 1;
|
||||
operands = op;
|
||||
explicit_count = 1;
|
||||
operands = op;
|
||||
return;
|
||||
}
|
||||
|
||||
/* get to end of list */
|
||||
for ( ; list->next; list = list->next )
|
||||
;
|
||||
|
||||
operand_count = operand_count + 1;
|
||||
explicit_count = explicit_count + 1;
|
||||
list->next = op;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* get to end of list */
|
||||
for ( ; list->next; list = list->next )
|
||||
;
|
||||
|
||||
operand_count = operand_count + 1;
|
||||
explicit_count = explicit_count + 1;
|
||||
list->next = op;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
|
||||
@ -48,7 +48,7 @@ bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
|
||||
return (in & (insn_dir_set | insn_dir_clear))!=0;
|
||||
case insn_eflag_sign:
|
||||
return (in & (insn_sign_set | insn_sign_clear | insn_zero_set_or_sign_ne_oflow |
|
||||
insn_sign_eq_oflow | insn_sign_ne_oflow))!=0;
|
||||
insn_sign_eq_oflow | insn_sign_ne_oflow))!=0;
|
||||
case insn_eflag_parity:
|
||||
return (in & (insn_parity_set | insn_parity_clear))!=0;
|
||||
}
|
||||
@ -56,31 +56,31 @@ bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
|
||||
}
|
||||
|
||||
x86_op_t * x86_insn_t::x86_operand_new( ) {
|
||||
x86_oplist_t *op;
|
||||
x86_oplist_t *op;
|
||||
assert(this);
|
||||
op = (x86_oplist_t *)calloc( sizeof(x86_oplist_t), 1 );
|
||||
op->op.insn = this;
|
||||
x86_oplist_append( op );
|
||||
return( &(op->op) );
|
||||
op = (x86_oplist_t *)calloc( sizeof(x86_oplist_t), 1 );
|
||||
op->op.insn = this;
|
||||
x86_oplist_append( op );
|
||||
return( &(op->op) );
|
||||
}
|
||||
|
||||
/** free the operand list associated with an instruction -- useful for
|
||||
* preventing memory leaks when free()ing an x86_insn_t */
|
||||
void x86_insn_t::x86_oplist_free( )
|
||||
{
|
||||
x86_oplist_t *op, *list;
|
||||
x86_oplist_t *op, *list;
|
||||
assert(this);
|
||||
for ( list = operands; list; ) {
|
||||
op = list;
|
||||
list = list->next;
|
||||
free(op);
|
||||
}
|
||||
for ( list = operands; list; ) {
|
||||
op = list;
|
||||
list = list->next;
|
||||
free(op);
|
||||
}
|
||||
|
||||
operands = NULL;
|
||||
operand_count = 0;
|
||||
explicit_count = 0;
|
||||
operands = NULL;
|
||||
operand_count = 0;
|
||||
explicit_count = 0;
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== LIBDISASM API */
|
||||
@ -88,122 +88,121 @@ void x86_insn_t::x86_oplist_free( )
|
||||
enum... yet one more confusing thing in the API */
|
||||
int x86_insn_t::x86_operand_foreach( x86_operand_fn func, void *arg, enum x86_op_foreach_type type )
|
||||
{
|
||||
x86_oplist_t *list;
|
||||
char _explicit = 1, implicit = 1;
|
||||
x86_oplist_t *list;
|
||||
char _explicit = 1, implicit = 1;
|
||||
assert(this);
|
||||
if ( ! func ) {
|
||||
return 0;
|
||||
}
|
||||
if ( ! func ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* note: explicit and implicit can be ORed together to
|
||||
/* note: explicit and implicit can be ORed together to
|
||||
* allow an "all" limited by access type, even though the
|
||||
* user is stupid to do this since it is default behavior :) */
|
||||
if ( (type & op_explicit) && ! (type & op_implicit) ) {
|
||||
implicit = 0;
|
||||
}
|
||||
if ( (type & op_implicit) && ! (type & op_explicit) ) {
|
||||
_explicit = 0;
|
||||
}
|
||||
|
||||
type = (x86_op_foreach_type)((int)type & 0x0F); /* mask out explicit/implicit operands */
|
||||
|
||||
for ( list = operands; list; list = list->next ) {
|
||||
if (! implicit && (list->op.flags.op_implied) ) {
|
||||
/* operand is implicit */
|
||||
continue;
|
||||
if ( (type & op_explicit) && ! (type & op_implicit) ) {
|
||||
implicit = 0;
|
||||
}
|
||||
if ( (type & op_implicit) && ! (type & op_explicit) ) {
|
||||
_explicit = 0;
|
||||
}
|
||||
|
||||
if (! _explicit && ! (list->op.flags.op_implied) ) {
|
||||
/* operand is not implicit */
|
||||
continue;
|
||||
type = (x86_op_foreach_type)((int)type & 0x0F); /* mask out explicit/implicit operands */
|
||||
|
||||
for ( list = operands; list; list = list->next ) {
|
||||
if (! implicit && (list->op.flags.op_implied) ) {
|
||||
/* operand is implicit */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! _explicit && ! (list->op.flags.op_implied) ) {
|
||||
/* operand is not implicit */
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ( type ) {
|
||||
case op_any:
|
||||
break;
|
||||
case op_dest:
|
||||
if (! (list->op.access & op_write) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_src:
|
||||
if (! (list->op.access & op_read) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_ro:
|
||||
if (! (list->op.access & op_read) ||
|
||||
(list->op.access & op_write ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_wo:
|
||||
if (! (list->op.access & op_write) ||
|
||||
(list->op.access & op_read ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_xo:
|
||||
if (! (list->op.access & op_execute) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_rw:
|
||||
if (! (list->op.access & op_write) ||
|
||||
! (list->op.access & op_read ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_implicit: case op_explicit: /* make gcc happy */
|
||||
break;
|
||||
}
|
||||
/* any non-continue ends up here: invoke the callback */
|
||||
(*func)( &list->op, this, arg );
|
||||
}
|
||||
|
||||
switch ( type ) {
|
||||
case op_any:
|
||||
break;
|
||||
case op_dest:
|
||||
if (! (list->op.access & op_write) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_src:
|
||||
if (! (list->op.access & op_read) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_ro:
|
||||
if (! (list->op.access & op_read) ||
|
||||
(list->op.access & op_write ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_wo:
|
||||
if (! (list->op.access & op_write) ||
|
||||
(list->op.access & op_read ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_xo:
|
||||
if (! (list->op.access & op_execute) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_rw:
|
||||
if (! (list->op.access & op_write) ||
|
||||
! (list->op.access & op_read ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_implicit: case op_explicit: /* make gcc happy */
|
||||
break;
|
||||
}
|
||||
/* any non-continue ends up here: invoke the callback */
|
||||
(*func)( &list->op, this, arg );
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void count_operand( x86_op_t *op, x86_insn_t *insn, void *arg ) {
|
||||
size_t * count = (size_t *) arg;
|
||||
*count = *count + 1;
|
||||
static void count_operand( x86_op_t */*op*/, x86_insn_t */*insn*/, void *arg ) {
|
||||
size_t * count = (size_t *) arg;
|
||||
*count = *count + 1;
|
||||
}
|
||||
|
||||
/** convenience routine: returns count of operands matching 'type' */
|
||||
size_t x86_insn_t::x86_operand_count( enum x86_op_foreach_type type ) {
|
||||
size_t count = 0;
|
||||
size_t count = 0;
|
||||
|
||||
/* save us a list traversal for common counts... */
|
||||
if ( type == op_any ) {
|
||||
return operand_count;
|
||||
} else if ( type == op_explicit ) {
|
||||
return explicit_count;
|
||||
}
|
||||
/* save us a list traversal for common counts... */
|
||||
if ( type == op_any ) {
|
||||
return operand_count;
|
||||
} else if ( type == op_explicit ) {
|
||||
return explicit_count;
|
||||
}
|
||||
|
||||
x86_operand_foreach( count_operand, &count, type );
|
||||
return count;
|
||||
x86_operand_foreach( count_operand, &count, type );
|
||||
return count;
|
||||
}
|
||||
|
||||
/* accessor functions */
|
||||
x86_op_t * x86_insn_t::x86_operand_1st() {
|
||||
if (! explicit_count ) {
|
||||
return NULL;
|
||||
}
|
||||
if (! explicit_count ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &(operands->op);
|
||||
return &(operands->op);
|
||||
}
|
||||
|
||||
x86_op_t * x86_insn_t::x86_operand_2nd( ) {
|
||||
if ( explicit_count < 2 ) {
|
||||
return NULL;
|
||||
}
|
||||
if ( explicit_count < 2 ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &(operands->next->op);
|
||||
return &(operands->next->op);
|
||||
}
|
||||
|
||||
x86_op_t * x86_insn_t::x86_operand_3rd( ) {
|
||||
if ( explicit_count < 3 ) {
|
||||
return NULL;
|
||||
}
|
||||
return &(operands->next->next->op);
|
||||
if ( explicit_count < 3 ) {
|
||||
return NULL;
|
||||
}
|
||||
return &(operands->next->next->op);
|
||||
}
|
||||
|
||||
@ -8,8 +8,9 @@ IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
ADD_DEFINITIONS(/W4)
|
||||
ELSE()
|
||||
#-D_GLIBCXX_DEBUG
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++0x")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG " ) #--coverage
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} " ) #--coverage
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH})
|
||||
@ -17,6 +18,7 @@ SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH})
|
||||
FIND_PACKAGE(LLVM)
|
||||
FIND_PACKAGE(Boost)
|
||||
IF(dcc_build_tests)
|
||||
enable_testing()
|
||||
FIND_PACKAGE(GMock)
|
||||
ENDIF()
|
||||
|
||||
@ -30,9 +32,7 @@ INCLUDE_DIRECTORIES(
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${LLVM_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(dcc_SOURCES
|
||||
src/dcc.cpp
|
||||
set(dcc_LIB_SOURCES
|
||||
src/ast.cpp
|
||||
src/backend.cpp
|
||||
src/bundle.cpp
|
||||
@ -46,6 +46,7 @@ set(dcc_SOURCES
|
||||
src/frontend.cpp
|
||||
src/graph.cpp
|
||||
src/hlicode.cpp
|
||||
src/hltype.cpp
|
||||
src/machine_x86.cpp
|
||||
src/icode.cpp
|
||||
src/idioms.cpp
|
||||
@ -70,6 +71,9 @@ set(dcc_SOURCES
|
||||
src/udm.cpp
|
||||
src/BasicBlock.cpp
|
||||
)
|
||||
set(dcc_SOURCES
|
||||
src/dcc.cpp
|
||||
)
|
||||
set(dcc_HEADERS
|
||||
include/ast.h
|
||||
include/bundle.h
|
||||
@ -105,8 +109,12 @@ set(dcc_HEADERS
|
||||
SOURCE_GROUP(Source FILES ${dcc_SOURCES})
|
||||
SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
|
||||
|
||||
ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS})
|
||||
|
||||
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
|
||||
TARGET_LINK_LIBRARIES(dcc_original disasm_s ${REQ_LLVM_LIBRARIES})
|
||||
ADD_DEPENDENCIES(dcc_original dcc_lib)
|
||||
TARGET_LINK_LIBRARIES(dcc_original dcc_lib disasm_s ${REQ_LLVM_LIBRARIES})
|
||||
|
||||
if(dcc_build_tests)
|
||||
ADD_SUBDIRECTORY(src)
|
||||
endif()
|
||||
|
||||
@ -114,7 +114,7 @@ public:
|
||||
void writeBB(std::ostream &ostr, int lev, Function *pProc, int *numLoc);
|
||||
BB * rmJMP(int marker, BB *pBB);
|
||||
void genDU1();
|
||||
int findBBExps(LOCAL_ID &locals, Function *f);
|
||||
void findBBExps(LOCAL_ID &locals, Function *f);
|
||||
bool valid() {return 0==(flg & INVALID_BB); }
|
||||
bool wasTraversedAtLevel(int l) const {return traversed==l;}
|
||||
ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond);
|
||||
|
||||
@ -57,33 +57,33 @@ enum opLoc
|
||||
enum eLLFlags
|
||||
{
|
||||
|
||||
B =0x0000001, /* uint8_t operands (value implicitly used) */
|
||||
I =0x0000002, /* Immed. source */
|
||||
NOT_HLL =0x0000004, /* Not HLL inst. */
|
||||
FLOAT_OP =0x0000008, /* ESC or WAIT */
|
||||
SEG_IMMED =0x0000010, /* Number is relocated segment value */
|
||||
IMPURE =0x0000020, /* Instruction modifies code */
|
||||
WORD_OFF =0x0000040, /* Inst has uint16_t offset ie.could be address */
|
||||
TERMINATES =0x0000080, /* Instruction terminates program */
|
||||
CASE =0x0000100, /* Label as case part of switch */
|
||||
SWITCH =0x0000200, /* Treat indirect JMP as switch stmt */
|
||||
TARGET =0x0000400, /* Jump target */
|
||||
SYNTHETIC =0x0000800, /* Synthetic jump instruction */
|
||||
NO_LABEL =0x0001000, /* Immed. jump cannot be linked to a label */
|
||||
NO_CODE =0x0002000, /* Hole in Icode array */
|
||||
SYM_USE =0x0004000, /* Instruction uses a symbol */
|
||||
SYM_DEF =0x0008000, /* Instruction defines a symbol */
|
||||
NO_SRC =0x0010000, /* Opcode takes no source */
|
||||
NO_OPS =0x0020000, /* Opcode takes no operands */
|
||||
IM_OPS =0x0040000, /* Opcode takes implicit operands */
|
||||
SRC_B =0x0080000, /* Source operand is uint8_t (dest is uint16_t) */
|
||||
HLL_LABEL =0x0100000, /* Icode has a high level language label */
|
||||
IM_DST =0x0200000, /* Implicit DST for opcode (SIGNEX) */
|
||||
IM_SRC =0x0400000, /* Implicit SRC for opcode (dx:ax) */
|
||||
IM_TMP_DST =0x0800000, /* Implicit rTMP DST for opcode (DIV/IDIV) */
|
||||
JMP_ICODE =0x1000000, /* Jmp dest immed.op converted to icode index */
|
||||
JX_LOOP =0x2000000, /* Cond jump is part of loop conditional exp */
|
||||
REST_STK =0x4000000 /* Stack needs to be restored after CALL */
|
||||
B = 0x0000001, /* uint8_t operands (value implicitly used) */
|
||||
I = 0x0000002, /* Immed. source */
|
||||
NOT_HLL = 0x0000004, /* Not HLL inst. */
|
||||
FLOAT_OP = 0x0000008, /* ESC or WAIT */
|
||||
SEG_IMMED = 0x0000010, /* Number is relocated segment value */
|
||||
IMPURE = 0x0000020, /* Instruction modifies code */
|
||||
WORD_OFF = 0x0000040, /* Inst has uint16_t offset ie.could be address */
|
||||
TERMINATES = 0x0000080, /* Instruction terminates program */
|
||||
CASE = 0x0000100, /* Label as case part of switch */
|
||||
SWITCH = 0x0000200, /* Treat indirect JMP as switch stmt */
|
||||
TARGET = 0x0000400, /* Jump target */
|
||||
SYNTHETIC = 0x0000800, /* Synthetic jump instruction */
|
||||
NO_LABEL = 0x0001000, /* Immed. jump cannot be linked to a label */
|
||||
NO_CODE = 0x0002000, /* Hole in Icode array */
|
||||
SYM_USE = 0x0004000, /* Instruction uses a symbol */
|
||||
SYM_DEF = 0x0008000, /* Instruction defines a symbol */
|
||||
NO_SRC = 0x0010000, /* Opcode takes no source */
|
||||
NO_OPS = 0x0020000, /* Opcode takes no operands */
|
||||
IM_OPS = 0x0040000, /* Opcode takes implicit operands */
|
||||
SRC_B = 0x0080000, /* Source operand is uint8_t (dest is uint16_t) */
|
||||
HLL_LABEL = 0x0100000, /* Icode has a high level language label */
|
||||
IM_DST = 0x0200000, /* Implicit DST for opcode (SIGNEX) */
|
||||
IM_SRC = 0x0400000, /* Implicit SRC for opcode (dx:ax) */
|
||||
IM_TMP_DST = 0x0800000, /* Implicit rTMP DST for opcode (DIV/IDIV) */
|
||||
JMP_ICODE = 0x1000000, /* Jmp dest immed.op converted to icode index */
|
||||
JX_LOOP = 0x2000000, /* Cond jump is part of loop conditional exp */
|
||||
REST_STK = 0x4000000 /* Stack needs to be restored after CALL */
|
||||
#define ICODEMASK 0x0FF00FF /* Masks off parser flags */
|
||||
};
|
||||
/* Types of icodes */
|
||||
@ -237,7 +237,7 @@ enum hlFirst
|
||||
/* HIGH_LEVEL icodes opcodes */
|
||||
enum hlIcode
|
||||
{
|
||||
HLI_INVALID,
|
||||
HLI_INVALID=0,
|
||||
HLI_ASSIGN, /* := */
|
||||
HLI_CALL, /* Call procedure */
|
||||
HLI_JCOND, /* Conditional jump */
|
||||
|
||||
@ -122,12 +122,12 @@ public:
|
||||
std::bitset<32> liveOut; /* Registers that may be used in successors */
|
||||
bool liveAnal; /* Procedure has been analysed already */
|
||||
|
||||
Function(void *ty=0) : procEntry(0),depth(0),flg(0),cbParam(0),m_cfg(0),m_dfsLast(0),numBBs(0),
|
||||
Function(void */*ty*/=0) : procEntry(0),depth(0),flg(0),cbParam(0),m_cfg(0),m_dfsLast(0),numBBs(0),
|
||||
hasCase(false),liveIn(0),liveOut(0),liveAnal(0)//,next(0),prev(0)
|
||||
{
|
||||
}
|
||||
public:
|
||||
static Function *Create(void *ty=0,int Linkage=0,const std::string &nm="",void *module=0)
|
||||
static Function *Create(void *ty=0,int /*Linkage*/=0,const std::string &nm="",void */*module*/=0)
|
||||
{
|
||||
Function *r=new Function(ty);
|
||||
r->name = nm;
|
||||
|
||||
@ -13,7 +13,7 @@ struct STKFRAME : public SymbolTableCommon<STKSYM>
|
||||
int16_t maxOff; /* Maximum offset in stack frame*/
|
||||
int cb; /* Number of bytes in arguments */
|
||||
int numArgs; /* No. of arguments in the table*/
|
||||
void adjustForArgType(int numArg_, hlType actType_);
|
||||
void adjustForArgType(size_t numArg_, hlType actType_);
|
||||
STKFRAME() : m_minOff(0),maxOff(0),cb(0),numArgs(0)
|
||||
{
|
||||
|
||||
|
||||
@ -123,10 +123,10 @@ struct BinaryOperator : public COND_EXPR
|
||||
}
|
||||
static BinaryOperator *Create(condOp o,COND_EXPR *l,COND_EXPR *r);
|
||||
static BinaryOperator *CreateAdd(COND_EXPR *l,COND_EXPR *r);
|
||||
virtual COND_EXPR *inverse();
|
||||
virtual COND_EXPR *clone();
|
||||
virtual COND_EXPR *inverse() const;
|
||||
virtual COND_EXPR *clone() const;
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
|
||||
virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, LOCAL_ID *locsym);
|
||||
virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
virtual COND_EXPR *insertSubTreeLongReg(COND_EXPR *_expr, int longIdx);
|
||||
|
||||
COND_EXPR *lhs()
|
||||
@ -157,8 +157,8 @@ struct UnaryOperator : public COND_EXPR
|
||||
{
|
||||
condOp op;
|
||||
COND_EXPR *unaryExp;
|
||||
virtual COND_EXPR *inverse();
|
||||
virtual COND_EXPR *clone();
|
||||
virtual COND_EXPR *inverse() const;
|
||||
virtual COND_EXPR *clone() const;
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
|
||||
static UnaryOperator *Create(condNodeType t, COND_EXPR *sub_expr)
|
||||
{
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
#include "bundle.h"
|
||||
#include "Procedure.h"
|
||||
#include "BasicBlock.h"
|
||||
struct Project;
|
||||
class Project;
|
||||
/* CALL GRAPH NODE */
|
||||
struct CALL_GRAPH
|
||||
{
|
||||
@ -116,7 +116,7 @@ void parse (CALL_GRAPH * *); /* parser.c */
|
||||
|
||||
int strSize (uint8_t *, char); /* parser.c */
|
||||
//void disassem(int pass, Function * pProc); /* disassem.c */
|
||||
void interactDis(Function * initProc, int initIC); /* disassem.c */
|
||||
void interactDis(Function *, int initIC); /* disassem.c */
|
||||
bool JmpInst(llIcode opcode); /* idioms.c */
|
||||
queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */
|
||||
|
||||
|
||||
@ -25,12 +25,13 @@ struct LOCAL_ID;
|
||||
struct BB;
|
||||
struct Function;
|
||||
struct STKFRAME;
|
||||
struct CIcodeRec;
|
||||
class CIcodeRec;
|
||||
struct ICODE;
|
||||
struct bundle;
|
||||
typedef std::list<ICODE>::iterator iICODE;
|
||||
typedef std::list<ICODE>::reverse_iterator riICODE;
|
||||
typedef boost::iterator_range<iICODE> rCODE;
|
||||
|
||||
extern std::bitset<32> duReg[30];
|
||||
/* uint8_t and uint16_t registers */
|
||||
|
||||
@ -65,7 +66,7 @@ struct CallType : public HlTypeSupport
|
||||
void placeStkArg(COND_EXPR *exp, int pos);
|
||||
virtual COND_EXPR * toId();
|
||||
public:
|
||||
bool removeRegFromLong(eReg regi, LOCAL_ID *locId)
|
||||
bool removeRegFromLong(eReg /*regi*/, LOCAL_ID */*locId*/)
|
||||
{
|
||||
printf("CallType : removeRegFromLong not supproted");
|
||||
return false;
|
||||
@ -106,34 +107,16 @@ public:
|
||||
hlIcode opcode; /* hlIcode opcode */
|
||||
AssignType asgn;
|
||||
CallType call;
|
||||
HlTypeSupport *get()
|
||||
{
|
||||
switch(opcode)
|
||||
{
|
||||
case HLI_ASSIGN: return &asgn;
|
||||
case HLI_RET:
|
||||
case HLI_POP:
|
||||
case HLI_JCOND:
|
||||
case HLI_PUSH: return &exp;
|
||||
case HLI_CALL: return &call;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
HlTypeSupport *get();
|
||||
|
||||
void expr(COND_EXPR *e)
|
||||
{
|
||||
assert(e);
|
||||
exp.v=e;
|
||||
}
|
||||
void replaceExpr(COND_EXPR *e)
|
||||
{
|
||||
assert(e);
|
||||
delete exp.v;
|
||||
exp.v=e;
|
||||
}
|
||||
void replaceExpr(COND_EXPR *e);
|
||||
COND_EXPR * expr() { return exp.v;}
|
||||
const COND_EXPR * const expr() const { return exp.v;}
|
||||
const COND_EXPR * expr() const { return exp.v;}
|
||||
void set(hlIcode i,COND_EXPR *e)
|
||||
{
|
||||
if(i!=HLI_RET)
|
||||
@ -180,7 +163,7 @@ struct LLOperand
|
||||
Function *proc; /* pointer to target proc (for CALL(F))*/
|
||||
int cb; /* # actual arg bytes */
|
||||
} proc;
|
||||
LLOperand() : seg(rUNDEF),segValue(0),segOver(rUNDEF),regi(rUNDEF),off(0),opz(0)
|
||||
LLOperand() : seg(rUNDEF),segOver(rUNDEF),segValue(0),regi(rUNDEF),off(0),opz(0)
|
||||
{
|
||||
proc.proc=0;
|
||||
proc.cb=0;
|
||||
@ -214,6 +197,11 @@ struct LLInst : public llvm::MCInst //: public llvm::ilist_node<LLInst>
|
||||
{
|
||||
protected:
|
||||
uint32_t flg; /* icode flags */
|
||||
// LLOperand &get(int idx)
|
||||
// {
|
||||
// assert(idx<size());
|
||||
// return getOperand(idx);
|
||||
// }
|
||||
LLOperand m_src; /* source operand */
|
||||
public:
|
||||
int codeIdx; /* Index into cCode.code */
|
||||
@ -456,7 +444,7 @@ public:
|
||||
{
|
||||
return hl()->call.newStkArg(exp,opcode,pproc);
|
||||
}
|
||||
ICODE() : m_ll(this),type(NOT_SCANNED),Parent(0),loc_ip(0),invalid(false)
|
||||
ICODE() : m_ll(this),Parent(0),invalid(false),type(NOT_SCANNED),loc_ip(0)
|
||||
{
|
||||
}
|
||||
public:
|
||||
@ -485,6 +473,6 @@ public:
|
||||
void SetInBB(rCODE &rang, BB* pnewBB);
|
||||
bool labelSrch(uint32_t target, uint32_t &pIndex);
|
||||
iterator labelSrch(uint32_t target);
|
||||
ICODE * GetIcode(int ip);
|
||||
ICODE * GetIcode(size_t ip);
|
||||
bool alreadyDecoded(uint32_t target);
|
||||
};
|
||||
|
||||
11
include/loader.h
Normal file
11
include/loader.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
class ILoader
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class LoaderManger
|
||||
{
|
||||
|
||||
};
|
||||
@ -99,7 +99,7 @@ struct ID
|
||||
void setLocalName(int i)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf (buf, "loc%ld", i);
|
||||
sprintf (buf, "loc%d", i);
|
||||
name=buf;
|
||||
}
|
||||
};
|
||||
@ -121,7 +121,7 @@ public:
|
||||
std::vector<ID>::iterator end() {return id_arr.end();}
|
||||
int newByteWordReg(hlType t, eReg regi);
|
||||
int newByteWordStk(hlType t, int off, uint8_t regOff);
|
||||
int newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t);
|
||||
int newIntIdx(int16_t seg, int16_t off, eReg regi, hlType t);
|
||||
int newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_);
|
||||
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, int off);
|
||||
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
|
||||
|
||||
@ -6,55 +6,40 @@
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include "symtab.h"
|
||||
#include "BinaryImage.h"
|
||||
struct Function;
|
||||
struct SourceMachine;
|
||||
#include "Procedure.h"
|
||||
class SourceMachine;
|
||||
struct CALL_GRAPH;
|
||||
class IProject
|
||||
{
|
||||
virtual PROG *binary()=0;
|
||||
virtual const std::string & project_name() const =0;
|
||||
virtual const std::string & binary_path() const =0;
|
||||
};
|
||||
class Project : public IProject
|
||||
{
|
||||
static Project *s_instance;
|
||||
std::string m_fname;
|
||||
std::string m_project_name;
|
||||
public:
|
||||
|
||||
typedef llvm::iplist<Function> FunctionListType;
|
||||
typedef FunctionListType lFunction;
|
||||
typedef lFunction::iterator ilFunction;
|
||||
|
||||
|
||||
struct Project
|
||||
{
|
||||
typedef FunctionListType::iterator ilFunction;
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
|
||||
std::string m_fname;
|
||||
FunctionListType pProcList;
|
||||
CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
PROG prog; /* Loaded program image parameters */
|
||||
Project() {}
|
||||
// no copies
|
||||
Project(const Project&) = delete;
|
||||
const Project &operator=(const Project & l) =delete;
|
||||
// only moves
|
||||
Project(Project && l)
|
||||
{
|
||||
m_fname =l.m_fname;
|
||||
size_t before=l.pProcList.size();
|
||||
pProcList.splice(pProcList.end(),l.pProcList);
|
||||
callGraph=l.callGraph;
|
||||
l.m_fname.clear();
|
||||
l.pProcList.clear();
|
||||
l.callGraph=0;
|
||||
assert(before==pProcList.size());
|
||||
}
|
||||
Project &operator=(Project && l)
|
||||
{
|
||||
if(this == &l)
|
||||
return *this;
|
||||
m_fname =l.m_fname;
|
||||
size_t before=l.pProcList.size();
|
||||
pProcList.splice(pProcList.end(),l.pProcList);
|
||||
callGraph=l.callGraph;
|
||||
l.m_fname.clear();
|
||||
l.pProcList.clear();
|
||||
l.callGraph=0;
|
||||
assert(before==pProcList.size());
|
||||
return *this;
|
||||
}
|
||||
Project(); // default constructor,
|
||||
|
||||
public:
|
||||
void create(const std::string & a);
|
||||
const std::string &project_name() const {return m_project_name;}
|
||||
const std::string &binary_path() const {return m_fname;}
|
||||
ilFunction funcIter(Function *to_find);
|
||||
ilFunction findByEntry(uint32_t entry);
|
||||
ilFunction createFunction();
|
||||
@ -72,6 +57,7 @@ public:
|
||||
SourceMachine *machine();
|
||||
|
||||
protected:
|
||||
void initialize();
|
||||
void writeGlobSymTable();
|
||||
};
|
||||
//extern Project g_proj;
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "error.h"
|
||||
/* Extracts reg bits from middle of mod-reg-rm uint8_t */
|
||||
|
||||
#define REG(x) ((uint8_t)(x & 0x38) >> 3)
|
||||
|
||||
//#define LH(p) ((int)((uint8_t *)(p))[0] + ((int)((uint8_t *)(p))[1] << 8))
|
||||
struct ICODE;
|
||||
|
||||
/* Extracts reg bits from middle of mod-reg-rm uint8_t */
|
||||
extern eErrorId scan(uint32_t ip, ICODE &p);
|
||||
|
||||
@ -27,7 +27,7 @@ struct SYM : public SymbolCommon
|
||||
{
|
||||
|
||||
}
|
||||
int32_t label; /* physical address (20 bit) */
|
||||
uint32_t label; /* physical address (20 bit) */
|
||||
uint32_t flg; /* SEG_IMMED, IMPURE, WORD_OFF */
|
||||
};
|
||||
/* STACK FRAME */
|
||||
@ -60,13 +60,13 @@ class SymbolTableCommon : public std::vector<T>
|
||||
public:
|
||||
typedef typename std::vector<T>::iterator iterator;
|
||||
typedef typename std::vector<T>::const_iterator const_iterator;
|
||||
iterator findByLabel(int lab)
|
||||
iterator findByLabel(uint32_t lab)
|
||||
{
|
||||
auto iter = std::find_if(this->begin(),this->end(),
|
||||
[lab](T &s)->bool {return s.label==lab;});
|
||||
return iter;
|
||||
}
|
||||
const_iterator findByLabel(int lab) const
|
||||
const_iterator findByLabel(uint32_t lab) const
|
||||
{
|
||||
auto iter = std::find_if(this->begin(),this->end(),
|
||||
[lab](const T &s)->bool {return s.label==lab;});
|
||||
@ -102,9 +102,9 @@ struct SYMTABLE
|
||||
enum tableType /* The table types */
|
||||
{
|
||||
Label=0, /* The label table */
|
||||
Comment, /* The comment table */
|
||||
NUM_TABLE_TYPES /* Number of entries: must be last */
|
||||
Comment /* The comment table */
|
||||
};
|
||||
constexpr int NUM_TABLE_TYPES = int(Comment)+1; /* Number of entries: must be last */
|
||||
|
||||
void createSymTables(void);
|
||||
void destroySymTables(void);
|
||||
|
||||
@ -53,9 +53,9 @@ struct eDuVal
|
||||
USE=2,
|
||||
VAL=4
|
||||
};
|
||||
int def :1; /* Variable was first defined than used */
|
||||
int use :1; /* Variable was first used than defined */
|
||||
int val :1; /* Variable has an initial value. 2 cases:
|
||||
uint8_t def :1; /* Variable was first defined than used */
|
||||
uint8_t use :1; /* Variable was first used than defined */
|
||||
uint8_t val :1; /* Variable has an initial value. 2 cases:
|
||||
* 1. When variable is used first (ie. global)
|
||||
* 2. When a value is moved into the variable
|
||||
* for the first time. */
|
||||
@ -65,7 +65,7 @@ struct eDuVal
|
||||
use = x&USE;
|
||||
val = x&VAL;
|
||||
}
|
||||
bool isUSE_VAL() {return use&&val;} /* Use and Val */
|
||||
bool isUSE_VAL() {return use&&val;} /* Use and Val */
|
||||
};
|
||||
static constexpr const char * hlTypes[13] = {
|
||||
"", "char", "unsigned char", "int", "unsigned int",
|
||||
@ -88,6 +88,12 @@ struct TypeContainer
|
||||
return 2;
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
return 1;
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
return 4;
|
||||
case TYPE_FLOAT:
|
||||
return 4;
|
||||
default:
|
||||
return ~0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
BB *BB::Create(void *ctx, const string &s, Function *parent, BB *insertBefore)
|
||||
BB *BB::Create(void */*ctx*/, const string &/*s*/, Function *parent, BB */*insertBefore*/)
|
||||
{
|
||||
BB *pnewBB = new BB;
|
||||
pnewBB->Parent = parent;
|
||||
@ -81,14 +81,14 @@ static const char *const s_loopType[] = {"noLoop", "while", "repeat", "loop", "f
|
||||
void BB::display()
|
||||
{
|
||||
printf("\nnode type = %s, ", s_nodeType[nodeType]);
|
||||
printf("start = %ld, length = %ld, #out edges = %ld\n", begin()->loc_ip, size(), edges.size());
|
||||
printf("start = %d, length = %zd, #out edges = %zd\n", begin()->loc_ip, size(), edges.size());
|
||||
|
||||
for (size_t i = 0; i < edges.size(); i++)
|
||||
{
|
||||
if(edges[i].BBptr==0)
|
||||
printf(" outEdge[%2d] = Unlinked out edge to %d\n",i, edges[i].ip);
|
||||
printf(" outEdge[%2zd] = Unlinked out edge to %d\n",i, edges[i].ip);
|
||||
else
|
||||
printf(" outEdge[%2d] = %d\n",i, edges[i].BBptr->begin()->loc_ip);
|
||||
printf(" outEdge[%2zd] = %d\n",i, edges[i].BBptr->begin()->loc_ip);
|
||||
}
|
||||
}
|
||||
/*****************************************************************************
|
||||
@ -101,29 +101,29 @@ void BB::displayDfs()
|
||||
traversed = DFS_DISP;
|
||||
|
||||
printf("node type = %s, ", s_nodeType[nodeType]);
|
||||
printf("start = %ld, length = %ld, #in-edges = %ld, #out-edges = %ld\n",
|
||||
printf("start = %d, length = %zd, #in-edges = %zd, #out-edges = %zd\n",
|
||||
begin()->loc_ip, size(), inEdges.size(), edges.size());
|
||||
printf("dfsFirst = %ld, dfsLast = %ld, immed dom = %ld\n",
|
||||
printf("dfsFirst = %d, dfsLast = %d, immed dom = %d\n",
|
||||
dfsFirstNum, dfsLastNum,
|
||||
immedDom == MAX ? -1 : immedDom);
|
||||
printf("loopType = %s, loopHead = %ld, latchNode = %ld, follow = %ld\n",
|
||||
printf("loopType = %s, loopHead = %d, latchNode = %d, follow = %d\n",
|
||||
s_loopType[loopType],
|
||||
loopHead == MAX ? -1 : loopHead,
|
||||
latchNode == MAX ? -1 : latchNode,
|
||||
loopFollow == MAX ? -1 : loopFollow);
|
||||
printf ("ifFollow = %ld, caseHead = %ld, caseTail = %ld\n",
|
||||
printf ("ifFollow = %d, caseHead = %d, caseTail = %d\n",
|
||||
ifFollow == MAX ? -1 : ifFollow,
|
||||
caseHead == MAX ? -1 : caseHead,
|
||||
caseTail == MAX ? -1 : caseTail);
|
||||
|
||||
if (nodeType == INTERVAL_NODE)
|
||||
printf("corresponding interval = %ld\n", correspInt->numInt);
|
||||
printf("corresponding interval = %d\n", correspInt->numInt);
|
||||
else
|
||||
{
|
||||
int edge_idx=0;
|
||||
for(BB *node : inEdges)
|
||||
{
|
||||
printf (" inEdge[%ld] = %ld\n", edge_idx, node->begin()->loc_ip);
|
||||
printf (" inEdge[%d] = %d\n", edge_idx, node->begin()->loc_ip);
|
||||
edge_idx++;
|
||||
}
|
||||
}
|
||||
@ -132,9 +132,9 @@ void BB::displayDfs()
|
||||
for(TYPEADR_TYPE &edg : edges)
|
||||
{
|
||||
if (nodeType == INTERVAL_NODE)
|
||||
printf(" outEdge[%ld] = %ld\n", i, edg.BBptr->correspInt->numInt);
|
||||
printf(" outEdge[%d] = %d\n", i, edg.BBptr->correspInt->numInt);
|
||||
else
|
||||
printf(" outEdge[%d] = %ld\n", i, edg.BBptr->begin()->loc_ip);
|
||||
printf(" outEdge[%d] = %d\n", i, edg.BBptr->begin()->loc_ip);
|
||||
++i;
|
||||
}
|
||||
printf("----\n");
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
SET(dcc_test_SOURCES tests/comwrite.cpp)
|
||||
SET(dcc_test_SOURCES
|
||||
tests/comwrite.cpp
|
||||
tests/project.cpp
|
||||
tests/loader.cpp
|
||||
|
||||
)
|
||||
include_directories(${GMOCK_INCLUDE_DIRS} ${GMOCK_ROOT}/gtest/include)
|
||||
enable_testing()
|
||||
add_executable(tester ${dcc_test_SOURCES})
|
||||
target_link_libraries(tester
|
||||
ADD_DEPENDENCIES(tester dcc_lib)
|
||||
|
||||
target_link_libraries(tester dcc_lib disasm_s
|
||||
${GMOCK_BOTH_LIBRARIES} ${REQ_LLVM_LIBRARIES})
|
||||
add_test(dcc-tests tester)
|
||||
|
||||
361
src/ast.cpp
361
src/ast.cpp
@ -13,7 +13,6 @@
|
||||
#include "dcc.h"
|
||||
#include "machine_x86.h"
|
||||
#include "project.h"
|
||||
extern Project g_proj;
|
||||
using namespace std;
|
||||
// Conditional operator symbols in C. Index by condOp enumeration type
|
||||
static const char * const condOpSym[] = { " <= ", " < ", " == ", " != ", " > ", " >= ",
|
||||
@ -122,8 +121,8 @@ COND_EXPR *GlobalVariable::Create(int16_t segValue, int16_t off)
|
||||
newExp = new COND_EXPR(IDENTIFIER);
|
||||
newExp->expr.ident.idType = GLOB_VAR;
|
||||
adr = opAdr(segValue, off);
|
||||
auto i=g_proj.getSymIdxByAdd(adr);
|
||||
if ( not g_proj.validSymIdx(i) )
|
||||
auto i=Project::get()->getSymIdxByAdd(adr);
|
||||
if ( not Project::get()->validSymIdx(i) )
|
||||
{
|
||||
printf ("Error, glob var not found in symtab\n");
|
||||
delete newExp;
|
||||
@ -477,7 +476,7 @@ int hlTypeSize (const COND_EXPR *expr, Function * pproc)
|
||||
switch (expr->expr.ident.idType)
|
||||
{
|
||||
case GLOB_VAR:
|
||||
return (g_proj.symbolSize(expr->expr.ident.idNode.globIdx));
|
||||
return (Project::get()->symbolSize(expr->expr.ident.idNode.globIdx));
|
||||
case REGISTER:
|
||||
if (expr->expr.ident.regiType == BYTE_REG)
|
||||
return (1);
|
||||
@ -501,6 +500,9 @@ int hlTypeSize (const COND_EXPR *expr, Function * pproc)
|
||||
return (2);
|
||||
} /* eos */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"hlTypeSize queried for Unkown type %d \n",expr->m_type);
|
||||
break;
|
||||
}
|
||||
return 2; // CC: is this correct?
|
||||
}
|
||||
@ -540,7 +542,7 @@ hlType COND_EXPR::expType(Function * pproc) const
|
||||
switch (expr.ident.idType)
|
||||
{
|
||||
case GLOB_VAR:
|
||||
return g_proj.symbolType(expr.ident.idNode.globIdx);
|
||||
return Project::get()->symbolType(expr.ident.idNode.globIdx);
|
||||
case REGISTER:
|
||||
if (expr.ident.regiType == BYTE_REG)
|
||||
return (TYPE_BYTE_SIGN);
|
||||
@ -580,23 +582,26 @@ void HlTypeSupport::performLongRemoval (eReg regi, LOCAL_ID *locId, COND_EXPR *t
|
||||
eReg otherRegi; /* high or low part of long register */
|
||||
|
||||
switch (tree->m_type) {
|
||||
case BOOLEAN_OP:
|
||||
break;
|
||||
case POST_INC: case POST_DEC:
|
||||
case PRE_INC: case PRE_DEC:
|
||||
case NEGATION: case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
break;
|
||||
case IDENTIFIER:
|
||||
ident = &tree->expr.ident;
|
||||
if (ident->idType == LONG_VAR)
|
||||
{
|
||||
otherRegi = otherLongRegi (regi, ident->idNode.longIdx, locId);
|
||||
ident->idType = REGISTER;
|
||||
ident->regiType = WORD_REG;
|
||||
ident->idNode.regiIdx = locId->newByteWordReg(TYPE_WORD_SIGN,otherRegi);
|
||||
}
|
||||
break;
|
||||
case BOOLEAN_OP:
|
||||
break;
|
||||
case POST_INC: case POST_DEC:
|
||||
case PRE_INC: case PRE_DEC:
|
||||
case NEGATION: case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
break;
|
||||
case IDENTIFIER:
|
||||
ident = &tree->expr.ident;
|
||||
if (ident->idType == LONG_VAR)
|
||||
{
|
||||
otherRegi = otherLongRegi (regi, ident->idNode.longIdx, locId);
|
||||
ident->idType = REGISTER;
|
||||
ident->regiType = WORD_REG;
|
||||
ident->idNode.regiIdx = locId->newByteWordReg(TYPE_WORD_SIGN,otherRegi);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"performLongRemoval attemped on %d\n",tree->m_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -634,154 +639,159 @@ string walkCondExpr (const COND_EXPR* expr, Function * pProc, int* numLoc)
|
||||
needBracket = true;
|
||||
switch (expr->m_type)
|
||||
{
|
||||
case BOOLEAN_OP:
|
||||
outStr << "(";
|
||||
outStr << walkCondExpr(expr->lhs(), pProc, numLoc);
|
||||
outStr << condOpSym[expr->op()];
|
||||
outStr << walkCondExpr(expr->rhs(), pProc, numLoc);
|
||||
outStr << ")";
|
||||
break;
|
||||
|
||||
case NEGATION:
|
||||
if (expr->expr.unaryExp->m_type == IDENTIFIER)
|
||||
{
|
||||
needBracket = false;
|
||||
outStr << "!";
|
||||
}
|
||||
else
|
||||
outStr << "! (";
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
if (needBracket == true)
|
||||
outStr << ")";
|
||||
break;
|
||||
|
||||
case ADDRESSOF:
|
||||
if (expr->expr.unaryExp->m_type == IDENTIFIER)
|
||||
{
|
||||
needBracket = false;
|
||||
outStr << "&";
|
||||
}
|
||||
else
|
||||
outStr << "&(";
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
if (needBracket == true)
|
||||
outStr << ")";
|
||||
break;
|
||||
|
||||
case DEREFERENCE:
|
||||
outStr << "*";
|
||||
if (expr->expr.unaryExp->m_type == IDENTIFIER)
|
||||
needBracket = false;
|
||||
else
|
||||
case BOOLEAN_OP:
|
||||
outStr << "(";
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
if (needBracket == true)
|
||||
outStr << walkCondExpr(expr->lhs(), pProc, numLoc);
|
||||
outStr << condOpSym[expr->op()];
|
||||
outStr << walkCondExpr(expr->rhs(), pProc, numLoc);
|
||||
outStr << ")";
|
||||
break;
|
||||
break;
|
||||
|
||||
case POST_INC:
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc) << "++";
|
||||
break;
|
||||
case NEGATION:
|
||||
if (expr->expr.unaryExp->m_type == IDENTIFIER)
|
||||
{
|
||||
needBracket = false;
|
||||
outStr << "!";
|
||||
}
|
||||
else
|
||||
outStr << "! (";
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
if (needBracket == true)
|
||||
outStr << ")";
|
||||
break;
|
||||
|
||||
case POST_DEC:
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc) << "--";
|
||||
break;
|
||||
case ADDRESSOF:
|
||||
if (expr->expr.unaryExp->m_type == IDENTIFIER)
|
||||
{
|
||||
needBracket = false;
|
||||
outStr << "&";
|
||||
}
|
||||
else
|
||||
outStr << "&(";
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
if (needBracket == true)
|
||||
outStr << ")";
|
||||
break;
|
||||
|
||||
case PRE_INC:
|
||||
outStr << "++"<< walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
break;
|
||||
case DEREFERENCE:
|
||||
outStr << "*";
|
||||
if (expr->expr.unaryExp->m_type == IDENTIFIER)
|
||||
needBracket = false;
|
||||
else
|
||||
outStr << "(";
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
if (needBracket == true)
|
||||
outStr << ")";
|
||||
break;
|
||||
|
||||
case PRE_DEC:
|
||||
outStr << "--"<< walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
break;
|
||||
case POST_INC:
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc) << "++";
|
||||
break;
|
||||
|
||||
case IDENTIFIER:
|
||||
std::ostringstream o;
|
||||
switch (expr->expr.ident.idType)
|
||||
case POST_DEC:
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc) << "--";
|
||||
break;
|
||||
|
||||
case PRE_INC:
|
||||
outStr << "++"<< walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
break;
|
||||
|
||||
case PRE_DEC:
|
||||
outStr << "--"<< walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
break;
|
||||
|
||||
case IDENTIFIER:
|
||||
{
|
||||
case GLOB_VAR:
|
||||
o << g_proj.symtab[expr->expr.ident.idNode.globIdx].name;
|
||||
break;
|
||||
case REGISTER:
|
||||
id = &pProc->localId.id_arr[expr->expr.ident.idNode.regiIdx];
|
||||
if (id->name[0] == '\0') /* no name */
|
||||
std::ostringstream o;
|
||||
switch (expr->expr.ident.idType)
|
||||
{
|
||||
id->setLocalName(++(*numLoc));
|
||||
codeOut <<TypeContainer::typeName(id->type)<< " "<<id->name<<"; ";
|
||||
codeOut <<"/* "<<Machine_X86::regName(id->id.regi)<<" */\n";
|
||||
}
|
||||
if (id->hasMacro)
|
||||
o << id->macro << "("<<id->name<<")";
|
||||
else
|
||||
o << id->name;
|
||||
break;
|
||||
case GLOB_VAR:
|
||||
o << Project::get()->symtab[expr->expr.ident.idNode.globIdx].name;
|
||||
break;
|
||||
case REGISTER:
|
||||
id = &pProc->localId.id_arr[expr->expr.ident.idNode.regiIdx];
|
||||
if (id->name[0] == '\0') /* no name */
|
||||
{
|
||||
id->setLocalName(++(*numLoc));
|
||||
codeOut <<TypeContainer::typeName(id->type)<< " "<<id->name<<"; ";
|
||||
codeOut <<"/* "<<Machine_X86::regName(id->id.regi)<<" */\n";
|
||||
}
|
||||
if (id->hasMacro)
|
||||
o << id->macro << "("<<id->name<<")";
|
||||
else
|
||||
o << id->name;
|
||||
break;
|
||||
|
||||
case LOCAL_VAR:
|
||||
o << pProc->localId.id_arr[expr->expr.ident.idNode.localIdx].name;
|
||||
break;
|
||||
case LOCAL_VAR:
|
||||
o << pProc->localId.id_arr[expr->expr.ident.idNode.localIdx].name;
|
||||
break;
|
||||
|
||||
case PARAM:
|
||||
psym = &pProc->args[expr->expr.ident.idNode.paramIdx];
|
||||
if (psym->hasMacro)
|
||||
o << psym->macro<<"("<<psym->name<< ")";
|
||||
else
|
||||
o << psym->name;
|
||||
break;
|
||||
case PARAM:
|
||||
psym = &pProc->args[expr->expr.ident.idNode.paramIdx];
|
||||
if (psym->hasMacro)
|
||||
o << psym->macro<<"("<<psym->name<< ")";
|
||||
else
|
||||
o << psym->name;
|
||||
break;
|
||||
|
||||
case GLOB_VAR_IDX:
|
||||
bwGlb = &pProc->localId.id_arr[expr->expr.ident.idNode.idxGlbIdx].id.bwGlb;
|
||||
o << (bwGlb->seg << 4) + bwGlb->off << "["<<Machine_X86::regName(bwGlb->regi)<<"]";
|
||||
break;
|
||||
case GLOB_VAR_IDX:
|
||||
bwGlb = &pProc->localId.id_arr[expr->expr.ident.idNode.idxGlbIdx].id.bwGlb;
|
||||
o << (bwGlb->seg << 4) + bwGlb->off << "["<<Machine_X86::regName(bwGlb->regi)<<"]";
|
||||
break;
|
||||
|
||||
case CONSTANT:
|
||||
if (expr->expr.ident.idNode.kte.kte < 1000)
|
||||
o << expr->expr.ident.idNode.kte.kte;
|
||||
else
|
||||
o << "0x"<<std::hex << expr->expr.ident.idNode.kte.kte;
|
||||
break;
|
||||
case CONSTANT:
|
||||
if (expr->expr.ident.idNode.kte.kte < 1000)
|
||||
o << expr->expr.ident.idNode.kte.kte;
|
||||
else
|
||||
o << "0x"<<std::hex << expr->expr.ident.idNode.kte.kte;
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
o << getString (expr->expr.ident.idNode.strIdx);
|
||||
break;
|
||||
case STRING:
|
||||
o << getString (expr->expr.ident.idNode.strIdx);
|
||||
break;
|
||||
|
||||
case LONG_VAR:
|
||||
id = &pProc->localId.id_arr[expr->expr.ident.idNode.longIdx];
|
||||
if (id->name[0] != '\0') /* STK_FRAME & REG w/name*/
|
||||
o << id->name;
|
||||
else if (id->loc == REG_FRAME)
|
||||
{
|
||||
id->setLocalName(++(*numLoc));
|
||||
codeOut <<TypeContainer::typeName(id->type)<< " "<<id->name<<"; ";
|
||||
codeOut <<"/* "<<Machine_X86::regName(id->id.longId.h) << ":" <<
|
||||
Machine_X86::regName(id->id.longId.l) << " */\n";
|
||||
o << id->name;
|
||||
pProc->localId.propLongId (id->id.longId.l,id->id.longId.h, id->name.c_str());
|
||||
}
|
||||
else /* GLB_FRAME */
|
||||
{
|
||||
if (id->id.longGlb.regi == 0) /* not indexed */
|
||||
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"]";
|
||||
else if (id->id.longGlb.regi == rBX)
|
||||
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"][bx]";
|
||||
}
|
||||
break;
|
||||
case LONG_VAR:
|
||||
id = &pProc->localId.id_arr[expr->expr.ident.idNode.longIdx];
|
||||
if (id->name[0] != '\0') /* STK_FRAME & REG w/name*/
|
||||
o << id->name;
|
||||
else if (id->loc == REG_FRAME)
|
||||
{
|
||||
id->setLocalName(++(*numLoc));
|
||||
codeOut <<TypeContainer::typeName(id->type)<< " "<<id->name<<"; ";
|
||||
codeOut <<"/* "<<Machine_X86::regName(id->id.longId.h) << ":" <<
|
||||
Machine_X86::regName(id->id.longId.l) << " */\n";
|
||||
o << id->name;
|
||||
pProc->localId.propLongId (id->id.longId.l,id->id.longId.h, id->name.c_str());
|
||||
}
|
||||
else /* GLB_FRAME */
|
||||
{
|
||||
if (id->id.longGlb.regi == 0) /* not indexed */
|
||||
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"]";
|
||||
else if (id->id.longGlb.regi == rBX)
|
||||
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"][bx]";
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNCTION:
|
||||
o << writeCall (expr->expr.ident.idNode.call.proc,*expr->expr.ident.idNode.call.args, pProc, numLoc);
|
||||
break;
|
||||
case FUNCTION:
|
||||
o << writeCall (expr->expr.ident.idNode.call.proc,*expr->expr.ident.idNode.call.args, pProc, numLoc);
|
||||
break;
|
||||
|
||||
case OTHER:
|
||||
off = expr->expr.ident.idNode.other.off;
|
||||
o << Machine_X86::regName(expr->expr.ident.idNode.other.seg)<< "[";
|
||||
o << Machine_X86::regName(expr->expr.ident.idNode.other.regi);
|
||||
if (off < 0)
|
||||
o << "-"<< hexStr (-off);
|
||||
else if (off>0)
|
||||
o << "+"<< hexStr (off);
|
||||
o << "]";
|
||||
} /* eos */
|
||||
outStr << o.str();
|
||||
break;
|
||||
case OTHER:
|
||||
off = expr->expr.ident.idNode.other.off;
|
||||
o << Machine_X86::regName(expr->expr.ident.idNode.other.seg)<< "[";
|
||||
o << Machine_X86::regName(expr->expr.ident.idNode.other.regi);
|
||||
if (off < 0)
|
||||
o << "-"<< hexStr (-off);
|
||||
else if (off>0)
|
||||
o << "+"<< hexStr (off);
|
||||
o << "]";
|
||||
} /* eos */
|
||||
outStr << o.str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr,"walkCondExpr attemped on %d\n",expr->m_type);
|
||||
break;
|
||||
}
|
||||
cCode.appendDecl(codeOut.str());
|
||||
return outStr.str();
|
||||
@ -796,21 +806,23 @@ COND_EXPR *COND_EXPR::clone() const
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case BOOLEAN_OP:
|
||||
newExp = new COND_EXPR(*this);
|
||||
newExp->boolExpr.lhs = lhs()->clone();
|
||||
newExp->boolExpr.rhs = rhs()->clone();
|
||||
break;
|
||||
case BOOLEAN_OP:
|
||||
newExp = new COND_EXPR(*this);
|
||||
newExp->boolExpr.lhs = lhs()->clone();
|
||||
newExp->boolExpr.rhs = rhs()->clone();
|
||||
break;
|
||||
|
||||
case NEGATION:
|
||||
case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
newExp = new COND_EXPR(*this);
|
||||
newExp->expr.unaryExp = expr.unaryExp->clone();
|
||||
break;
|
||||
case NEGATION:
|
||||
case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
newExp = new COND_EXPR(*this);
|
||||
newExp->expr.unaryExp = expr.unaryExp->clone();
|
||||
break;
|
||||
|
||||
case IDENTIFIER:
|
||||
return new COND_EXPR(*this);
|
||||
case IDENTIFIER:
|
||||
return new COND_EXPR(*this);
|
||||
default:
|
||||
fprintf(stderr,"Clone attempt on unhandled type %d\n",m_type);
|
||||
}
|
||||
return (newExp);
|
||||
}
|
||||
@ -857,7 +869,7 @@ COND_EXPR *COND_EXPR::insertSubTreeReg (COND_EXPR *_expr, eReg regi,const LOCAL_
|
||||
return _expr;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return nullptr;
|
||||
|
||||
case BOOLEAN_OP:
|
||||
temp = lhs()->insertSubTreeReg( _expr, regi, locsym);
|
||||
@ -884,11 +896,14 @@ COND_EXPR *COND_EXPR::insertSubTreeReg (COND_EXPR *_expr, eReg regi,const LOCAL_
|
||||
return this;
|
||||
}
|
||||
return nullptr;
|
||||
default:
|
||||
fprintf(stderr,"insertSubTreeReg attempt on unhandled type %d\n",m_type);
|
||||
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
COND_EXPR *BinaryOperator::insertSubTreeReg(COND_EXPR *_expr, eReg regi, LOCAL_ID *locsym)
|
||||
COND_EXPR *BinaryOperator::insertSubTreeReg(COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym)
|
||||
{
|
||||
COND_EXPR *r;
|
||||
r=m_lhs->insertSubTreeReg(_expr,regi,locsym);
|
||||
@ -957,6 +972,8 @@ COND_EXPR *COND_EXPR::insertSubTreeLongReg(COND_EXPR *_expr, int longIdx)
|
||||
return this;
|
||||
}
|
||||
return nullptr;
|
||||
default:
|
||||
fprintf(stderr,"insertSubTreeLongReg attempt on unhandled type %d\n",m_type);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -993,13 +1010,15 @@ void COND_EXPR::release()
|
||||
case DEREFERENCE:
|
||||
expr.unaryExp->release();
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"release attempt on unhandled type %d\n",m_type);
|
||||
}
|
||||
delete (this);
|
||||
}
|
||||
/* Makes a copy of the given expression. Allocates newExp storage for each
|
||||
* node. Returns the copy. */
|
||||
|
||||
COND_EXPR *BinaryOperator::clone()
|
||||
COND_EXPR *BinaryOperator::clone() const
|
||||
{
|
||||
BinaryOperator* newExp=new BinaryOperator(m_op); /* Expression node copy */
|
||||
newExp->m_lhs = m_lhs->clone();
|
||||
@ -1007,7 +1026,7 @@ COND_EXPR *BinaryOperator::clone()
|
||||
return newExp;
|
||||
}
|
||||
|
||||
COND_EXPR *BinaryOperator::inverse()
|
||||
COND_EXPR *BinaryOperator::inverse() const
|
||||
{
|
||||
static condOp invCondOp[] = {GREATER, GREATER_EQUAL, NOT_EQUAL, EQUAL,
|
||||
LESS_EQUAL, LESS, DUMMY,DUMMY,DUMMY,DUMMY,
|
||||
@ -1030,6 +1049,8 @@ COND_EXPR *BinaryOperator::inverse()
|
||||
res->m_lhs=m_lhs->inverse ();
|
||||
res->m_rhs=m_rhs->inverse ();
|
||||
return res;
|
||||
default:
|
||||
fprintf(stderr,"BinaryOperator::inverse attempt on unhandled op %d\n",m_op);
|
||||
} /* eos */
|
||||
assert(false);
|
||||
return res;
|
||||
|
||||
@ -178,11 +178,12 @@ static void writeHeader (std::ostream &_ios, char *fileName)
|
||||
}
|
||||
|
||||
// Note: Not currently called!
|
||||
/* Checks the given icode to determine whether it has a label associated
|
||||
/** Checks the given icode to determine whether it has a label associated
|
||||
* to it. If so, a goto is emitted to this label; otherwise, a new label
|
||||
* is created and a goto is also emitted.
|
||||
* Note: this procedure is to be used when the label is to be forward on
|
||||
* the code; that is, the target code has not been traversed yet. */
|
||||
#if 0
|
||||
static void emitFwdGotoLabel (ICODE * pt, int indLevel)
|
||||
{
|
||||
if ( not pt->ll()->testFlags(HLL_LABEL)) /* node hasn't got a lab */
|
||||
@ -193,7 +194,7 @@ static void emitFwdGotoLabel (ICODE * pt, int indLevel)
|
||||
}
|
||||
cCode.appendCode( "%sgoto l%ld;\n", indentStr(indLevel), pt->ll()->hllLabNum);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Writes the procedure's declaration (including arguments), local variables,
|
||||
* and invokes the procedure that writes the code of the given record *hli */
|
||||
|
||||
@ -26,7 +26,7 @@ void strTable::addLabelBundle (int idx, int label)
|
||||
if(at(idx).size()<4)
|
||||
at(idx)=s;
|
||||
else
|
||||
at(idx) = string(s)+at(idx).substr(4);
|
||||
at(idx) = string(s)+at(idx).substr(4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -219,8 +219,8 @@ static uint8_t pattMainSmall[] =
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0xE8, WILD, WILD /* call _main */
|
||||
/* 0x50, /* push ax... not in Borland V3 */
|
||||
/* 0xE8 /* call _exit */
|
||||
// 0x50, /* push ax... not in Borland V3 */
|
||||
// 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINSMALL 13
|
||||
@ -232,9 +232,9 @@ static uint8_t pattMainMedium[] =
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0x9A, WILD, WILD, WILD, WILD /* call far _main */
|
||||
/* 0x50 /* push ax */
|
||||
/* 0x0E, /* push cs NB not tested Borland */
|
||||
/* 0xE8 /* call _exit */
|
||||
// 0x50 /* push ax */
|
||||
// 0x0E, /* push cs NB not tested Borland */
|
||||
// 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINMEDIUM 13
|
||||
@ -248,8 +248,8 @@ static uint8_t pattMainCompact[] =
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv hi */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0xE8, WILD, WILD, /* call _main */
|
||||
/* 0x50, /* push ax */
|
||||
/* 0xE8 /* call _exit */
|
||||
// 0x50, /* push ax */
|
||||
// 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINCOMPACT 21
|
||||
@ -263,9 +263,9 @@ static uint8_t pattMainLarge[] =
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv hi */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0x9A, WILD, WILD, WILD, WILD /* call far _main */
|
||||
/* 0x50 /* push ax */
|
||||
/* 0x0E, /* push cs */
|
||||
/* 0xE8 /* call _exit */
|
||||
// 0x50 /* push ax */
|
||||
// 0x0E, /* push cs */
|
||||
// 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINLARGE 21
|
||||
@ -502,6 +502,8 @@ bool LibCheck(Function & pProc)
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
pProc.liveOut = duReg[rAL];
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Unknown retval type %d in LibCheck\n",pProc.retVal.type);
|
||||
/*** other types are not considered yet ***/
|
||||
}
|
||||
}
|
||||
@ -569,12 +571,12 @@ readFileSection(uint16_t* p, int len, FILE* f)
|
||||
}
|
||||
|
||||
/* The following two functions are dummies, since we don't call map() */
|
||||
void getKey(int i, uint8_t **keys)
|
||||
void getKey(int /*i*/, uint8_t **/*keys*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void dispKey(int i)
|
||||
void dispKey(int /*i*/)
|
||||
{
|
||||
|
||||
}
|
||||
@ -695,7 +697,7 @@ void STATE::checkStartup()
|
||||
but decides the model required. Note: must do the far data models
|
||||
(large and compact) before the others, since they are the same pattern
|
||||
as near data, just more pushes at the start. */
|
||||
if(prog.cbImage>startOff+0x180+sizeof(pattMainLarge))
|
||||
if(prog.cbImage>int(startOff+0x180+sizeof(pattMainLarge)))
|
||||
{
|
||||
if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainLarge,sizeof(pattMainLarge), &i))
|
||||
{
|
||||
|
||||
@ -244,6 +244,9 @@ void Function::writeProcComments(std::ostream &ostr)
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
ostr << " * Return value in registers dx:ax.\n";
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Unknown retval type %d",this->retVal.type);
|
||||
break;
|
||||
} /* eos */
|
||||
}
|
||||
|
||||
|
||||
@ -300,13 +300,12 @@ void Function::structLoops(derSeq *derivedG)
|
||||
{
|
||||
pred = intHead->inEdges[i];
|
||||
if (inInt(pred, intNodes) && isBackEdge(pred, intHead))
|
||||
{
|
||||
if (! latchNode)
|
||||
latchNode = pred;
|
||||
else
|
||||
{
|
||||
if (pred->dfsLastNum > latchNode->dfsLastNum)
|
||||
latchNode = pred;
|
||||
}
|
||||
else if (pred->dfsLastNum > latchNode->dfsLastNum)
|
||||
latchNode = pred;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find nodes in the loop and the type of loop */
|
||||
@ -352,8 +351,7 @@ static bool successor (int s, int h, Function * pProc)
|
||||
* case). */
|
||||
static void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
|
||||
{
|
||||
int current, /* index to current node */
|
||||
i;
|
||||
int current; /* index to current node */
|
||||
|
||||
pBB->traversed = DFS_CASE;
|
||||
current = pBB->dfsLastNum;
|
||||
@ -374,44 +372,46 @@ static void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
|
||||
* has a case node. */
|
||||
void Function::structCases()
|
||||
{
|
||||
int i, j;
|
||||
BB * caseHeader; /* case header node */
|
||||
int exitNode = NO_NODE; /* case exit node */
|
||||
nodeList caseNodes; /* temporary: list of nodes in case */
|
||||
|
||||
/* Linear scan of the nodes in reverse dfsLast order, searching for
|
||||
* case nodes */
|
||||
for (i = numBBs - 1; i >= 0; i--)
|
||||
if (m_dfsLast[i]->nodeType == MULTI_BRANCH)
|
||||
{
|
||||
caseHeader = m_dfsLast[i];
|
||||
for (int i = numBBs - 1; i >= 0; i--)
|
||||
{
|
||||
if ((m_dfsLast[i]->nodeType != MULTI_BRANCH))
|
||||
continue;
|
||||
BB * caseHeader = m_dfsLast[i];; /* case header node */
|
||||
|
||||
/* Find descendant node which has as immediate predecessor
|
||||
/* Find descendant node which has as immediate predecessor
|
||||
* the current header node, and is not a successor. */
|
||||
for (j = i + 2; j < numBBs; j++)
|
||||
for (size_t j = i + 2; j < numBBs; j++)
|
||||
{
|
||||
if ((!successor(j, i, this)) && (m_dfsLast[j]->immedDom == i))
|
||||
{
|
||||
if ((!successor(j, i, this)) &&
|
||||
(m_dfsLast[j]->immedDom == i))
|
||||
if (exitNode == NO_NODE)
|
||||
exitNode = j;
|
||||
else if (m_dfsLast[exitNode]->inEdges.size() < m_dfsLast[j]->inEdges.size())
|
||||
exitNode = j;
|
||||
if (exitNode == NO_NODE)
|
||||
{
|
||||
exitNode = j;
|
||||
}
|
||||
else if (m_dfsLast[exitNode]->inEdges.size() < m_dfsLast[j]->inEdges.size())
|
||||
exitNode = j;
|
||||
}
|
||||
m_dfsLast[i]->caseTail = exitNode;
|
||||
|
||||
/* Tag nodes that belong to the case by recording the
|
||||
* header field with caseHeader. */
|
||||
insertList (caseNodes, i);
|
||||
m_dfsLast[i]->caseHead = i;
|
||||
for(TYPEADR_TYPE &pb : caseHeader->edges)
|
||||
{
|
||||
tagNodesInCase(pb.BBptr, caseNodes, i, exitNode);
|
||||
}
|
||||
//for (j = 0; j < caseHeader->edges[j]; j++)
|
||||
// tagNodesInCase (caseHeader->edges[j].BBptr, caseNodes, i, exitNode);
|
||||
if (exitNode != NO_NODE)
|
||||
m_dfsLast[exitNode]->caseHead = i;
|
||||
}
|
||||
m_dfsLast[i]->caseTail = exitNode;
|
||||
|
||||
/* Tag nodes that belong to the case by recording the
|
||||
* header field with caseHeader. */
|
||||
insertList (caseNodes, i);
|
||||
m_dfsLast[i]->caseHead = i;
|
||||
for(TYPEADR_TYPE &pb : caseHeader->edges)
|
||||
{
|
||||
tagNodesInCase(pb.BBptr, caseNodes, i, exitNode);
|
||||
}
|
||||
//for (j = 0; j < caseHeader->edges[j]; j++)
|
||||
// tagNodesInCase (caseHeader->edges[j].BBptr, caseNodes, i, exitNode);
|
||||
if (exitNode != NO_NODE)
|
||||
m_dfsLast[exitNode]->caseHead = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -432,7 +432,7 @@ static void flagNodes (nodeList &l, int f, Function * pProc)
|
||||
void Function::structIfs ()
|
||||
{
|
||||
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 */
|
||||
nodeList domDesc, /* List of nodes dominated by curr */
|
||||
@ -454,7 +454,7 @@ void Function::structIfs ()
|
||||
follow = 0;
|
||||
|
||||
/* Find all nodes that have this node as immediate dominator */
|
||||
for (desc = curr+1; desc < numBBs; desc++)
|
||||
for (size_t desc = curr+1; desc < numBBs; desc++)
|
||||
{
|
||||
if (m_dfsLast[desc]->immedDom == curr)
|
||||
{
|
||||
@ -603,7 +603,7 @@ void Function::compoundCond()
|
||||
|
||||
/* Traverse nodes in postorder, this way, the header node of a
|
||||
* compound condition is analysed first */
|
||||
for (int i = 0; i < this->numBBs; i++)
|
||||
for (size_t i = 0; i < this->numBBs; i++)
|
||||
{
|
||||
pbb = this->m_dfsLast[i];
|
||||
if (pbb->flg & INVALID_BB)
|
||||
|
||||
118
src/dataflow.cpp
118
src/dataflow.cpp
@ -114,7 +114,7 @@ static COND_EXPR *dstIdent (const LLInst & ll_insn, Function * pProc, iICODE i,
|
||||
/* Eliminates all condition codes and generates new hlIcode instructions */
|
||||
void Function::elimCondCodes ()
|
||||
{
|
||||
int i;
|
||||
// int i;
|
||||
|
||||
uint8_t use; /* Used flags bit vector */
|
||||
uint8_t def; /* Defined flags bit vector */
|
||||
@ -122,15 +122,19 @@ void Function::elimCondCodes ()
|
||||
COND_EXPR *rhs; /* Source operand */
|
||||
COND_EXPR *lhs; /* Destination operand */
|
||||
COND_EXPR *_expr; /* Boolean expression */
|
||||
BB * pBB; /* Pointer to BBs in dfs last ordering */
|
||||
//BB * pBB; /* Pointer to BBs in dfs last ordering */
|
||||
riICODE useAt; /* Instruction that used flag */
|
||||
riICODE defAt; /* Instruction that defined flag */
|
||||
//lhs=rhs=_expr=0;
|
||||
for (i = 0; i < numBBs; i++)
|
||||
auto valid_reversed_bbs = (m_dfsLast | reversed | filtered(BB::ValidFunctor()) );
|
||||
for( BB * pBB : valid_reversed_bbs)
|
||||
{
|
||||
pBB = m_dfsLast[i];
|
||||
if (pBB->flg & INVALID_BB)
|
||||
continue; /* Do not process invalid BBs */
|
||||
|
||||
// for (size_t i = 0; i < numBBs; i++)
|
||||
// {
|
||||
// pBB = m_dfsLast[i];
|
||||
// if (pBB->flg & INVALID_BB)
|
||||
// continue; /* Do not process invalid BBs */
|
||||
// auto v(pBB | boost::adaptors::reversed);
|
||||
// for (const ICODE &useAt : v)
|
||||
// {}
|
||||
@ -245,11 +249,10 @@ void Function::elimCondCodes ()
|
||||
* is not really meant to be a register that is used before defined). */
|
||||
void Function::genLiveKtes ()
|
||||
{
|
||||
int i;
|
||||
BB * pbb;
|
||||
bitset<32> liveUse, def;
|
||||
|
||||
for (i = 0; i < numBBs; i++)
|
||||
for (size_t i = 0; i < numBBs; i++)
|
||||
{
|
||||
liveUse.reset();
|
||||
def.reset();
|
||||
@ -617,42 +620,45 @@ bool COND_EXPR::xClear (rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case IDENTIFIER:
|
||||
if (expr.ident.idType == REGISTER)
|
||||
{
|
||||
regi= locId.id_arr[expr.ident.idNode.regiIdx].id.regi;
|
||||
range_to_check.advance_begin(1);
|
||||
auto all_valid_and_high_level_after_start = range_to_check | filtered(ICODE::select_valid_high_level);
|
||||
for (ICODE &i : all_valid_and_high_level_after_start)
|
||||
if ((i.du.def & duReg[regi]).any())
|
||||
return false;
|
||||
if (all_valid_and_high_level_after_start.end().base() != lastBBinst)
|
||||
case IDENTIFIER:
|
||||
if (expr.ident.idType == REGISTER)
|
||||
{
|
||||
regi= locId.id_arr[expr.ident.idNode.regiIdx].id.regi;
|
||||
range_to_check.advance_begin(1);
|
||||
auto all_valid_and_high_level_after_start = range_to_check | filtered(ICODE::select_valid_high_level);
|
||||
for (ICODE &i : all_valid_and_high_level_after_start)
|
||||
if ((i.du.def & duReg[regi]).any())
|
||||
return false;
|
||||
if (all_valid_and_high_level_after_start.end().base() != lastBBinst)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
/* else if (rhs->expr.ident.idType == LONG_VAR)
|
||||
/* else if (rhs->expr.ident.idType == LONG_VAR)
|
||||
{
|
||||
missing all other identifiers ****
|
||||
} */
|
||||
|
||||
case BOOLEAN_OP:
|
||||
if(0==rhs())
|
||||
return false;
|
||||
res = rhs()->xClear ( range_to_check, lastBBinst, locId);
|
||||
if (res == false)
|
||||
return false;
|
||||
if(0==lhs())
|
||||
return false;
|
||||
return lhs()->xClear ( range_to_check, lastBBinst, locId);
|
||||
case BOOLEAN_OP:
|
||||
if(0==rhs())
|
||||
return false;
|
||||
res = rhs()->xClear ( range_to_check, lastBBinst, locId);
|
||||
if (res == false)
|
||||
return false;
|
||||
if(0==lhs())
|
||||
return false;
|
||||
return lhs()->xClear ( range_to_check, lastBBinst, locId);
|
||||
|
||||
case NEGATION:
|
||||
case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
if(0==expr.unaryExp)
|
||||
return false;
|
||||
return expr.unaryExp->xClear ( range_to_check, lastBBinst, locId);
|
||||
default:
|
||||
fprintf(stderr,"COND_EXPR::xClear unhandled type %d\n",m_type);
|
||||
|
||||
case NEGATION:
|
||||
case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
if(0==expr.unaryExp)
|
||||
return false;
|
||||
return expr.unaryExp->xClear ( range_to_check, lastBBinst, locId);
|
||||
} /* eos */
|
||||
return false;
|
||||
}
|
||||
@ -677,7 +683,7 @@ bool BinaryOperator::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCA
|
||||
* whenever possible, and then places the actual argument on the procedure's
|
||||
* argument list. */
|
||||
/// @returns the type size of the stored Arg
|
||||
static int processCArg (Function * pp, Function * pProc, ICODE * picode, int numArgs)
|
||||
static int processCArg (Function * pp, Function * pProc, ICODE * picode, size_t numArgs)
|
||||
{
|
||||
COND_EXPR *_exp;
|
||||
bool res;
|
||||
@ -689,6 +695,7 @@ static int processCArg (Function * pp, Function * pProc, ICODE * picode, int num
|
||||
if (pp->flg & PROC_ISLIB) /* library function */
|
||||
{
|
||||
if (pp->args.numArgs > 0)
|
||||
{
|
||||
if (pp->flg & PROC_VARARG)
|
||||
{
|
||||
if (numArgs < pp->args.size())
|
||||
@ -696,6 +703,7 @@ static int processCArg (Function * pp, Function * pProc, ICODE * picode, int num
|
||||
}
|
||||
else
|
||||
adjustActArgType (_exp, pp->args[numArgs].type, pProc);
|
||||
}
|
||||
}
|
||||
else /* user function */
|
||||
{
|
||||
@ -765,6 +773,9 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
|
||||
picode->invalidate();
|
||||
numHlIcodes--;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unhandled LOCAL_ID::processTargetIcode opcode %d\n",t_hl.opcode);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -831,7 +842,7 @@ void Function::processHliCall(COND_EXPR *_exp, iICODE picode)
|
||||
}
|
||||
|
||||
|
||||
int BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
{
|
||||
bool res;
|
||||
|
||||
@ -907,12 +918,15 @@ int BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
}
|
||||
break;
|
||||
|
||||
/****case HLI_CALL: /* register arguments
|
||||
/****case HLI_CALL: // register arguments
|
||||
newRegArg (pProc, picode, ticode);
|
||||
picode->invalidate();
|
||||
numHlIcodes--;
|
||||
break; */
|
||||
} /* eos */
|
||||
default:
|
||||
fprintf(stderr,"unhandled BB::findBBExps target opcode %d\n",ticode->hl()->opcode);
|
||||
|
||||
} // eos
|
||||
break;
|
||||
|
||||
case HLI_CALL:
|
||||
@ -953,8 +967,12 @@ int BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
picode->setAsgn(lhs, _exp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unhandled BB::findBBExps HLI_CALL target opcode %d\n",ti_hl->opcode);
|
||||
} /* eos */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"BB::findBBExps Unhandled HLI %d\n",_icHl.opcode);
|
||||
} /* eos */
|
||||
}
|
||||
}
|
||||
@ -1009,6 +1027,8 @@ int BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
break;
|
||||
case HLI_CALL: /*** missing ***/
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"BB::findBBExps Unhandled target op %d\n",ticode->hl()->opcode);
|
||||
} /* eos */
|
||||
}
|
||||
break;
|
||||
@ -1052,7 +1072,13 @@ int BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
picode->setAsgn(lhs, _exp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"BB::findBBExps Unhandled target op %d\n",ticode->hl()->opcode);
|
||||
} /* eos */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"BB::findBBExps Unhandled HLI %d\n",_icHl.opcode);
|
||||
|
||||
} /* eos */
|
||||
}
|
||||
}
|
||||
@ -1115,7 +1141,7 @@ void Function::preprocessReturnDU(std::bitset<32> &_liveOut)
|
||||
{
|
||||
if (_liveOut.any())
|
||||
{
|
||||
int idx;
|
||||
// int idx;
|
||||
bool isAx, isBx, isCx, isDx;
|
||||
flg |= PROC_IS_FUNC;
|
||||
isAx = _liveOut.test(rAX - rAX);
|
||||
@ -1157,7 +1183,7 @@ void Function::preprocessReturnDU(std::bitset<32> &_liveOut)
|
||||
retVal.loc = REG_FRAME;
|
||||
retVal.id.longId.h = rDX;
|
||||
retVal.id.longId.l = rAX;
|
||||
idx = localId.newLongReg(TYPE_LONG_SIGN, rDX, rAX, Icode.begin()/*0*/);
|
||||
/*idx = */localId.newLongReg(TYPE_LONG_SIGN, rDX, rAX, Icode.begin()/*0*/);
|
||||
localId.propLongId (rAX, rDX, "\0");
|
||||
}
|
||||
else if (isAx || isBx || isCx || isDx) /* uint16_t */
|
||||
@ -1172,7 +1198,7 @@ void Function::preprocessReturnDU(std::bitset<32> &_liveOut)
|
||||
retVal.id.regi = rCX;
|
||||
else
|
||||
retVal.id.regi = rDX;
|
||||
idx = localId.newByteWordReg(TYPE_WORD_SIGN,retVal.id.regi);
|
||||
/*idx = */localId.newByteWordReg(TYPE_WORD_SIGN,retVal.id.regi);
|
||||
}
|
||||
else if(isAL||isBL||isCL||isDL)
|
||||
{
|
||||
@ -1186,7 +1212,7 @@ void Function::preprocessReturnDU(std::bitset<32> &_liveOut)
|
||||
retVal.id.regi = rCL;
|
||||
else
|
||||
retVal.id.regi = rDL;
|
||||
idx = localId.newByteWordReg(TYPE_BYTE_SIGN,retVal.id.regi);
|
||||
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,retVal.id.regi);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
17
src/dcc.cpp
17
src/dcc.cpp
@ -9,11 +9,11 @@
|
||||
#include <string.h>
|
||||
|
||||
/* Global variables - extern to other modules */
|
||||
char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
STATS stats; /* cfg statistics */
|
||||
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
extern SYMTAB symtab; /* Global symbol table */
|
||||
extern STATS stats; /* cfg statistics */
|
||||
//PROG prog; /* programs fields */
|
||||
OPTION option; /* Command line options */
|
||||
extern OPTION option; /* Command line options */
|
||||
//Function * pProcList; /* List of procedures, topologically sort */
|
||||
//Function * pLastProc; /* Pointer to last node in procedure list */
|
||||
//FunctionListType pProcList;
|
||||
@ -27,7 +27,6 @@ static void displayTotalStats(void);
|
||||
* main
|
||||
***************************************************************************/
|
||||
#include <iostream>
|
||||
extern Project g_proj;
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// llvm::MCOperand op=llvm::MCOperand::CreateImm(11);
|
||||
@ -56,9 +55,9 @@ int main(int argc, char *argv[])
|
||||
* analysis, data flow etc. and outputs it to output file ready for
|
||||
* re-compilation.
|
||||
*/
|
||||
BackEnd(option.filename, g_proj.callGraph);
|
||||
BackEnd(option.filename, Project::get()->callGraph);
|
||||
|
||||
g_proj.callGraph->write();
|
||||
Project::get()->callGraph->write();
|
||||
|
||||
if (option.Stats)
|
||||
displayTotalStats();
|
||||
@ -153,8 +152,8 @@ displayTotalStats ()
|
||||
/* Displays final statistics for the complete program */
|
||||
{
|
||||
printf ("\nFinal Program Statistics\n");
|
||||
printf (" Total number of low-level Icodes : %ld\n", stats.totalLL);
|
||||
printf (" Total number of high-level Icodes: %ld\n", stats.totalHL);
|
||||
printf (" Total number of low-level Icodes : %d\n", stats.totalLL);
|
||||
printf (" Total number of high-level Icodes: %d\n", stats.totalHL);
|
||||
printf (" Total reduction of instructions : %2.2f%%\n", 100.0 -
|
||||
(stats.totalHL * 100.0) / stats.totalLL);
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ struct POSSTACK_ENTRY
|
||||
Function * pProc; /* A pointer to a PROCEDURE structure */
|
||||
} ;
|
||||
static vector<POSSTACK_ENTRY> posStack; /* position stack */
|
||||
static uint8_t iPS; /* Index into the stack */
|
||||
//static uint8_t iPS; /* Index into the stack */
|
||||
|
||||
|
||||
// These are "curses equivalent" functions. (Used to use curses for all this,
|
||||
@ -552,7 +552,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
/****************************************************************************
|
||||
* formatRM
|
||||
***************************************************************************/
|
||||
static void formatRM(std::ostringstream &p, uint32_t flg, const LLOperand &pm)
|
||||
static void formatRM(std::ostringstream &p, uint32_t /*flg*/, const LLOperand &pm)
|
||||
{
|
||||
//char seg[4];
|
||||
|
||||
@ -627,14 +627,14 @@ static char *strHex(uint32_t d)
|
||||
static char buf[10];
|
||||
|
||||
d &= 0xFFFF;
|
||||
sprintf(buf, "0%lX%s", d, (d > 9)? "h": "");
|
||||
sprintf(buf, "0%X%s", d, (d > 9)? "h": "");
|
||||
return (buf + (buf[1] <= '9'));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* interactDis - interactive disassembler *
|
||||
****************************************************************************/
|
||||
void interactDis(Function * initProc, int initIC)
|
||||
void interactDis(Function * /*initProc*/, int /*initIC*/)
|
||||
{
|
||||
printf("Sorry - interactive disasassembler option not available for Unix\n");
|
||||
return;
|
||||
@ -643,7 +643,7 @@ void interactDis(Function * initProc, int initIC)
|
||||
/* Handle the floating point opcodes (icode iESC) */
|
||||
void LLInst::flops(std::ostringstream &out)
|
||||
{
|
||||
char bf[30];
|
||||
//char bf[30];
|
||||
uint8_t op = (uint8_t)src().getImm2();
|
||||
|
||||
/* Note that op is set to the escape number, e.g.
|
||||
|
||||
@ -3,14 +3,20 @@
|
||||
* Loads a program into simulated main memory and builds the procedure list.
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include "dcc.h"
|
||||
#include "disassem.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h> /* For malloc, free, realloc */
|
||||
#include "project.h"
|
||||
class Loader
|
||||
{
|
||||
bool loadIntoProject(IProject *);
|
||||
};
|
||||
|
||||
typedef struct { /* PSP structure */
|
||||
uint16_t int20h; /* interrupt 20h */
|
||||
uint16_t eof; /* segment, end of allocation block */
|
||||
@ -50,7 +56,7 @@ static struct { /* EXE file header */
|
||||
|
||||
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
|
||||
|
||||
static void LoadImage(char *filename);
|
||||
//static void LoadImage(char *filename);
|
||||
static void displayLoadInfo(void);
|
||||
static void displayMemMap(void);
|
||||
|
||||
@ -58,22 +64,20 @@ static void displayMemMap(void);
|
||||
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
|
||||
* rewritter, and displays any useful information.
|
||||
****************************************************************************/
|
||||
extern Project g_proj;
|
||||
bool DccFrontend::FrontEnd ()
|
||||
{
|
||||
|
||||
g_proj.callGraph = 0;
|
||||
g_proj.m_fname = m_fname;
|
||||
Project::get()->callGraph = 0;
|
||||
Project::get()->create(m_fname);
|
||||
|
||||
/* Load program into memory */
|
||||
LoadImage(g_proj);
|
||||
LoadImage(*Project::get());
|
||||
|
||||
if (option.verbose)
|
||||
displayLoadInfo();
|
||||
|
||||
/* Do depth first flow analysis building call graph and procedure list,
|
||||
* and attaching the I-code to each procedure */
|
||||
parse (g_proj);
|
||||
parse (*Project::get());
|
||||
|
||||
if (option.asm1)
|
||||
{
|
||||
@ -82,7 +86,7 @@ bool DccFrontend::FrontEnd ()
|
||||
|
||||
/* Search through code looking for impure references and flag them */
|
||||
Disassembler ds(1);
|
||||
for(Function &f : g_proj.pProcList)
|
||||
for(Function &f : Project::get()->pProcList)
|
||||
{
|
||||
f.markImpure();
|
||||
if (option.asm1)
|
||||
@ -92,11 +96,11 @@ bool DccFrontend::FrontEnd ()
|
||||
}
|
||||
if (option.Interact)
|
||||
{
|
||||
interactDis(&g_proj.pProcList.front(), 0); /* Interactive disassembler */
|
||||
interactDis(&Project::get()->pProcList.front(), 0); /* Interactive disassembler */
|
||||
}
|
||||
|
||||
/* Converts jump target addresses to icode offsets */
|
||||
for(Function &f : g_proj.pProcList)
|
||||
for(Function &f : Project::get()->pProcList)
|
||||
{
|
||||
f.bindIcodeOff();
|
||||
}
|
||||
@ -125,7 +129,7 @@ static void displayLoadInfo(void)
|
||||
printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
|
||||
printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
|
||||
}
|
||||
printf("Load image size = %04X\n", prog.cbImage - sizeof(PSP));
|
||||
printf("Load image size = %04" PRIiPTR "\n", prog.cbImage - sizeof(PSP));
|
||||
printf("Initial SS:SP = %04X:%04X\n", prog.initSS, prog.initSP);
|
||||
printf("Initial CS:IP = %04X:%04X\n", prog.initCS, prog.initIP);
|
||||
|
||||
@ -208,15 +212,15 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
uint8_t buf[4];
|
||||
|
||||
/* Open the input file */
|
||||
if ((fp = fopen(proj.m_fname.c_str(), "rb")) == NULL)
|
||||
if ((fp = fopen(proj.binary_path().c_str(), "rb")) == NULL)
|
||||
{
|
||||
fatalError(CANNOT_OPEN, proj.m_fname.c_str());
|
||||
fatalError(CANNOT_OPEN, proj.binary_path().c_str());
|
||||
}
|
||||
|
||||
/* Read in first 2 bytes to check EXE signature */
|
||||
if (fread(&header, 1, 2, fp) != 2)
|
||||
{
|
||||
fatalError(CANNOT_READ, proj.m_fname.c_str());
|
||||
fatalError(CANNOT_READ, proj.binary_path().c_str());
|
||||
}
|
||||
|
||||
if (! (prog.fCOM = (boolT)(header.sigLo != 0x4D || header.sigHi != 0x5A))) {
|
||||
@ -224,7 +228,7 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
if (fread(&header, sizeof(header), 1, fp) != 1)
|
||||
{
|
||||
fatalError(CANNOT_READ, proj.m_fname.c_str());
|
||||
fatalError(CANNOT_READ, proj.binary_path().c_str());
|
||||
}
|
||||
|
||||
/* This is a typical DOS kludge! */
|
||||
@ -305,7 +309,7 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
/* Read in the image past where a PSP would go */
|
||||
if (cb != (int)fread(prog.Image + sizeof(PSP), 1, (size_t)cb, fp))
|
||||
{
|
||||
fatalError(CANNOT_READ, proj.m_fname.c_str());
|
||||
fatalError(CANNOT_READ, proj.binary_path().c_str());
|
||||
}
|
||||
|
||||
/* Set up memory map */
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
#include "project.h"
|
||||
extern Project g_proj;
|
||||
//static BB * rmJMP(Function * pProc, int marker, BB * pBB);
|
||||
static void mergeFallThrough(Function * pProc, BB * pBB);
|
||||
static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last);
|
||||
//static void mergeFallThrough(Function * pProc, BB * pBB);
|
||||
//static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last);
|
||||
|
||||
/*****************************************************************************
|
||||
* createCFG - Create the basic control flow graph
|
||||
@ -30,7 +30,6 @@ void Function::createCFG()
|
||||
* 6) End of procedure
|
||||
*/
|
||||
int i;
|
||||
int ip;
|
||||
BB * psBB;
|
||||
BB * pBB;
|
||||
iICODE pIcode = Icode.begin();
|
||||
@ -85,7 +84,7 @@ CondJumps:
|
||||
{
|
||||
//pBB = BB::Create(start, ip, MULTI_BRANCH, ll->caseTbl.numEntries, this);
|
||||
pBB = BB::Create(iStart, pIcode, MULTI_BRANCH, ll->caseTbl2.size(), this);
|
||||
for (i = 0; i < ll->caseTbl2.size(); i++)
|
||||
for (size_t i = 0; i < ll->caseTbl2.size(); i++)
|
||||
pBB->edges[i].ip = ll->caseTbl2[i];
|
||||
hasCase = true;
|
||||
}
|
||||
@ -153,7 +152,7 @@ CondJumps:
|
||||
pBB = *iter;
|
||||
for (size_t edeg_idx = 0; edeg_idx < pBB->edges.size(); edeg_idx++)
|
||||
{
|
||||
uint32_t ip = pBB->edges[edeg_idx].ip;
|
||||
int32_t ip = pBB->edges[edeg_idx].ip;
|
||||
if (ip >= SYNTHESIZED_MIN)
|
||||
{
|
||||
fatalError (INVALID_SYNTHETIC_BB);
|
||||
@ -179,8 +178,8 @@ void Function::markImpure()
|
||||
continue;
|
||||
//assert that case tbl has less entries then symbol table ????
|
||||
//WARNING: Case entries are held in symbol table !
|
||||
assert(g_proj.validSymIdx(icod.ll()->caseEntry));
|
||||
const SYM &psym(g_proj.getSymByIdx(icod.ll()->caseEntry));
|
||||
assert(Project::get()->validSymIdx(icod.ll()->caseEntry));
|
||||
const SYM &psym(Project::get()->getSymByIdx(icod.ll()->caseEntry));
|
||||
for (int c = (int)psym.label; c < (int)psym.label+psym.size; c++)
|
||||
{
|
||||
if (BITMAP(c, BM_CODE))
|
||||
@ -335,8 +334,6 @@ BB *BB::rmJMP(int marker, BB * pBB)
|
||||
void BB::mergeFallThrough( CIcodeRec &Icode)
|
||||
{
|
||||
BB * pChild;
|
||||
int i;
|
||||
|
||||
if (!this)
|
||||
{
|
||||
printf("mergeFallThrough on empty BB!\n");
|
||||
@ -375,9 +372,11 @@ void BB::mergeFallThrough( CIcodeRec &Icode)
|
||||
traversed = DFS_MERGE;
|
||||
|
||||
/* Process all out edges recursively */
|
||||
for (i = 0; i < edges.size(); i++)
|
||||
if (edges[i].BBptr->traversed != DFS_MERGE)
|
||||
edges[i].BBptr->mergeFallThrough(Icode);
|
||||
for (size_t i = 0; i < edges.size(); i++)
|
||||
{
|
||||
if (edges[i].BBptr->traversed != DFS_MERGE)
|
||||
edges[i].BBptr->mergeFallThrough(Icode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -399,7 +398,7 @@ void BB::dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last)
|
||||
pChild->inEdges[pChild->index++] = this;
|
||||
|
||||
/* Is this the last visit? */
|
||||
if (pChild->index == pChild->inEdges.size())
|
||||
if (pChild->index == int(pChild->inEdges.size()))
|
||||
pChild->index = UN_INIT;
|
||||
|
||||
if (pChild->traversed != DFS_NUM)
|
||||
|
||||
@ -282,7 +282,7 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
|
||||
* refines the HIGH_LEVEL icodes. */
|
||||
void Function::highLevelGen()
|
||||
{
|
||||
int numIcode; /* number of icode instructions */
|
||||
size_t numIcode; /* number of icode instructions */
|
||||
iICODE pIcode; /* ptr to current icode node */
|
||||
COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */
|
||||
uint32_t _flg; /* icode flags */
|
||||
@ -473,6 +473,8 @@ COND_EXPR *COND_EXPR::inverse () const
|
||||
res->boolExpr.lhs=lhs()->inverse ();
|
||||
res->boolExpr.rhs=rhs()->inverse ();
|
||||
return res;
|
||||
default:
|
||||
fprintf(stderr,"COND_EXPR::inverse unhandled op %d",op());
|
||||
} /* eos */
|
||||
|
||||
}
|
||||
@ -488,8 +490,7 @@ COND_EXPR *COND_EXPR::inverse () const
|
||||
* actual parameters) */
|
||||
std::string writeCall (Function * tproc, STKFRAME & args, Function * pproc, int *numLoc)
|
||||
{
|
||||
int i; /* counter of # arguments */
|
||||
string condExp;
|
||||
//string condExp;
|
||||
ostringstream ostr;
|
||||
ostr<<tproc->name<<" (";
|
||||
for(const STKSYM &sym : args)
|
||||
@ -585,6 +586,10 @@ string HLTYPE::write1HlIcode (Function * pProc, int *numLoc)
|
||||
ostr << p->writeOut(pProc,numLoc);
|
||||
ostr << "\n";
|
||||
break;
|
||||
case HLI_JCOND: //Handled elsewhere
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr," HLTYPE::write1HlIcode - Unhandled opcode %d\n",opcode);
|
||||
}
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
26
src/hltype.cpp
Normal file
26
src/hltype.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "icode.h"
|
||||
#include "ast.h"
|
||||
|
||||
void HLTYPE::replaceExpr(COND_EXPR *e)
|
||||
{
|
||||
assert(e);
|
||||
delete exp.v;
|
||||
exp.v=e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HlTypeSupport *HLTYPE::get()
|
||||
{
|
||||
switch(opcode)
|
||||
{
|
||||
case HLI_ASSIGN: return &asgn;
|
||||
case HLI_RET:
|
||||
case HLI_POP:
|
||||
case HLI_JCOND:
|
||||
case HLI_PUSH: return &exp;
|
||||
case HLI_CALL: return &call;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -57,9 +57,9 @@ CIcodeRec::iterator CIcodeRec::labelSrch(uint32_t target)
|
||||
{
|
||||
return find_if(begin(),end(),[target](ICODE &l) -> bool {return l.ll()->label==target;});
|
||||
}
|
||||
ICODE * CIcodeRec::GetIcode(int ip)
|
||||
ICODE * CIcodeRec::GetIcode(size_t ip)
|
||||
{
|
||||
assert(ip>=0 && ip<size());
|
||||
assert(ip<size());
|
||||
iICODE res=begin();
|
||||
advance(res,ip);
|
||||
return &(*res);
|
||||
|
||||
@ -207,7 +207,9 @@ bool Idiom19::match(iICODE picode)
|
||||
return true;
|
||||
}
|
||||
else /* indexed */
|
||||
/* not supported yet */ ;
|
||||
{
|
||||
/* not supported yet */
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom19::action()
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include "dcc.h"
|
||||
|
||||
/*****************************************************************************
|
||||
/* checkStkVars - Checks for PUSH SI
|
||||
* checkStkVars - Checks for PUSH SI
|
||||
* [PUSH DI]
|
||||
* or PUSH DI
|
||||
* [PUSH SI]
|
||||
@ -115,7 +115,7 @@ bool Idiom1::match(iICODE picode)
|
||||
else // push di [push si] / push si [push di]
|
||||
{
|
||||
size_t n = checkStkVars (picode);
|
||||
for(int i=0; i<n; ++i)
|
||||
for(size_t i=0; i<n; ++i)
|
||||
m_icodes.push_back(picode++);
|
||||
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ using namespace std;
|
||||
****************************************************************************/
|
||||
bool Idiom11::match (iICODE picode)
|
||||
{
|
||||
const char *matchstring="(oNEG rH) (oNEG rL) (SBB \rH i0)";
|
||||
//const char *matchstring="(oNEG rH) (oNEG rL) (SBB \rH i0)";
|
||||
condId type; /* type of argument */
|
||||
if(distance(picode,m_end)<3)
|
||||
return false;
|
||||
@ -31,20 +31,22 @@ bool Idiom11::match (iICODE picode)
|
||||
return false;
|
||||
switch (type)
|
||||
{
|
||||
case GLOB_VAR:
|
||||
if ((m_icodes[2]->ll()->dst.segValue == m_icodes[0]->ll()->dst.segValue) &&
|
||||
(m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off))
|
||||
return true;
|
||||
break;
|
||||
case REGISTER:
|
||||
if (m_icodes[2]->ll()->dst.regi == m_icodes[0]->ll()->dst.regi)
|
||||
return true;
|
||||
break;
|
||||
case PARAM:
|
||||
case LOCAL_VAR:
|
||||
if (m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off)
|
||||
return true;
|
||||
break;
|
||||
case GLOB_VAR:
|
||||
if ((m_icodes[2]->ll()->dst.segValue == m_icodes[0]->ll()->dst.segValue) &&
|
||||
(m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off))
|
||||
return true;
|
||||
break;
|
||||
case REGISTER:
|
||||
if (m_icodes[2]->ll()->dst.regi == m_icodes[0]->ll()->dst.regi)
|
||||
return true;
|
||||
break;
|
||||
case PARAM:
|
||||
case LOCAL_VAR:
|
||||
if (m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Idiom11::match unhandled type %d\n",type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -73,7 +75,7 @@ int Idiom11::action()
|
||||
****************************************************************************/
|
||||
bool Idiom16::match (iICODE picode)
|
||||
{
|
||||
const char *matchstring="(oNEG rR) (oSBB rR rR) (oINC rR)";
|
||||
//const char *matchstring="(oNEG rR) (oSBB rR rR) (oINC rR)";
|
||||
if(distance(picode,m_end)<3)
|
||||
return false;
|
||||
for(int i=0; i<3; ++i)
|
||||
|
||||
@ -12,7 +12,7 @@ bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const
|
||||
{
|
||||
return (a->ll()->src().getReg2()==l) and (b->ll()->dst.getReg2()==h);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ID::ID() : type(TYPE_UNKNOWN),illegal(false),loc(STK_FRAME),hasMacro(false)
|
||||
{
|
||||
@ -72,7 +72,6 @@ int LOCAL_ID::newByteWordReg(hlType t, eReg regi)
|
||||
* flagging this entry as illegal is all that can be done. */
|
||||
void LOCAL_ID::flagByteWordId (int off)
|
||||
{
|
||||
int idx;
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off](ID &en)->bool {
|
||||
//if (((en.type == TYPE_WORD_SIGN) || (en.type == TYPE_BYTE_SIGN)) &&
|
||||
if ((en.typeBitsize()<=16) &&
|
||||
@ -121,12 +120,10 @@ int LOCAL_ID::newByteWordStk(hlType t, int off, uint8_t regOff)
|
||||
* regi: indexed register into global variable
|
||||
* ix: index into icode array
|
||||
* t: HIGH_LEVEL type */
|
||||
int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t)
|
||||
int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, hlType t)
|
||||
{
|
||||
int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
for (size_t idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.bwGlb.seg == seg) &&
|
||||
@ -137,11 +134,10 @@ int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t)
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, GLB_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.bwGlb.seg = seg;
|
||||
id_arr[idx].id.bwGlb.off = off;
|
||||
id_arr[idx].id.bwGlb.regi = regi;
|
||||
return (idx);
|
||||
id_arr.back().id.bwGlb.seg = seg;
|
||||
id_arr.back().id.bwGlb.off = off;
|
||||
id_arr.back().id.bwGlb.regi = regi;
|
||||
return id_arr.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
@ -279,7 +275,7 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
|
||||
{
|
||||
size_t idx;
|
||||
const LLOperand *pmH, *pmL;
|
||||
LLInst &p_ll(*pIcode->ll());
|
||||
LLInst &p_ll(*pIcode->ll());
|
||||
if (f == LOW_FIRST)
|
||||
{
|
||||
pmL = p_ll.get(sd);
|
||||
|
||||
147
src/parser.cpp
147
src/parser.cpp
@ -2,7 +2,8 @@
|
||||
* dcc project procedure list builder
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann
|
||||
****************************************************************************/
|
||||
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h> /* For exit() */
|
||||
#include <sstream>
|
||||
@ -12,9 +13,8 @@
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
using namespace std;
|
||||
extern Project g_proj;
|
||||
|
||||
//static void FollowCtrl (Function * pProc, CALL_GRAPH * pcallGraph, STATE * pstate);
|
||||
static boolT process_JMP (ICODE * pIcode, STATE * pstate, CALL_GRAPH * pcallGraph);
|
||||
static void setBits(int16_t type, uint32_t start, uint32_t len);
|
||||
static void process_MOV(LLInst &ll, STATE * pstate);
|
||||
static SYM * lookupAddr (LLOperand *pm, STATE * pstate, int size, uint16_t duFlag);
|
||||
@ -38,7 +38,7 @@ void DccFrontend::parse(Project &proj)
|
||||
SynthLab = SYNTHESIZED_MIN;
|
||||
|
||||
// default-construct a Function object !
|
||||
auto func = proj.createFunction();
|
||||
/*auto func = */proj.createFunction();
|
||||
|
||||
/* Check for special settings of initial state, based on idioms of the
|
||||
startup code */
|
||||
@ -102,7 +102,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
||||
uint32_t offset;
|
||||
eErrorId err;
|
||||
bool done = false;
|
||||
SYMTAB &global_symbol_table(g_proj.symtab);
|
||||
SYMTAB &global_symbol_table(Project::get()->symtab);
|
||||
if (name.find("chkstk") != string::npos)
|
||||
{
|
||||
// Danger! Dcc will likely fall over in this code.
|
||||
@ -115,7 +115,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
||||
}
|
||||
if (option.VeryVerbose)
|
||||
{
|
||||
printf("Parsing proc %s at %lX\n", name.c_str(), pstate->IP);
|
||||
printf("Parsing proc %s at %X\n", name.c_str(), pstate->IP);
|
||||
}
|
||||
|
||||
while (! done && ! (err = scan(pstate->IP, _Icode)))
|
||||
@ -337,10 +337,12 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
||||
|
||||
case iSHL:
|
||||
if (pstate->JCond.regi == ll->dst.regi)
|
||||
{
|
||||
if ((ll->testFlags(I)) && ll->src().getImm2() == 1)
|
||||
pstate->JCond.immed *= 2;
|
||||
else
|
||||
pstate->JCond.regi = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case iLEA:
|
||||
@ -404,7 +406,7 @@ bool Function::followAllTableEntries(JumpTable &table, uint32_t cs, ICODE& pIcod
|
||||
pIcode.ll()->caseTbl2.resize( table.size() );
|
||||
assert(pIcode.ll()->caseTbl2.size()<512);
|
||||
uint32_t k=0;
|
||||
for (int i = table.start; i < table.finish; i += 2)
|
||||
for (size_t i = table.start; i < table.finish; i += 2)
|
||||
{
|
||||
StCopy = *pstate;
|
||||
StCopy.IP = cs + LH(&prog.Image[i]);
|
||||
@ -417,6 +419,7 @@ bool Function::followAllTableEntries(JumpTable &table, uint32_t cs, ICODE& pIcod
|
||||
last_current_insn->ll()->setFlags(CASE);
|
||||
pIcode.ll()->caseTbl2.push_back( last_current_insn->ll()->GetLlLabel() );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGraph)
|
||||
@ -426,14 +429,14 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
||||
ICODE _Icode;
|
||||
uint32_t cs, offTable, endTable;
|
||||
uint32_t i, k, seg, target;
|
||||
uint32_t tmp;
|
||||
|
||||
if (pIcode.ll()->testFlags(I))
|
||||
{
|
||||
if (pIcode.ll()->getOpcode() == iJMPF)
|
||||
pstate->setState( rCS, LH(prog.Image + pIcode.ll()->label + 3));
|
||||
uint32_t i = pstate->IP = pIcode.ll()->src().getImm2();
|
||||
if ((long)i < 0)
|
||||
pstate->IP = pIcode.ll()->src().getImm2();
|
||||
int64_t i = pIcode.ll()->src().getImm2();
|
||||
if (i < 0)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
@ -501,8 +504,8 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
||||
{
|
||||
assert(((endTable - offTable) / 2)<512);
|
||||
STATE StCopy;
|
||||
int ip;
|
||||
uint32_t *psw;
|
||||
//int ip;
|
||||
//uint32_t *psw;
|
||||
|
||||
setBits(BM_DATA, offTable, endTable - offTable);
|
||||
|
||||
@ -514,7 +517,7 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
||||
StCopy = *pstate;
|
||||
StCopy.IP = cs + LH(&prog.Image[i]);
|
||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
||||
ip = Icode.size();
|
||||
//ip = Icode.size();
|
||||
|
||||
FollowCtrl (pcallGraph, &StCopy);
|
||||
++last_current_insn;
|
||||
@ -600,9 +603,9 @@ boolT Function::process_CALL (ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *ps
|
||||
* previous offset into the program image */
|
||||
uint32_t tgtAddr=0;
|
||||
if (pIcode.ll()->getOpcode() == iCALLF)
|
||||
tgtAddr= LH(&prog.Image[off]) + (uint32_t)(LH(&prog.Image[off+2])) << 4;
|
||||
tgtAddr= LH(&prog.Image[off]) + ((uint32_t)(LH(&prog.Image[off+2])) << 4);
|
||||
else
|
||||
tgtAddr= LH(&prog.Image[off]) + (uint32_t)(uint16_t)state.r[rCS] << 4;
|
||||
tgtAddr= LH(&prog.Image[off]) + ((uint32_t)(uint16_t)state.r[rCS] << 4);
|
||||
pIcode.ll()->replaceSrc(LLOperand::CreateImm2( tgtAddr ) );
|
||||
pIcode.ll()->setFlags(I);
|
||||
indirect = true;
|
||||
@ -612,12 +615,12 @@ boolT Function::process_CALL (ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *ps
|
||||
if (pIcode.ll()->testFlags(I))
|
||||
{
|
||||
/* Search procedure list for one with appropriate entry point */
|
||||
ilFunction iter = g_proj.findByEntry(pIcode.ll()->src().getImm2());
|
||||
ilFunction iter = Project::get()->findByEntry(pIcode.ll()->src().getImm2());
|
||||
|
||||
/* Create a new procedure node and save copy of the state */
|
||||
if ( not g_proj.valid(iter) )
|
||||
if ( not Project::get()->valid(iter) )
|
||||
{
|
||||
iter = g_proj.createFunction();
|
||||
iter = Project::get()->createFunction();
|
||||
Function &x(*iter);
|
||||
x.procEntry = pIcode.ll()->src().getImm2();
|
||||
LibCheck(x);
|
||||
@ -665,7 +668,7 @@ boolT Function::process_CALL (ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *ps
|
||||
|
||||
}
|
||||
else
|
||||
g_proj.callGraph->insertCallGraph (this, iter);
|
||||
Project::get()->callGraph->insertCallGraph (this, iter);
|
||||
|
||||
last_insn.ll()->src().proc.proc = &(*iter); // ^ target proc
|
||||
|
||||
@ -707,6 +710,7 @@ static void process_MOV(LLInst & ll, STATE * pstate)
|
||||
size=1;
|
||||
psym = lookupAddr (&ll.dst, pstate, size, eDEF);
|
||||
if (psym && ! (psym->duVal.val)) /* no initial value yet */
|
||||
{
|
||||
if (ll.testFlags(I)) /* immediate */
|
||||
{
|
||||
prog.Image[psym->label] = (uint8_t)ll.src().getImm2();
|
||||
@ -733,6 +737,7 @@ static void process_MOV(LLInst & ll, STATE * pstate)
|
||||
prog.Image[psym->label+1] = (uint8_t)(pstate->r[srcReg] >> 8);
|
||||
psym->duVal.setFlags(eDuVal::DEF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -742,8 +747,6 @@ static void process_MOV(LLInst & ll, STATE * pstate)
|
||||
* and returns a pointer to such entry. */
|
||||
void STKFRAME::updateFrameOff ( int16_t off, int _size, uint16_t duFlag)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Check for symbol in stack frame table */
|
||||
auto iter=findByLabel(off);
|
||||
if(iter!=end())
|
||||
@ -751,14 +754,14 @@ void STKFRAME::updateFrameOff ( int16_t off, int _size, uint16_t duFlag)
|
||||
if (iter->size < _size)
|
||||
{
|
||||
iter->size = _size;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char nm[16];
|
||||
STKSYM new_sym;
|
||||
|
||||
sprintf (nm, "arg%ld", size());
|
||||
sprintf (nm, "arg%" PRIu64, uint64_t(size()));
|
||||
new_sym.name = nm;
|
||||
new_sym.label= off;
|
||||
new_sym.size = _size;
|
||||
@ -800,13 +803,13 @@ static SYM * lookupAddr (LLOperand *pm, STATE *pstate, int size, uint16_t duFlag
|
||||
if (pm->segValue) /* there is a value in the seg field */
|
||||
{
|
||||
operand = opAdr (pm->segValue, pm->off);
|
||||
psym = g_proj.symtab.updateGlobSym (operand, size, duFlag,created_new);
|
||||
psym = Project::get()->symtab.updateGlobSym (operand, size, duFlag,created_new);
|
||||
}
|
||||
else if (pstate->f[pm->seg]) /* new value */
|
||||
{
|
||||
pm->segValue = pstate->r[pm->seg];
|
||||
operand = opAdr(pm->segValue, pm->off);
|
||||
psym = g_proj.symtab.updateGlobSym (operand, size, duFlag,created_new);
|
||||
psym = Project::get()->symtab.updateGlobSym (operand, size, duFlag,created_new);
|
||||
|
||||
/* Flag new memory locations that are segment values */
|
||||
if (created_new)
|
||||
@ -821,7 +824,7 @@ static SYM * lookupAddr (LLOperand *pm, STATE *pstate, int size, uint16_t duFlag
|
||||
}
|
||||
}
|
||||
/* Check for out of bounds */
|
||||
if (psym && (psym->label>=0) and (psym->label < (uint32_t)prog.cbImage))
|
||||
if (psym and (psym->label < (uint32_t)prog.cbImage))
|
||||
return psym;
|
||||
return nullptr;
|
||||
}
|
||||
@ -903,7 +906,7 @@ std::bitset<32> duReg[] = { 0x00,
|
||||
* pstate: ptr to current procedure state
|
||||
* size : size of the operand
|
||||
* ix : current index into icode array */
|
||||
static void use (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int size, int ix)
|
||||
static void use (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int size)
|
||||
{
|
||||
const LLOperand * pm = pIcode.ll()->get(d) ;
|
||||
SYM * psym;
|
||||
@ -927,17 +930,21 @@ static void use (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int
|
||||
if ((pm->seg == rDS) && (pm->regi == INDEX_BX)) /* bx */
|
||||
{
|
||||
if (pm->off > 0) /* global indexed variable */
|
||||
pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,ix, TYPE_WORD_SIGN);
|
||||
pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,TYPE_WORD_SIGN);
|
||||
}
|
||||
pIcode.du.use |= duReg[pm->regi];
|
||||
}
|
||||
|
||||
else if (psym = lookupAddr(const_cast<LLOperand *>(pm), pstate, size, eDuVal::USE))
|
||||
else
|
||||
{
|
||||
setBits (BM_DATA, psym->label, (uint32_t)size);
|
||||
pIcode.ll()->setFlags(SYM_USE);
|
||||
pIcode.ll()->caseEntry = distance(&g_proj.symtab[0],psym); //WARNING: was setting case count
|
||||
psym = lookupAddr(const_cast<LLOperand *>(pm), pstate, size, eDuVal::USE);
|
||||
if( nullptr != psym )
|
||||
{
|
||||
setBits (BM_DATA, psym->label, (uint32_t)size);
|
||||
pIcode.ll()->setFlags(SYM_USE);
|
||||
pIcode.ll()->caseEntry = distance(&Project::get()->symtab[0],psym); //WARNING: was setting case count
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -950,13 +957,21 @@ static void use (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int
|
||||
/* Checks which registers were defined (ie. got a new value) and updates the
|
||||
* du.d flag.
|
||||
* Places local variables in the local symbol table. */
|
||||
static void def (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int size,
|
||||
int ix)
|
||||
static void def (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int size)
|
||||
{
|
||||
LLOperand *pm = pIcode.ll()->get(d);
|
||||
SYM * psym;
|
||||
|
||||
if (pm->regi == 0 || pm->regi >= INDEX_BX_SI)
|
||||
if (pm->regi==0)
|
||||
{
|
||||
SYM * psym;
|
||||
psym = lookupAddr(pm, pstate, size, eDEF);
|
||||
if (nullptr!=psym)
|
||||
{
|
||||
setBits(BM_DATA, psym->label, (uint32_t)size);
|
||||
pIcode.ll()->setFlags(SYM_DEF);
|
||||
pIcode.ll()->caseEntry = distance(&Project::get()->symtab[0],psym); // WARNING: was setting Case count
|
||||
}
|
||||
}
|
||||
else if (pm->regi >= INDEX_BX_SI)
|
||||
{
|
||||
if (pm->regi == INDEX_BP) /* indexed on bp */
|
||||
{
|
||||
@ -977,19 +992,11 @@ static void def (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int
|
||||
if ((pm->seg == rDS) && (pm->regi == INDEX_BX)) /* bx */
|
||||
{
|
||||
if (pm->off > 0) /* global var */
|
||||
pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,ix, TYPE_WORD_SIGN);
|
||||
pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,TYPE_WORD_SIGN);
|
||||
}
|
||||
pIcode.du.use |= duReg[pm->regi];
|
||||
}
|
||||
|
||||
else if (psym = lookupAddr(pm, pstate, size, eDEF))
|
||||
{
|
||||
setBits(BM_DATA, psym->label, (uint32_t)size);
|
||||
pIcode.ll()->setFlags(SYM_DEF);
|
||||
pIcode.ll()->caseEntry = distance(&g_proj.symtab[0],psym); // WARNING: was setting Case count
|
||||
}
|
||||
}
|
||||
|
||||
/* Definition of register */
|
||||
else if ((d == DST) || ((d == SRC) && (not pIcode.ll()->testFlags(I))))
|
||||
{
|
||||
@ -1002,12 +1009,11 @@ static void def (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int
|
||||
/* use_def - operand is both use and def'd.
|
||||
* Note: the destination will always be a register, stack variable, or global
|
||||
* variable. */
|
||||
static void use_def(opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int cb,
|
||||
int ix)
|
||||
static void use_def(opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int cb)
|
||||
{
|
||||
const LLOperand * pm = pIcode.ll()->get(d);
|
||||
|
||||
use (d, pIcode, pProc, pstate, cb, ix);
|
||||
use (d, pIcode, pProc, pstate, cb);
|
||||
|
||||
if (pm->regi < INDEX_BX_SI) /* register */
|
||||
{
|
||||
@ -1022,7 +1028,6 @@ static void use_def(opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, i
|
||||
extern LLOperand convertOperand(const x86_op_t &from);
|
||||
void Function::process_operands(ICODE & pIcode, STATE * pstate)
|
||||
{
|
||||
int ix=Icode.size();
|
||||
LLInst &ll_ins(*pIcode.ll());
|
||||
|
||||
int sseg = (ll_ins.src().seg)? ll_ins.src().seg: rDS;
|
||||
@ -1036,39 +1041,39 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
|
||||
case iRCL: case iRCR: case iROL: case iROR:
|
||||
case iADD: case iADC: case iSUB: case iSBB:
|
||||
if (! Imm) {
|
||||
use(SRC, pIcode, this, pstate, cb, ix);
|
||||
use(SRC, pIcode, this, pstate, cb);
|
||||
}
|
||||
case iINC: case iDEC: case iNEG: case iNOT:
|
||||
case iAAA: case iAAD: case iAAM: case iAAS:
|
||||
case iDAA: case iDAS:
|
||||
use_def(DST, pIcode, this, pstate, cb, ix);
|
||||
use_def(DST, pIcode, this, pstate, cb);
|
||||
break;
|
||||
|
||||
case iXCHG:
|
||||
/* This instruction is replaced by 3 instructions, only need
|
||||
* to define the src operand and use the destination operand
|
||||
* in the mean time. */
|
||||
use(SRC, pIcode, this, pstate, cb, ix);
|
||||
def(DST, pIcode, this, pstate, cb, ix);
|
||||
use(SRC, pIcode, this, pstate, cb);
|
||||
def(DST, pIcode, this, pstate, cb);
|
||||
break;
|
||||
|
||||
case iTEST: case iCMP:
|
||||
if (! Imm)
|
||||
use(SRC, pIcode, this, pstate, cb, ix);
|
||||
use(DST, pIcode, this, pstate, cb, ix);
|
||||
use(SRC, pIcode, this, pstate, cb);
|
||||
use(DST, pIcode, this, pstate, cb);
|
||||
break;
|
||||
|
||||
case iDIV: case iIDIV:
|
||||
use(SRC, pIcode, this, pstate, cb, ix);
|
||||
use(SRC, pIcode, this, pstate, cb);
|
||||
if (cb == 1)
|
||||
pIcode.du.use |= duReg[rTMP];
|
||||
break;
|
||||
|
||||
case iMUL: case iIMUL:
|
||||
use(SRC, pIcode, this, pstate, cb, ix);
|
||||
use(SRC, pIcode, this, pstate, cb);
|
||||
if (! Imm)
|
||||
{
|
||||
use (DST, pIcode, this, pstate, cb, ix);
|
||||
use (DST, pIcode, this, pstate, cb);
|
||||
if (cb == 1)
|
||||
{
|
||||
pIcode.du.def |= duReg[rAX];
|
||||
@ -1081,7 +1086,7 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
|
||||
}
|
||||
}
|
||||
else
|
||||
def (DST, pIcode, this, pstate, cb, ix);
|
||||
def (DST, pIcode, this, pstate, cb);
|
||||
break;
|
||||
|
||||
case iSIGNEX:
|
||||
@ -1105,14 +1110,14 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
|
||||
case iCALL: case iPUSH: case iPOP:
|
||||
if (! Imm) {
|
||||
if (pIcode.ll()->getOpcode() == iPOP)
|
||||
def(DST, pIcode, this, pstate, cb, ix);
|
||||
def(DST, pIcode, this, pstate, cb);
|
||||
else
|
||||
use(DST, pIcode, this, pstate, cb, ix);
|
||||
use(DST, pIcode, this, pstate, cb);
|
||||
}
|
||||
break;
|
||||
|
||||
case iESC: /* operands may be larger */
|
||||
use(DST, pIcode, this, pstate, cb, ix);
|
||||
use(DST, pIcode, this, pstate, cb);
|
||||
break;
|
||||
|
||||
case iLDS: case iLES:
|
||||
@ -1120,25 +1125,25 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
|
||||
pIcode.du1.numRegsDef++;
|
||||
cb = 4;
|
||||
case iMOV:
|
||||
use(SRC, pIcode, this, pstate, cb, ix);
|
||||
def(DST, pIcode, this, pstate, cb, ix);
|
||||
use(SRC, pIcode, this, pstate, cb);
|
||||
def(DST, pIcode, this, pstate, cb);
|
||||
break;
|
||||
|
||||
case iLEA:
|
||||
use(SRC, pIcode, this, pstate, 2, ix);
|
||||
def(DST, pIcode, this, pstate, 2, ix);
|
||||
use(SRC, pIcode, this, pstate, 2);
|
||||
def(DST, pIcode, this, pstate, 2);
|
||||
break;
|
||||
|
||||
case iBOUND:
|
||||
use(SRC, pIcode, this, pstate, 4, ix);
|
||||
use(DST, pIcode, this, pstate, cb, ix);
|
||||
use(SRC, pIcode, this, pstate, 4);
|
||||
use(DST, pIcode, this, pstate, cb);
|
||||
break;
|
||||
|
||||
case iJMPF:
|
||||
cb = 4;
|
||||
case iJMP:
|
||||
if (! Imm)
|
||||
use(SRC, pIcode, this, pstate, cb, ix);
|
||||
use(SRC, pIcode, this, pstate, cb);
|
||||
break;
|
||||
|
||||
case iLOOP: case iLOOPE: case iLOOPNE:
|
||||
@ -1194,7 +1199,7 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
|
||||
break;
|
||||
|
||||
case iIN: case iOUT:
|
||||
def(DST, pIcode, this, pstate, cb, ix);
|
||||
def(DST, pIcode, this, pstate, cb);
|
||||
if (! Imm)
|
||||
{
|
||||
pIcode.du.use |= duReg[rDX];
|
||||
|
||||
@ -14,14 +14,14 @@
|
||||
static uint16_t *T1, *T2; /* Pointers to T1[i], T2[i] */
|
||||
static short *g; /* g[] */
|
||||
|
||||
static int numEdges; /* An edge counter */
|
||||
//static int numEdges; /* An edge counter */
|
||||
//static bool *visited; /* Array of bools: whether visited */
|
||||
|
||||
/* Private prototypes */
|
||||
static void initGraph(void);
|
||||
static void addToGraph(int e, int v1, int v2);
|
||||
static bool isCycle(void);
|
||||
static void duplicateKeys(int v1, int v2);
|
||||
//static void initGraph(void);
|
||||
//static void addToGraph(int e, int v1, int v2);
|
||||
//static bool isCycle(void);
|
||||
//static void duplicateKeys(int v1, int v2);
|
||||
PatternHasher g_pattern_hasher;
|
||||
|
||||
void
|
||||
|
||||
@ -43,8 +43,6 @@ void CALL_GRAPH::insertArc (ilFunction newProc)
|
||||
/* Inserts a (caller, callee) arc in the call graph tree. */
|
||||
bool CALL_GRAPH::insertCallGraph(ilFunction caller, ilFunction callee)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (proc == caller)
|
||||
{
|
||||
insertArc (callee);
|
||||
@ -52,8 +50,8 @@ bool CALL_GRAPH::insertCallGraph(ilFunction caller, ilFunction callee)
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < outEdges.size(); i++)
|
||||
if (outEdges[i]->insertCallGraph (caller, callee))
|
||||
for (CALL_GRAPH *edg : outEdges)
|
||||
if (edg->insertCallGraph (caller, callee))
|
||||
return true;
|
||||
return (false);
|
||||
}
|
||||
@ -61,7 +59,7 @@ bool CALL_GRAPH::insertCallGraph(ilFunction caller, ilFunction callee)
|
||||
|
||||
bool CALL_GRAPH::insertCallGraph(Function *caller, ilFunction callee)
|
||||
{
|
||||
return insertCallGraph(g_proj.funcIter(caller),callee);
|
||||
return insertCallGraph(Project::get()->funcIter(caller),callee);
|
||||
}
|
||||
|
||||
|
||||
@ -69,11 +67,9 @@ bool CALL_GRAPH::insertCallGraph(Function *caller, ilFunction callee)
|
||||
* the nodes the procedure invokes. */
|
||||
void CALL_GRAPH::writeNodeCallGraph(int indIdx)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf ("%s%s\n", indentStr(indIdx), proc->name.c_str());
|
||||
for (i = 0; i < outEdges.size(); i++)
|
||||
outEdges[i]->writeNodeCallGraph (indIdx + 1);
|
||||
for (CALL_GRAPH *cg : outEdges)
|
||||
cg->writeNodeCallGraph (indIdx + 1);
|
||||
}
|
||||
|
||||
|
||||
@ -205,6 +201,8 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
|
||||
picode->du.def &= maskDuReg[id->id.longId.l];
|
||||
newsym.type = TYPE_LONG_SIGN;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"LOCAL_ID::newRegArg unhandled type %d in masking low\n",type);
|
||||
}
|
||||
call_args_stackframe->push_back(newsym);
|
||||
call_args_stackframe->numArgs++;
|
||||
@ -228,10 +226,12 @@ bool CallType::newStkArg(COND_EXPR *exp, llIcode opcode, Function * pproc)
|
||||
{
|
||||
regi = pproc->localId.id_arr[exp->expr.ident.idNode.regiIdx].id.regi;
|
||||
if ((regi >= rES) && (regi <= rDS))
|
||||
{
|
||||
if (opcode == iCALLF)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,8 +308,12 @@ void adjustActArgType (COND_EXPR *exp, hlType forType, Function * pproc)
|
||||
case TYPE_WORD_SIGN:
|
||||
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"adjustForArgType unhandled actType_ %d \n",actType);
|
||||
} /* eos */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"adjustForArgType unhandled forType %d \n",forType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,11 +321,11 @@ void adjustActArgType (COND_EXPR *exp, hlType forType, Function * pproc)
|
||||
/* Determines whether the formal argument has the same type as the given
|
||||
* type (type of the actual argument). If not, the formal argument is
|
||||
* changed its type */
|
||||
void STKFRAME::adjustForArgType(int numArg_, hlType actType_)
|
||||
void STKFRAME::adjustForArgType(size_t numArg_, hlType actType_)
|
||||
{
|
||||
hlType forType;
|
||||
STKSYM * psym, * nsym;
|
||||
int off, i;
|
||||
int off;
|
||||
/* If formal argument does not exist, do not create new ones, just
|
||||
* ignore actual argument
|
||||
*/
|
||||
@ -330,7 +334,7 @@ void STKFRAME::adjustForArgType(int numArg_, hlType actType_)
|
||||
|
||||
/* Find stack offset for this argument */
|
||||
off = m_minOff;
|
||||
i=0;
|
||||
size_t i=0;
|
||||
for(STKSYM &s : *this) // walk formal arguments upto numArg_
|
||||
{
|
||||
if(i>=numArg_)
|
||||
@ -343,7 +347,7 @@ void STKFRAME::adjustForArgType(int numArg_, hlType actType_)
|
||||
//psym = &at(numArg_);
|
||||
//i = numArg_;
|
||||
//auto iter=std::find_if(sym.begin(),sym.end(),[off](STKSYM &s)->bool {s.off==off;});
|
||||
auto iter=std::find_if(begin()+numArg_,end(),[off](STKSYM &s)->bool {s.label==off;});
|
||||
auto iter=std::find_if(begin()+numArg_,end(),[off](STKSYM &s)->bool {return s.label==off;});
|
||||
if(iter==end()) // symbol not found
|
||||
return;
|
||||
psym = &(*iter);
|
||||
@ -380,6 +384,8 @@ void STKFRAME::adjustForArgType(int numArg_, hlType actType_)
|
||||
case TYPE_CONST:
|
||||
case TYPE_STR:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"STKFRAME::adjustForArgType unhandled actType_ %d \n",actType_);
|
||||
} /* eos */
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,38 @@
|
||||
#include <utility>
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
#include "Procedure.h"
|
||||
Project g_proj;
|
||||
using namespace std;
|
||||
//Project g_proj;
|
||||
char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
STATS stats; /* cfg statistics */
|
||||
//PROG prog; /* programs fields */
|
||||
OPTION option; /* Command line options */
|
||||
Project *Project::s_instance = 0;
|
||||
Project::Project() : callGraph(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
void Project::initialize()
|
||||
{
|
||||
delete callGraph;
|
||||
callGraph = nullptr;
|
||||
}
|
||||
void Project::create(const string &a)
|
||||
{
|
||||
m_fname=a;
|
||||
string::size_type ext_loc=a.find_last_of('.');
|
||||
string::size_type slash_loc=a.find_last_of('/',ext_loc);
|
||||
if(slash_loc==string::npos)
|
||||
slash_loc=0;
|
||||
else
|
||||
slash_loc++;
|
||||
if(ext_loc!=string::npos)
|
||||
m_project_name = a.substr(slash_loc,(ext_loc-slash_loc));
|
||||
else
|
||||
m_project_name = a.substr(slash_loc);
|
||||
}
|
||||
bool Project::valid(ilFunction iter)
|
||||
{
|
||||
return iter!=pProcList.end();
|
||||
@ -63,7 +94,10 @@ const std::string &Project::symbolName(size_t idx)
|
||||
}
|
||||
Project *Project::get()
|
||||
{
|
||||
return &g_proj;
|
||||
//WARNING: poor man's singleton, not thread safe
|
||||
if(s_instance==0)
|
||||
s_instance=new Project;
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
|
||||
@ -71,3 +105,4 @@ SourceMachine *Project::machine()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@ -236,7 +236,7 @@ void Function::propLongStk (int i, const ID &pLocId)
|
||||
iICODE l23;
|
||||
/* Check all icodes for offHi:offLo */
|
||||
pEnd = Icode.end();
|
||||
int stat_size=Icode.size();
|
||||
size_t stat_size=Icode.size();
|
||||
// for (idx = 0; idx < (Icode.size() - 1); idx++)
|
||||
for(auto pIcode = Icode.begin(); ;++pIcode)
|
||||
{
|
||||
@ -459,7 +459,7 @@ int Function::findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE be
|
||||
{
|
||||
if (checkLongRegEq (pLocId.id.longId, pIcode, loc_ident_idx, this, asgn, *long_loc->ll()))
|
||||
{
|
||||
// reduce the advance by 1 here (loop increases) ?
|
||||
// reduce the advance by 1 here (loop increases) ?
|
||||
advance(pIcode,longJCond23 (asgn, pIcode, arc, long_loc));
|
||||
}
|
||||
}
|
||||
@ -476,9 +476,9 @@ int Function::findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE be
|
||||
}
|
||||
|
||||
/* Check for OR regH, regL
|
||||
* JX lab
|
||||
* => HLI_JCOND (regH:regL X 0) lab
|
||||
* This is better code than HLI_JCOND (HI(regH:regL) | LO(regH:regL)) */
|
||||
* JX lab
|
||||
* => HLI_JCOND (regH:regL X 0) lab
|
||||
* This is better code than HLI_JCOND (HI(regH:regL) | LO(regH:regL)) */
|
||||
else if (pIcode->ll()->match(iOR) && (next1 != pEnd) && (isJCond ((llIcode)next1->ll()->getOpcode())))
|
||||
{
|
||||
if (pLocId.id.longId.srcDstRegMatch(pIcode,pIcode))
|
||||
@ -492,6 +492,7 @@ int Function::findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE be
|
||||
}
|
||||
}
|
||||
} /* end for */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Finds the definition of the long register pointed to by pLocId, and
|
||||
@ -504,8 +505,8 @@ void Function::propLongReg (int loc_ident_idx, const ID &pLocId)
|
||||
{
|
||||
/* Process all definitions/uses of long registers at an icode position */
|
||||
// WARNING: this loop modifies the iterated-over container.
|
||||
size_t initial_size=pLocId.idx.size();
|
||||
for (int j = 0; j < pLocId.idx.size(); j++)
|
||||
//size_t initial_size=pLocId.idx.size();
|
||||
for (size_t j = 0; j < pLocId.idx.size(); j++)
|
||||
{
|
||||
auto idx_iter=pLocId.idx.begin();
|
||||
std::advance(idx_iter,j);
|
||||
@ -524,7 +525,7 @@ void Function::propLongReg (int loc_ident_idx, const ID &pLocId)
|
||||
|
||||
/* Propagates the long global address across all LOW_LEVEL icodes.
|
||||
* Transforms some LOW_LEVEL icodes into HIGH_LEVEL */
|
||||
void Function::propLongGlb (int i, const ID &pLocId)
|
||||
void Function::propLongGlb (int /*i*/, const ID &/*pLocId*/)
|
||||
{
|
||||
printf("WARN: Function::propLongGlb not implemented");
|
||||
}
|
||||
@ -534,10 +535,9 @@ void Function::propLongGlb (int i, const ID &pLocId)
|
||||
* into HIGH_LEVEL icodes. */
|
||||
void Function::propLong()
|
||||
{
|
||||
int i;
|
||||
/* Pointer to current local identifier */
|
||||
|
||||
for (i = 0; i < localId.csym(); i++)
|
||||
//TODO: change into range based for
|
||||
for (size_t i = 0; i < localId.csym(); i++)
|
||||
{
|
||||
const ID &pLocId(localId.id_arr[i]);
|
||||
if ((pLocId.type==TYPE_LONG_SIGN) || (pLocId.type==TYPE_LONG_UNSIGN))
|
||||
|
||||
@ -103,7 +103,7 @@ void derSeq_Entry::findIntervals (Function *c)
|
||||
BB *h, /* Node being processed */
|
||||
*header, /* Current interval's header node */
|
||||
*succ; /* Successor basic block */
|
||||
int i; /* Counter */
|
||||
//int i; /* Counter */
|
||||
queue H; /* Queue of possible header nodes */
|
||||
boolT first = true; /* First pass through the loop */
|
||||
|
||||
@ -125,7 +125,7 @@ void derSeq_Entry::findIntervals (Function *c)
|
||||
while ((h = pI->firstOfInt()) != NULL)
|
||||
{
|
||||
/* Check all immediate successors of h */
|
||||
for (i = 0; i < h->edges.size(); i++)
|
||||
for (size_t i = 0; i < h->edges.size(); i++)
|
||||
{
|
||||
succ = h->edges[i].BBptr;
|
||||
succ->inEdgeCount--;
|
||||
@ -176,11 +176,11 @@ static void displayIntervals (interval *pI)
|
||||
|
||||
while (pI)
|
||||
{
|
||||
printf (" Interval #: %ld\t#OutEdges: %ld\n", pI->numInt, pI->numOutEdges);
|
||||
printf (" Interval #: %d\t#OutEdges: %d\n", pI->numInt, pI->numOutEdges);
|
||||
for(BB *node : pI->nodes)
|
||||
{
|
||||
if (node->correspInt == NULL) /* real BBs */
|
||||
printf (" Node: %ld\n", node->begin()->loc_ip);
|
||||
printf (" Node: %d\n", node->begin()->loc_ip);
|
||||
else // BBs represent intervals
|
||||
printf (" Node (corresp int): %d\n", node->correspInt->numInt);
|
||||
}
|
||||
@ -190,17 +190,17 @@ static void displayIntervals (interval *pI)
|
||||
|
||||
|
||||
/* Allocates space for a new derSeq node. */
|
||||
static derSeq_Entry *newDerivedSeq()
|
||||
{
|
||||
return new derSeq_Entry;
|
||||
}
|
||||
//static derSeq_Entry *newDerivedSeq()
|
||||
//{
|
||||
// return new derSeq_Entry;
|
||||
//}
|
||||
|
||||
|
||||
/* Frees the storage allocated for the queue q*/
|
||||
static void freeQueue (queue &q)
|
||||
{
|
||||
q.clear();
|
||||
}
|
||||
//static void freeQueue (queue &q)
|
||||
//{
|
||||
// q.clear();
|
||||
//}
|
||||
|
||||
|
||||
/* Frees the storage allocated for the interval pI */
|
||||
@ -237,12 +237,12 @@ bool Function::nextOrderGraph (derSeq &derivedGi)
|
||||
{
|
||||
interval *Ii; /* Interval being processed */
|
||||
BB *BBnode, /* New basic block of intervals */
|
||||
*curr, /* BB being checked for out edges */
|
||||
//*curr, /* BB being checked for out edges */
|
||||
*succ /* Successor node */
|
||||
;
|
||||
//queue *listIi; /* List of intervals */
|
||||
int i, /* Index to outEdges array */
|
||||
j; /* Index to successors */
|
||||
int i; /* Index to outEdges array */
|
||||
/*j;*/ /* Index to successors */
|
||||
boolT sameGraph; /* Boolean, isomorphic graphs */
|
||||
|
||||
/* Process Gi's intervals */
|
||||
@ -271,7 +271,7 @@ bool Function::nextOrderGraph (derSeq &derivedGi)
|
||||
{
|
||||
for(BB *curr : listIi)
|
||||
{
|
||||
for (j = 0; j < curr->edges.size(); j++)
|
||||
for (size_t j = 0; j < curr->edges.size(); j++)
|
||||
{
|
||||
succ = curr->edges[j].BBptr;
|
||||
if (succ->inInterval != curr->inInterval)
|
||||
@ -287,7 +287,8 @@ bool Function::nextOrderGraph (derSeq &derivedGi)
|
||||
/* Convert list of pointers to intervals into a real graph.
|
||||
* Determines the number of in edges to each new BB, and places it
|
||||
* in numInEdges and inEdgeCount for later interval processing. */
|
||||
curr = new_entry.Gi = bbs.front();
|
||||
//curr = new_entry.Gi = bbs.front();
|
||||
new_entry.Gi = bbs.front();
|
||||
for(BB *curr : bbs)
|
||||
{
|
||||
for(TYPEADR_TYPE &edge : curr->edges)
|
||||
@ -315,6 +316,7 @@ uint8_t Function::findDerivedSeq (derSeq &derivedGi)
|
||||
BB *Gi; /* Current derived sequence graph */
|
||||
|
||||
derSeq::iterator iter=derivedGi.begin();
|
||||
assert(iter!=derivedGi.end());
|
||||
Gi = iter->Gi;
|
||||
while (! trivialGraph (Gi))
|
||||
{
|
||||
@ -343,7 +345,7 @@ uint8_t Function::findDerivedSeq (derSeq &derivedGi)
|
||||
|
||||
/* Converts the irreducible graph G into an equivalent reducible one, by
|
||||
* means of node splitting. */
|
||||
static void nodeSplitting (std::list<BB *> &G)
|
||||
static void nodeSplitting (std::list<BB *> &/*G*/)
|
||||
{
|
||||
fprintf(stderr,"Attempt to perform node splitting: NOT IMPLEMENTED\n");
|
||||
}
|
||||
@ -356,7 +358,7 @@ void derSeq::display()
|
||||
derSeq::iterator iter=this->begin();
|
||||
while (iter!=this->end())
|
||||
{
|
||||
printf ("\nIntervals for G%lX\n", n++);
|
||||
printf ("\nIntervals for G%X\n", n++);
|
||||
displayIntervals (iter->Ii);
|
||||
++iter;
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#define S_EXT 0x000200 /* sign extend */
|
||||
#define OP386 0x000400 /* 386 op-code */
|
||||
#define NSP 0x000800 /* NOT_HLL if SP is src or dst */
|
||||
#define ICODEMASK 0xFF00FF /* Masks off parser flags */
|
||||
// defined in Enums.h #define ICODEMASK 0xFF00FF /* Masks off parser flags */
|
||||
|
||||
static void rm(int i);
|
||||
static void modrm(int i);
|
||||
@ -408,7 +408,12 @@ LLOperand convertOperand(const x86_op_t &from)
|
||||
break;
|
||||
case op_register:
|
||||
return LLOperand::CreateReg2(convertRegister(from.data.reg));
|
||||
case op_immediate:
|
||||
return LLOperand::CreateImm2(from.data.sdword);
|
||||
default:
|
||||
fprintf(stderr,"convertOperand does not know how to convert %d\n",from.type);
|
||||
}
|
||||
return LLOperand::CreateImm2(0);
|
||||
}
|
||||
eErrorId scan(uint32_t ip, ICODE &p)
|
||||
{
|
||||
|
||||
@ -133,7 +133,7 @@ void destroySymTables(void)
|
||||
}
|
||||
|
||||
/* Using the value, read the symbolic name */
|
||||
boolT readVal(std::ostringstream &symName, uint32_t symOff, Function * symProc)
|
||||
boolT readVal(std::ostringstream &/*symName*/, uint32_t /*symOff*/, Function * /*symProc*/)
|
||||
{
|
||||
return false; // no symbolic names for now
|
||||
}
|
||||
@ -142,7 +142,6 @@ boolT readVal(std::ostringstream &symName, uint32_t symOff, Function * symProc)
|
||||
* if necessary (0 means no update necessary). */
|
||||
void SYMTAB::updateSymType (uint32_t symbol,const TypeContainer &tc)
|
||||
{
|
||||
int i;
|
||||
auto iter=findByLabel(symbol);
|
||||
if(iter==end())
|
||||
return;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "dcc.h"
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include "dcc.h"
|
||||
|
||||
TEST(CowriteTest, HandlesZeroInput) {
|
||||
EXPECT_EQ(1, 1);
|
||||
|
||||
14
src/tests/loader.cpp
Normal file
14
src/tests/loader.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "project.h"
|
||||
#include "loader.h"
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(Loader, NewProjectIsInitalized) {
|
||||
Project p;
|
||||
EXPECT_EQ(nullptr,p.callGraph);
|
||||
ASSERT_TRUE(p.pProcList.empty());
|
||||
ASSERT_TRUE(p.binary_path().empty());
|
||||
ASSERT_TRUE(p.project_name().empty());
|
||||
ASSERT_TRUE(p.symtab.empty());
|
||||
}
|
||||
|
||||
27
src/tests/project.cpp
Normal file
27
src/tests/project.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "project.h"
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(Project, NewProjectIsInitalized) {
|
||||
Project p;
|
||||
EXPECT_EQ(nullptr,p.callGraph);
|
||||
ASSERT_TRUE(p.pProcList.empty());
|
||||
ASSERT_TRUE(p.binary_path().empty());
|
||||
ASSERT_TRUE(p.project_name().empty());
|
||||
ASSERT_TRUE(p.symtab.empty());
|
||||
}
|
||||
|
||||
TEST(Project, CreatedProjectHasValidNames) {
|
||||
Project p;
|
||||
std::vector<std::string> strs = {"./Project1.EXE","/home/Project2.EXE","/home/Pro ject3"};
|
||||
std::vector<std::string> expected = {"Project1","Project2","Pro ject3"};
|
||||
for(size_t i=0; i<strs.size(); i++)
|
||||
{
|
||||
p.create(strs[i]);
|
||||
EXPECT_EQ(nullptr,p.callGraph);
|
||||
ASSERT_TRUE(p.pProcList.empty());
|
||||
EXPECT_EQ(expected[i],p.project_name());
|
||||
EXPECT_EQ(strs[i],p.binary_path());
|
||||
ASSERT_TRUE(p.symtab.empty());
|
||||
}
|
||||
}
|
||||
10
src/udm.cpp
10
src/udm.cpp
@ -12,8 +12,8 @@
|
||||
#include "project.h"
|
||||
|
||||
extern Project g_proj;
|
||||
static void displayCFG(Function * pProc);
|
||||
static void displayDfs(BB * pBB);
|
||||
//static void displayCFG(Function * pProc);
|
||||
//static void displayDfs(BB * pBB);
|
||||
|
||||
/****************************************************************************
|
||||
* udm
|
||||
@ -73,7 +73,7 @@ void udm(void)
|
||||
/* Build the control flow graph, find idioms, and convert low-level
|
||||
* icodes to high-level ones */
|
||||
Disassembler ds(2);
|
||||
for (auto iter = g_proj.pProcList.rbegin(); iter!=g_proj.pProcList.rend(); ++iter)
|
||||
for (auto iter = Project::get()->pProcList.rbegin(); iter!=Project::get()->pProcList.rend(); ++iter)
|
||||
{
|
||||
iter->buildCFG(ds);
|
||||
}
|
||||
@ -83,10 +83,10 @@ void udm(void)
|
||||
* and intermediate instructions. Find expressions by forward
|
||||
* substitution algorithm */
|
||||
std::bitset<32> live_regs;
|
||||
g_proj.pProcList.front().dataFlow (live_regs);
|
||||
Project::get()->pProcList.front().dataFlow (live_regs);
|
||||
|
||||
/* Control flow analysis - structuring algorithm */
|
||||
for (auto iter = g_proj.pProcList.rbegin(); iter!=g_proj.pProcList.rend(); ++iter)
|
||||
for (auto iter = Project::get()->pProcList.rbegin(); iter!=Project::get()->pProcList.rend(); ++iter)
|
||||
{
|
||||
iter->controlFlowAnalysis();
|
||||
}
|
||||
|
||||
6
valgrind_base.sh
Executable file
6
valgrind_base.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
cd bld
|
||||
make -j5
|
||||
cd ..
|
||||
./test_use_base.sh
|
||||
./valgrind_tester ./bld/dcc_original -s -c 2>stderr >stdout; diff tests/prev/ tests/outputs/
|
||||
Loading…
x
Reference in New Issue
Block a user