removed most of clang warnings / errors

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

4
.gitignore vendored
View File

@ -4,4 +4,6 @@ tests/prev
tests/outputs/*
tests/errors
*.autosave
bld*
bld*
*.user
*.idb

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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()

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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 */

View File

@ -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
View File

@ -0,0 +1,11 @@
#pragma once
class ILoader
{
};
class LoaderManger
{
};

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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");

View File

@ -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)

View File

@ -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;

View File

@ -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 */

View File

@ -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);
}

View File

@ -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))
{

View File

@ -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 */
}

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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.

View File

@ -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 */

View File

@ -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)

View File

@ -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
View 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;
}
}

View File

@ -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);

View File

@ -207,7 +207,9 @@ bool Idiom19::match(iICODE picode)
return true;
}
else /* indexed */
/* not supported yet */ ;
{
/* not supported yet */
}
return false;
}
int Idiom19::action()

View File

@ -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++);
}

View File

@ -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)

View File

@ -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);

View File

@ -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];

View File

@ -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

View File

@ -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 */
}
}

View File

@ -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;
}

View File

@ -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))

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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;

View File

@ -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
View 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
View 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());
}
}

View File

@ -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
View 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/