├── .gitattributes ├── .gitignore ├── 3rd_party ├── CMakeLists.txt └── libdisasm │ ├── CMakeLists.txt │ ├── INTEL_BUGS │ ├── LICENSE │ ├── NAMESPACE.TXT │ ├── README │ ├── TODO │ ├── ia32_fixup.cpp │ ├── ia32_implicit.cpp │ ├── ia32_implicit.h │ ├── ia32_insn.cpp │ ├── ia32_insn.h │ ├── ia32_invariant.cpp │ ├── ia32_invariant.h │ ├── ia32_modrm.cpp │ ├── ia32_modrm.h │ ├── ia32_opcode.dat │ ├── ia32_opcode_tables.cpp │ ├── ia32_opcode_tables.h │ ├── ia32_operand.cpp │ ├── ia32_operand.h │ ├── ia32_reg.cpp │ ├── ia32_reg.h │ ├── ia32_settings.cpp │ ├── ia32_settings.h │ ├── libdis.h │ ├── libdisasm.def │ ├── qword.h │ ├── x86_disasm.cpp │ ├── x86_format.cpp │ ├── x86_imm.cpp │ ├── x86_imm.h │ ├── x86_insn.cpp │ ├── x86_misc.cpp │ ├── x86_operand_list.cpp │ └── x86_operand_list.h ├── CMakeLists.txt ├── CMakeScripts ├── FindGMock.cmake └── cotire.cmake ├── LICENSE ├── Readme.md ├── base_regression.sh ├── common ├── CMakeLists.txt ├── PatternCollector.h ├── perfhlib.cpp └── perfhlib.h ├── covproc.sh ├── full_regression.sh ├── include ├── BasicBlock.h ├── BinaryImage.h ├── CallConvention.h ├── CallGraph.h ├── DccFrontend.h ├── Enums.h ├── IdentType.h ├── Procedure.h ├── StackFrame.h ├── ast.h ├── boost_fwd.h ├── bundle.h ├── dcc.h ├── dcc_interface.h ├── disassem.h ├── error.h ├── graph.h ├── icode.h ├── idioms │ ├── arith_idioms.h │ ├── call_idioms.h │ ├── epilogue_idioms.h │ ├── idiom.h │ ├── idiom1.h │ ├── mov_idioms.h │ ├── neg_idioms.h │ ├── shift_idioms.h │ └── xor_idioms.h ├── loader.h ├── locident.h ├── machine_x86.h ├── msvc_fixes.h ├── project.h ├── scanner.h ├── state.h ├── symtab.h └── types.h ├── prototypes └── dcclibs.dat ├── regression_tester.rb ├── sigs ├── dccb2c.sig ├── dccb2l.sig ├── dccb2s.sig ├── dccb3c.sig ├── dccb3m.sig ├── dccm5l.sig ├── dccm5s.sig ├── dccm8l.sig ├── dccm8m.sig ├── dccm8s.sig ├── dcct3p.sig ├── dcct4p.sig └── dcct5p.sig ├── src ├── BasicBlock.cpp ├── CMakeLists.txt ├── CallConvention.cpp ├── DccFrontend.cpp ├── Procedure.cpp ├── RegisterNode.cpp ├── ast.cpp ├── backend.cpp ├── bundle.cpp ├── chklib.cpp ├── comwrite.cpp ├── control.cpp ├── dataflow.cpp ├── dcc.cpp ├── dcc_interface.cpp ├── disassem.cpp ├── error.cpp ├── fixwild.cpp ├── frontend.cpp ├── graph.cpp ├── hlicode.cpp ├── hltype.cpp ├── icode.cpp ├── idioms.cpp ├── idioms │ ├── arith_idioms.cpp │ ├── call_idioms.cpp │ ├── epilogue_idioms.cpp │ ├── idiom.cpp │ ├── idiom1.cpp │ ├── mov_idioms.cpp │ ├── neg_idioms.cpp │ ├── shift_idioms.cpp │ └── xor_idioms.cpp ├── liveness_set.cpp ├── locident.cpp ├── machine_x86.cpp ├── parser.cpp ├── procs.cpp ├── project.cpp ├── proplong.cpp ├── reducible.cpp ├── scanner.cpp ├── symtab.cpp ├── tests │ ├── comwrite.cpp │ ├── loader.cpp │ └── project.cpp └── udm.cpp ├── test_use_all.sh ├── test_use_base.sh ├── tests ├── initial_base │ ├── BENCHFN.C │ ├── BENCHFN.b │ ├── BENCHLNG.C │ ├── BENCHLNG.b │ ├── BENCHMUL.C │ ├── BENCHMUL.b │ ├── BENCHMUS.b │ ├── BENCHSHO.C │ ├── BENCHSHO.b │ ├── BYTEOPS.C │ ├── BYTEOPS.b │ ├── DHAMP.C │ ├── DHAMP.b │ ├── FIBO.C │ ├── FIBOL.b │ ├── FIBOS.b │ ├── INTOPS.C │ ├── INTOPS.b │ ├── LONGOPS.C │ ├── LONGOPS.b │ ├── MATRIXMU.C │ ├── MATRIXMU.b │ ├── MAX.C │ ├── MAX.b │ ├── STRLEN.C │ ├── STRLEN.b │ ├── TESTLONG.C │ └── TESTLONG.b ├── inputs_base │ ├── BENCHFN.EXE │ ├── BENCHLNG.EXE │ ├── BENCHMUL.EXE │ ├── BENCHMUS.EXE │ ├── BENCHSHO.EXE │ ├── BYTEOPS.EXE │ ├── DHAMP.EXE │ ├── FIBOL.EXE │ ├── FIBOS.EXE │ ├── INTOPS.EXE │ ├── LONGOPS.EXE │ ├── MATRIXMU.EXE │ ├── MAX.EXE │ ├── MIN.EXE │ ├── STRLEN.EXE │ └── TESTLONG.EXE └── prev_base │ ├── BENCHFN.EXE.a1 │ ├── BENCHFN.EXE.a2 │ ├── BENCHFN.b │ ├── BENCHLNG.EXE.a1 │ ├── BENCHLNG.EXE.a2 │ ├── BENCHLNG.b │ ├── BENCHMUL.EXE.a1 │ ├── BENCHMUL.EXE.a2 │ ├── BENCHMUL.b │ ├── BENCHMUS.EXE.a1 │ ├── BENCHMUS.EXE.a2 │ ├── BENCHMUS.b │ ├── BENCHSHO.EXE.a1 │ ├── BENCHSHO.EXE.a2 │ ├── BENCHSHO.b │ ├── BYTEOPS.EXE.a1 │ ├── BYTEOPS.EXE.a2 │ ├── BYTEOPS.b │ ├── DHAMP.EXE.a1 │ ├── DHAMP.EXE.a2 │ ├── DHAMP.b │ ├── FIBOL.EXE.a1 │ ├── FIBOL.EXE.a2 │ ├── FIBOL.b │ ├── FIBOS.EXE.a1 │ ├── FIBOS.EXE.a2 │ ├── FIBOS.b │ ├── INTERCEP.EXE.a1 │ ├── INTERCEP.EXE.a2 │ ├── INTOPS.EXE.a1 │ ├── INTOPS.EXE.a2 │ ├── INTOPS.b │ ├── LONGOPS.EXE.a1 │ ├── LONGOPS.EXE.a2 │ ├── LONGOPS.b │ ├── MATRIXMU.EXE.a1 │ ├── MATRIXMU.EXE.a2 │ ├── MATRIXMU.b │ ├── MAX.EXE.a1 │ ├── MAX.EXE.a2 │ ├── MAX.b │ ├── MIN.EXE.a1 │ ├── MIN.EXE.a2 │ ├── MIN.b │ ├── STRLEN.EXE.a1 │ ├── STRLEN.EXE.a2 │ ├── STRLEN.b │ ├── TESTLONG.EXE.a1 │ ├── TESTLONG.EXE.a2 │ └── TESTLONG.b ├── tools ├── CMakeLists.txt ├── dispsrch │ ├── CMakeLists.txt │ ├── dispsig.cpp │ ├── dispsig.mak │ ├── dispsrch.txt │ ├── srchsig.cpp │ └── srchsig.mak ├── makedsig │ ├── CMakeLists.txt │ ├── LIB_PatternCollector.cpp │ ├── LIB_PatternCollector.h │ ├── TPL_PatternCollector.cpp │ ├── TPL_PatternCollector.h │ ├── fixwild.cpp │ ├── makedsig.cpp │ └── makedsig.txt ├── parsehdr │ ├── CMakeLists.txt │ ├── locident.h │ ├── parsehdr.cpp │ ├── parsehdr.h │ ├── parsehdr.txt │ ├── parselib.mak │ └── tcfiles.lst ├── readsig │ ├── CMakeLists.txt │ ├── readsig.cpp │ ├── readsig.mak │ └── readsig.txt └── regression_tester │ ├── CMakeLists.txt │ └── regression_tester.cpp ├── valgrind_base.sh └── valgrind_tester /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.c text 3 | *.cpp text 4 | *.ui text 5 | *.qrc text 6 | *.h text 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | tests/inputs 3 | tests/prev 4 | tests/outputs/* 5 | tests/errors 6 | *.autosave 7 | bld* 8 | *.user 9 | *.idb 10 | -------------------------------------------------------------------------------- /3rd_party/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_definitions(-D_CRT_SECURE_NO_WARNINGS -D__STDC_FORMAT_MACROS) 2 | add_subdirectory(libdisasm) 3 | 4 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(disasm_LIB_SRCS 2 | ia32_implicit.cpp 3 | ia32_implicit.h 4 | ia32_insn.cpp 5 | ia32_insn.h 6 | ia32_invariant.cpp 7 | ia32_invariant.h 8 | ia32_modrm.cpp 9 | ia32_modrm.h 10 | ia32_opcode_tables.cpp 11 | ia32_opcode_tables.h 12 | ia32_operand.cpp 13 | ia32_operand.h 14 | ia32_reg.cpp 15 | ia32_reg.h 16 | ia32_settings.cpp 17 | ia32_settings.h 18 | libdis.h 19 | qword.h 20 | x86_disasm.cpp 21 | x86_format.cpp 22 | x86_imm.cpp 23 | x86_imm.h 24 | x86_insn.cpp 25 | x86_misc.cpp 26 | x86_operand_list.cpp 27 | x86_operand_list.h 28 | ) 29 | 30 | add_library(disasm SHARED ${disasm_LIB_SRCS}) 31 | add_library(disasm_s STATIC ${disasm_LIB_SRCS}) 32 | install(TARGETS disasm DESTINATION lib) 33 | install(FILES libdis.h DESTINATION /include) 34 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/INTEL_BUGS: -------------------------------------------------------------------------------- 1 | PMOVMSKB 2 | Gd, Pq1H 3 | PMOVMSKB 4 | (66) 5 | Gd, Vdq1H 6 | 7 | should be 8 | 9 | PMOVMSKB 10 | Gd, Qq1H 11 | PMOVMSKB 12 | (66) 13 | Gd, Wdq1H 14 | 15 | The instruction represented by this opcode expression does not support any 16 | operand to be a memory location. 17 | 18 | MASKMOVQ 19 | Pq, Pq1H 20 | MASKMOVDQU 21 | (66) 22 | Vdq, Vdq1H 23 | 24 | should be 25 | 26 | MASKMOVQ 27 | Pq, Pq1H 28 | MASKMOVDQU 29 | (66) 30 | Vdq, Wdq1H 31 | 32 | MOVMSKPS 33 | Gd, Vps1H 34 | MOVMSKPD 35 | (66) 36 | Gd, Vpd1H 37 | 38 | should be 39 | 40 | MOVMSKPS 41 | Gd, Wps1H 42 | MOVMSKPD 43 | (66) 44 | Gd, Wpd1H 45 | 46 | The opcode table entries for LFS, LGS, and LSS 47 | 48 | L[FGS]S 49 | Mp 50 | 51 | should be 52 | 53 | L[FGS]S 54 | Gv,Mp 55 | 56 | MOVHLPS 57 | Vps, Vps 58 | 59 | MOVLHPS 60 | Vps, Vps 61 | 62 | should be 63 | 64 | MOVHLPS 65 | Vps, Wps 66 | 67 | MOVLHPS 68 | Vps, Wps 69 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/NAMESPACE.TXT: -------------------------------------------------------------------------------- 1 | 2 | The rewritten libdisasm code uses the following namespaces: 3 | 4 | 5 | Prefix Namespace 6 | ---------------------------------------------------- 7 | x86_ Global 'libdisasm' namespace 8 | ia32_ Internal IA32 ISA namespace 9 | ia64_ Internal IA64 ISA namespace 10 | ix64_ Internal X86-64 ISA namespace 11 | 12 | Note that the 64-bit ISAs are not yet supported/written. 13 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/README: -------------------------------------------------------------------------------- 1 | This is a cut-up version of libdisasm originally from the bastard project http://bastard.sourceforge.net/ 2 | 3 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/TODO: -------------------------------------------------------------------------------- 1 | x86_format.c 2 | ------------ 3 | intel: jmpf -> jmp, callf -> call 4 | att: jmpf -> ljmp, callf -> lcall 5 | 6 | opcode table 7 | ------------ 8 | finish typing instructions 9 | fix flag clear/set/toggle types 10 | 11 | ix64 stuff 12 | ---------- 13 | document output file formats in web page 14 | features doc: register aliases, implicit operands, stack mods, 15 | ring0 flags, eflags, cpu model/isa 16 | 17 | ia32_handle_* implementation 18 | 19 | fix operand 0F C2 20 | CMPPS 21 | 22 | * sysenter, sysexit as CALL types -- preceded by MSR writes 23 | * SYSENTER/SYSEXIT stack : overwrites SS, ESP 24 | * stos, cmps, scas, movs, ins, outs, lods -> OP_PTR 25 | * OP_SIZE in implicit operands 26 | * use OP_SIZE to choose reg sizes! 27 | 28 | DONE?? : 29 | implicit operands: provide action ? 30 | e.g. add/inc for stach, write, etc 31 | replace table numbers in opcodes.dat with 32 | #defines for table names 33 | 34 | replace 0 with INSN_INVALID [or maybe FF for imnvalid and 00 for Not Applicable */ 35 | no wait that is only for prefix tables -- n/p 36 | 37 | if ( prefx) only use if insn != invalid 38 | 39 | these should cover all the wacky disasm exceptions 40 | 41 | for the rep one we can chet, match only a 0x90 42 | 43 | todo: privilege | ring 44 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/ia32_fixup.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static const char * mem_fixup[256] = { 4 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 00 */ 5 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 08 */ 6 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 10 */ 7 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 18 */ 8 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 20 */ 9 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 28 */ 10 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 30 */ 11 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 38 */ 12 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 40 */ 13 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 48 */ 14 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 50 */ 15 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 58 */ 16 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 60 */ 17 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 68 */ 18 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 70 */ 19 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 78 */ 20 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 80 */ 21 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 88 */ 22 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 90 */ 23 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 98 */ 24 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* A0 */ 25 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* A8 */ 26 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* B0 */ 27 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* B8 */ 28 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* C0 */ 29 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* C8 */ 30 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* D0 */ 31 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* D8 */ 32 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* E0 */ 33 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* E8 */ 34 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* F0 */ 35 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* F8 */ 36 | }; 37 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/ia32_implicit.h: -------------------------------------------------------------------------------- 1 | #ifndef IA32_IMPLICIT_H 2 | #define IA32_IMPLICIT_H 3 | 4 | #include "libdis.h" 5 | 6 | /* OK, this is a hack to deal with prefixes having implicit operands... 7 | * thought I had removed all the old hackishness ;( */ 8 | 9 | #define IDX_IMPLICIT_REP 41 /* change this if the table changes! */ 10 | 11 | //unsigned int ia32_insn_implicit_ops( x86_insn_t *insn, unsigned int impl_idx ); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/ia32_invariant.h: -------------------------------------------------------------------------------- 1 | #ifndef IA32_INVARIANT_H 2 | #define IA32_INVARIANT_H 3 | 4 | #include "libdis.h" 5 | 6 | size_t ia32_disasm_invariant( unsigned char *buf, size_t buf_len, 7 | x86_invariant_t *inv); 8 | 9 | size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/ia32_modrm.h: -------------------------------------------------------------------------------- 1 | #ifndef IA32_MODRM_H 2 | #define IA32_MODRM_H 3 | 4 | #include "libdis.h" 5 | #include "ia32_insn.h" 6 | 7 | size_t ia32_modrm_decode( unsigned char *buf, unsigned int buf_len, 8 | x86_op_t *op, x86_insn_t *insn, 9 | size_t gen_regs ); 10 | 11 | void ia32_reg_decode( unsigned char byte, x86_op_t *op, size_t gen_regs ); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/ia32_opcode_tables.h: -------------------------------------------------------------------------------- 1 | #define idx_Main 0 2 | #define idx_66 1 3 | #define idx_F2 2 4 | #define idx_F3 3 5 | #define idx_0F 4 6 | #define idx_660F 5 7 | #define idx_F20F 6 8 | #define idx_F30F 7 9 | #define idx_0F00 8 10 | #define idx_0F01 9 11 | #define idx_0F0111 10 12 | #define idx_0F12 11 13 | #define idx_0F16 12 14 | #define idx_0F18 13 15 | #define idx_0F71 14 16 | #define idx_660F71 15 17 | #define idx_0F72 16 18 | #define idx_660F72 17 19 | #define idx_0F73 18 20 | #define idx_660F73 19 21 | #define idx_0FAE 20 22 | #define idx_0FBA 21 23 | #define idx_0FC7 22 24 | #define idx_0FB9 23 25 | #define idx_C6 24 26 | #define idx_C7 25 27 | #define idx_80 26 28 | #define idx_81 27 29 | #define idx_82 28 30 | #define idx_83 29 31 | #define idx_C0 30 32 | #define idx_C1 31 33 | #define idx_D0 32 34 | #define idx_D1 33 35 | #define idx_D2 34 36 | #define idx_D3 35 37 | #define idx_F6 36 38 | #define idx_F7 37 39 | #define idx_FE 38 40 | #define idx_FF 39 41 | #define idx_D8 40 42 | #define idx_D8C0 41 43 | #define idx_D9 42 44 | #define idx_D9C0 43 45 | #define idx_DA 44 46 | #define idx_DAC0 45 47 | #define idx_DB 46 48 | #define idx_DBC0 47 49 | #define idx_DC 48 50 | #define idx_DCC0 49 51 | #define idx_DD 50 52 | #define idx_DDC0 51 53 | #define idx_DE 52 54 | #define idx_DEC0 53 55 | #define idx_DF 54 56 | #define idx_DFC0 55 57 | #define idx_0F0F 56 58 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/ia32_operand.h: -------------------------------------------------------------------------------- 1 | #ifndef IA32_OPERAND_H 2 | #define IA32_OPERAND_H 3 | 4 | #include "libdis.h" 5 | #include "ia32_insn.h" 6 | 7 | size_t ia32_decode_operand( unsigned char *buf, size_t buf_len, 8 | x86_insn_t *insn, unsigned int raw_op, 9 | unsigned int raw_flags, unsigned int prefixes, 10 | unsigned char modrm ); 11 | #endif 12 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/ia32_reg.h: -------------------------------------------------------------------------------- 1 | #ifndef IA32_REG_H 2 | #define IA32_REG_H 3 | 4 | #include /* for size_t */ 5 | #include "libdis.h" /* for x86_reg_t */ 6 | 7 | /* NOTE these are used in opcode tables for hard-coded registers */ 8 | #define REG_DWORD_OFFSET 1 /* 0 + 1 */ 9 | #define REG_ECX_INDEX 2 /* 0 + 1 + 1 */ 10 | #define REG_ESP_INDEX 5 /* 0 + 4 + 1 */ 11 | #define REG_EBP_INDEX 6 /* 0 + 5 + 1 */ 12 | #define REG_ESI_INDEX 7 /* 0 + 6 + 1 */ 13 | #define REG_EDI_INDEX 8 /* 0 + 7 + 1 */ 14 | #define REG_WORD_OFFSET 9 /* 1 * 8 + 1 */ 15 | #define REG_BYTE_OFFSET 17 /* 2 * 8 + 1 */ 16 | #define REG_MMX_OFFSET 25 /* 3 * 8 + 1 */ 17 | #define REG_SIMD_OFFSET 33 /* 4 * 8 + 1 */ 18 | #define REG_DEBUG_OFFSET 41 /* 5 * 8 + 1 */ 19 | #define REG_CTRL_OFFSET 49 /* 6 * 8 + 1 */ 20 | #define REG_TEST_OFFSET 57 /* 7 * 8 + 1 */ 21 | #define REG_SEG_OFFSET 65 /* 8 * 8 + 1 */ 22 | #define REG_LDTR_INDEX 71 /* 8 * 8 + 1 + 1 */ 23 | #define REG_GDTR_INDEX 72 /* 8 * 8 + 2 + 1 */ 24 | #define REG_FPU_OFFSET 73 /* 9 * 8 + 1 */ 25 | #define REG_FLAGS_INDEX 81 /* 10 * 8 + 1 */ 26 | #define REG_FPCTRL_INDEX 82 /* 10 * 8 + 1 + 1 */ 27 | #define REG_FPSTATUS_INDEX 83 /* 10 * 8 + 2 + 1 */ 28 | #define REG_FPTAG_INDEX 84 /* 10 * 8 + 3 + 1 */ 29 | #define REG_EIP_INDEX 85 /* 10 * 8 + 4 + 1 */ 30 | #define REG_IP_INDEX 86 /* 10 * 8 + 5 + 1 */ 31 | #define REG_IDTR_INDEX 87 /* 10 * 8 + 6 + 1 */ 32 | #define REG_MXCSG_INDEX 88 /* 10 * 8 + 7 + 1 */ 33 | #define REG_TR_INDEX 89 /* 10 * 8 + 8 + 1 */ 34 | #define REG_CSMSR_INDEX 90 /* 10 * 8 + 9 + 1 */ 35 | #define REG_ESPMSR_INDEX 91 /* 10 * 8 + 10 + 1 */ 36 | #define REG_EIPMSR_INDEX 92 /* 10 * 8 + 11 + 1 */ 37 | 38 | void ia32_handle_register( x86_reg_t *reg, size_t id ); 39 | size_t ia32_true_register_id( size_t id ); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/ia32_settings.cpp: -------------------------------------------------------------------------------- 1 | #include "libdis.h" 2 | #include "ia32_settings.h" 3 | #include "ia32_reg.h" 4 | #include "ia32_insn.h" 5 | 6 | ia32_settings_t ia32_settings = { 7 | 1, 0xF4, 8 | MAX_INSTRUCTION_SIZE, 9 | 4, 4, 8, 4, 8, 10 | REG_ESP_INDEX, REG_EBP_INDEX, REG_EIP_INDEX, REG_FLAGS_INDEX, 11 | REG_DWORD_OFFSET, REG_SEG_OFFSET, REG_FPU_OFFSET, 12 | opt_none 13 | }; 14 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/ia32_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef IA32_SETTINGS_H 2 | #define IA32_SETTINGS_H 3 | 4 | #include "libdis.h" 5 | 6 | typedef struct { 7 | /* options */ 8 | unsigned char endian, /* 0 = big, 1 = little */ 9 | wc_byte, /* wildcard byte */ 10 | max_insn, /* max insn size */ 11 | sz_addr, /* default address size */ 12 | sz_oper, /* default operand size */ 13 | sz_byte, /* # bits in byte */ 14 | sz_word, /* # bytes in machine word */ 15 | sz_dword; /* # bytes in machine dword */ 16 | unsigned int id_sp_reg, /* id of stack pointer */ 17 | id_fp_reg, /* id of frame pointer */ 18 | id_ip_reg, /* id of instruction pointer */ 19 | id_flag_reg, /* id of flags register */ 20 | offset_gen_regs, /* start of general regs */ 21 | offset_seg_regs, /* start of segment regs */ 22 | offset_fpu_regs; /* start of floating point regs */ 23 | /* user-controlled settings */ 24 | enum x86_options options; 25 | } ia32_settings_t; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/libdisasm.def: -------------------------------------------------------------------------------- 1 | ;libdisasm.def : Declares the module parameters 2 | 3 | LIBRARY "libdisasm.dll" 4 | DESCRIPTION "libdisasm exported functions" 5 | EXPORTS 6 | x86_addr_size @1 7 | x86_cleanup @2 8 | x86_disasm @3 9 | x86_disasm_forward @4 10 | x86_disasm_range @5 11 | x86_endian @6 12 | x86_format_header @7 13 | x86_format_insn @8 14 | x86_format_mnemonic @9 15 | x86_format_operand @10 16 | x86_fp_reg @11 17 | x86_get_branch_target @12 18 | x86_get_imm @13 19 | x86_get_options @14 20 | x86_get_raw_imm @15 21 | x86_get_rel_offset @16 22 | x86_imm_signsized @17 23 | x86_imm_sized @18 24 | x86_init @19 25 | x86_insn_is_tagged @20 26 | x86_insn_is_valid @21 27 | x86_invariant_disasm @22 28 | x86_ip_reg @23 29 | x86_max_insn_size @24 30 | x86_op_size @25 31 | x86_operand_1st @26 32 | x86_operand_2nd @27 33 | x86_operand_3rd @28 34 | x86_operand_count @29 35 | x86_operand_foreach @30 36 | x86_operand_new @31 37 | x86_operand_size @32 38 | x86_oplist_free @33 39 | x86_reg_from_id @34 40 | x86_report_error @35 41 | x86_set_insn_addr @36 42 | x86_set_insn_block @37 43 | x86_set_insn_function @38 44 | x86_set_insn_offset @39 45 | x86_set_options @40 46 | x86_set_reporter @41 47 | x86_size_disasm @42 48 | x86_sp_reg @43 49 | x86_tag_insn @44 -------------------------------------------------------------------------------- /3rd_party/libdisasm/qword.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBDISASM_QWORD_H 2 | #define LIBDISASM_QWORD_H 3 | 4 | #include 5 | 6 | /* platform independent data types */ 7 | 8 | #ifdef _MSC_VER 9 | typedef __int64 qword_t; 10 | #else 11 | typedef int64_t qword_t; 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/x86_imm.cpp: -------------------------------------------------------------------------------- 1 | #include "qword.h" 2 | #include "x86_imm.h" 3 | 4 | #include 5 | 6 | unsigned int x86_imm_signsized( unsigned char * buf, size_t buf_len, 7 | void *dest, unsigned int size ) { 8 | signed char *cp = (signed char *) dest; 9 | signed short *sp = (signed short *) dest; 10 | int32_t *lp = (int32_t *) dest; 11 | qword_t *qp = (qword_t *) dest; 12 | 13 | if ( size > buf_len ) { 14 | return 0; 15 | } 16 | 17 | /* Copy 'size' bytes from *buf to *op 18 | * return number of bytes copied */ 19 | switch (size) { 20 | case 1: /* BYTE */ 21 | *cp = *((signed char *) buf); 22 | break; 23 | case 2: /* WORD */ 24 | *sp = *((signed short *) buf); 25 | break; 26 | case 6: 27 | case 8: /* QWORD */ 28 | *qp = *((qword_t *) buf); 29 | break; 30 | case 4: /* DWORD */ 31 | default: 32 | *lp = *((int32_t *) buf); 33 | break; 34 | } 35 | return (size); 36 | } 37 | 38 | unsigned int x86_imm_sized( unsigned char * buf, size_t buf_len, void *dest, 39 | unsigned int size ) { 40 | unsigned char *cp = (unsigned char *) dest; 41 | unsigned short *sp = (unsigned short *) dest; 42 | uint32_t *lp = (uint32_t *) dest; 43 | qword_t *qp = (qword_t *) dest; 44 | 45 | if ( size > buf_len ) { 46 | return 0; 47 | } 48 | 49 | /* Copy 'size' bytes from *buf to *op 50 | * return number of bytes copied */ 51 | switch (size) { 52 | case 1: /* BYTE */ 53 | *cp = *((unsigned char *) buf); 54 | break; 55 | case 2: /* WORD */ 56 | *sp = *((unsigned short *) buf); 57 | break; 58 | case 6: 59 | case 8: /* QWORD */ 60 | *qp = *((qword_t *) buf); 61 | break; 62 | case 4: /* DWORD */ 63 | default: 64 | *lp = *((uint32_t *) buf); 65 | break; 66 | } 67 | 68 | return (size); 69 | } 70 | 71 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/x86_imm.h: -------------------------------------------------------------------------------- 1 | #ifndef x86_IMM_H 2 | #define x86_IMM_H 3 | 4 | #include "./qword.h" 5 | #include 6 | 7 | #ifdef WIN32 8 | #include 9 | #endif 10 | 11 | /* these are in the global x86 namespace but are not a part of the 12 | * official API */ 13 | unsigned int x86_imm_sized( unsigned char *buf, size_t buf_len, void *dest, 14 | unsigned int size ); 15 | 16 | unsigned int x86_imm_signsized( unsigned char *buf, size_t buf_len, void *dest, 17 | unsigned int size ); 18 | #endif 19 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/x86_misc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "libdis.h" 6 | #include "ia32_insn.h" 7 | #include "ia32_reg.h" /* for ia32_reg wrapper */ 8 | #include "ia32_settings.h" 9 | extern ia32_settings_t ia32_settings; 10 | 11 | #ifdef _MSC_VER 12 | #define snprintf _snprintf 13 | #define inline __inline 14 | #endif 15 | 16 | 17 | /* =========================================================== INIT/TERM */ 18 | 19 | int X86_Disasm::x86_init( enum x86_options options, DISASM_REPORTER reporter, void * arg ) 20 | { 21 | ia32_settings.options = options; 22 | __x86_reporter_func = reporter; 23 | __x86_reporter_arg = arg; 24 | 25 | return 1; 26 | } 27 | 28 | void X86_Disasm::x86_set_reporter( DISASM_REPORTER reporter, void * arg ) { 29 | __x86_reporter_func = reporter; 30 | __x86_reporter_arg = arg; 31 | } 32 | 33 | void X86_Disasm::x86_set_options( enum x86_options options ){ 34 | ia32_settings.options = options; 35 | } 36 | 37 | enum x86_options X86_Disasm::x86_get_options( void ) { 38 | return ia32_settings.options; 39 | } 40 | 41 | int X86_Disasm::x86_cleanup( void ) 42 | { 43 | return 1; 44 | } 45 | 46 | /* =========================================================== ERRORS */ 47 | void X86_Disasm::x86_report_error( enum x86_report_codes code, void *data ) { 48 | if ( __x86_reporter_func ) { 49 | (*__x86_reporter_func)(code, data, __x86_reporter_arg); 50 | } 51 | } 52 | 53 | 54 | /* =========================================================== MISC */ 55 | unsigned int X86_Disasm::x86_endian(void) { return ia32_settings.endian; } 56 | unsigned int X86_Disasm::x86_addr_size(void) { return ia32_settings.sz_addr; } 57 | unsigned int X86_Disasm::x86_op_size(void) { return ia32_settings.sz_oper; } 58 | unsigned int X86_Disasm::x86_word_size(void) { return ia32_settings.sz_word; } 59 | unsigned int X86_Disasm::x86_max_insn_size(void){ return ia32_settings.max_insn; } 60 | unsigned int X86_Disasm::x86_sp_reg(void) { return ia32_settings.id_sp_reg; } 61 | unsigned int X86_Disasm::x86_fp_reg(void) { return ia32_settings.id_fp_reg; } 62 | unsigned int X86_Disasm::x86_ip_reg(void) { return ia32_settings.id_ip_reg; } 63 | unsigned int X86_Disasm::x86_flag_reg(void) { return ia32_settings.id_flag_reg; } 64 | 65 | /* wrapper function to hide the IA32 register fn */ 66 | void x86_reg_t::x86_reg_from_id( unsigned int _id) { 67 | ia32_handle_register( this, _id ); 68 | return; 69 | } 70 | -------------------------------------------------------------------------------- /3rd_party/libdisasm/x86_operand_list.h: -------------------------------------------------------------------------------- 1 | #ifndef X86_OPERAND_LIST_H 2 | #define X86_OPERAND_LIST_H 3 | #include "libdis.h" 4 | 5 | 6 | //x86_op_t * x86_operand_new( x86_insn_t *insn ); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(dcc_original) 2 | cmake_minimum_required(VERSION 3.7) 3 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 4 | set(CMAKE_AUTOMOC ON) 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Qt5 COMPONENTS Core) 9 | 10 | option(dcc_build_tests "Enable unit tests." OFF) 11 | #SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}) 12 | if(WIN32) 13 | add_definitions(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS) 14 | endif() 15 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 16 | add_definitions(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE -DNOMINMAX) 17 | add_definitions(/W4) 18 | else() 19 | #-D_GLIBCXX_DEBUG 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 21 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} " ) #--coverage 22 | endif() 23 | 24 | set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH}) 25 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}) 26 | include(cotire) 27 | find_package(Boost) 28 | 29 | if(dcc_build_tests) 30 | enable_testing() 31 | find_package(GMock) 32 | endif() 33 | 34 | 35 | include_directories( 36 | 3rd_party/libdisasm 37 | include 38 | include/idioms 39 | common 40 | ${Boost_INCLUDE_DIRS} 41 | ) 42 | 43 | 44 | add_subdirectory(3rd_party) 45 | add_subdirectory(common) 46 | add_subdirectory(tools) 47 | 48 | 49 | set(dcc_LIB_SOURCES 50 | src/CallConvention.cpp 51 | src/ast.cpp 52 | src/backend.cpp 53 | src/bundle.cpp 54 | src/chklib.cpp 55 | src/comwrite.cpp 56 | src/control.cpp 57 | src/dataflow.cpp 58 | src/disassem.cpp 59 | src/DccFrontend.cpp 60 | src/error.cpp 61 | src/fixwild.cpp 62 | src/graph.cpp 63 | src/hlicode.cpp 64 | src/hltype.cpp 65 | src/machine_x86.cpp 66 | src/icode.cpp 67 | src/RegisterNode 68 | src/idioms.cpp 69 | src/idioms/idiom.cpp 70 | src/idioms/idiom1.cpp 71 | src/idioms/arith_idioms.cpp 72 | src/idioms/call_idioms.cpp 73 | src/idioms/epilogue_idioms.cpp 74 | src/idioms/mov_idioms.cpp 75 | src/idioms/neg_idioms.cpp 76 | src/idioms/shift_idioms.cpp 77 | src/idioms/xor_idioms.cpp 78 | src/locident.cpp 79 | src/liveness_set.cpp 80 | src/parser.cpp 81 | src/procs.cpp 82 | src/project.cpp 83 | src/Procedure.cpp 84 | src/proplong.cpp 85 | src/reducible.cpp 86 | src/scanner.cpp 87 | src/symtab.cpp 88 | src/udm.cpp 89 | src/BasicBlock.cpp 90 | src/dcc_interface.cpp 91 | ) 92 | set(dcc_SOURCES 93 | src/dcc.cpp 94 | ) 95 | set(dcc_HEADERS 96 | include/ast.h 97 | include/bundle.h 98 | include/BinaryImage.h 99 | include/DccFrontend.h 100 | include/Enums.h 101 | include/dcc.h 102 | include/disassem.h 103 | include/error.h 104 | include/graph.h 105 | include/machine_x86.h 106 | include/icode.h 107 | include/idioms/idiom.h 108 | include/idioms/idiom1.h 109 | include/idioms/arith_idioms.h 110 | include/idioms/call_idioms.h 111 | include/idioms/epilogue_idioms.h 112 | include/idioms/mov_idioms.h 113 | include/idioms/neg_idioms.h 114 | include/idioms/shift_idioms.h 115 | include/idioms/xor_idioms.h 116 | include/locident.h 117 | include/CallConvention.h 118 | include/project.h 119 | include/scanner.h 120 | include/state.h 121 | include/symtab.h 122 | include/types.h 123 | include/Procedure.h 124 | include/StackFrame.h 125 | include/BasicBlock.h 126 | include/dcc_interface.h 127 | 128 | ) 129 | 130 | source_group(Source FILES ${dcc_SOURCES}) 131 | source_group(Headers FILES ${dcc_HEADERS}) 132 | 133 | add_library(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS}) 134 | target_link_libraries(dcc_lib PUBLIC Qt5::Core) 135 | #cotire(dcc_lib) 136 | 137 | add_executable(dcc_original ${dcc_SOURCES} ${dcc_HEADERS}) 138 | target_link_libraries(dcc_original dcc_lib dcc_hash disasm_s Qt5::Core) 139 | 140 | #ADD_SUBDIRECTORY(gui) 141 | if(dcc_build_tests) 142 | add_subdirectory(src) 143 | endif() 144 | 145 | -------------------------------------------------------------------------------- /CMakeScripts/FindGMock.cmake: -------------------------------------------------------------------------------- 1 | # Locate the Google C++ Mocking Framework. 2 | # 3 | # Defines the following variables: 4 | # 5 | # GMOCK_FOUND - Found the Google Mocking framework 6 | # GMOCK_INCLUDE_DIRS - Include directories 7 | # 8 | # Also defines the library variables below as normal 9 | # variables. These contain debug/optimized keywords when 10 | # a debugging library is found. 11 | # 12 | # GMOCK_BOTH_LIBRARIES - Both libgmock & libgmock-main 13 | # GMOCK_LIBRARIES - libgmock 14 | # GMOCK_MAIN_LIBRARIES - libgmock-main 15 | # 16 | # Accepts the following variables as input: 17 | # 18 | # GMOCK_ROOT - (as CMake or env. variable) 19 | # The root directory of the gmock install prefix 20 | # 21 | #----------------------- 22 | # Example Usage: 23 | # 24 | # enable_testing(true) 25 | # find_package(GMock REQUIRED) 26 | # include_directories(${GMOCK_INCLUDE_DIRS}) 27 | # 28 | # add_executable(foo foo.cc) 29 | # target_link_libraries(foo ${GMOCK_BOTH_LIBRARIES}) 30 | # 31 | # add_test(AllTestsInFoo foo) 32 | # 33 | 34 | set (GMOCK_FOUND FALSE) 35 | 36 | set (GMOCK_ROOT $ENV{GMOCK_ROOT} CACHE PATH "Path to the gmock root directory.") 37 | if (NOT EXISTS ${GMOCK_ROOT}) 38 | message (FATAL_ERROR "GMOCK_ROOT does not exist.") 39 | endif () 40 | 41 | set (GMOCK_BUILD ${GMOCK_ROOT}/build CACHE PATH "Path to the gmock build directory.") 42 | if (NOT EXISTS ${GMOCK_BUILD}) 43 | message (FATAL_ERROR "GMOCK_BUILD does not exist.") 44 | endif () 45 | 46 | # Find the include directory 47 | find_path(GMOCK_INCLUDE_DIRS gmock/gmock.h 48 | HINTS 49 | ${GMOCK_ROOT}/include 50 | ) 51 | mark_as_advanced(GMOCK_INCLUDE_DIRS) 52 | 53 | function(_gmock_find_library _name) 54 | find_library(${_name} 55 | NAMES ${ARGN} 56 | HINTS 57 | $ENV{GMOCK_ROOT} 58 | ${GMOCK_ROOT} 59 | ) 60 | mark_as_advanced(${_name}) 61 | endfunction() 62 | 63 | # Find the gmock libraries 64 | if (MSVC) 65 | find_library (GMOCK_LIBRARIES_DEBUG gmock ${GMOCK_BUILD}/Debug) 66 | find_library (GMOCK_LIBRARIES_RELEASE gmock ${GMOCK_BUILD}/Release) 67 | find_library (GMOCK_MAIN_LIBRARIES_DEBUG gmock_main ${GMOCK_BUILD}/Debug) 68 | find_library (GMOCK_MAIN_LIBRARIES_RELEASE gmock_main ${GMOCK_BUILD}/Release) 69 | set (GMOCK_LIBRARIES 70 | debug ${GMOCK_LIBRARIES_DEBUG} 71 | optimized ${GMOCK_LIBRARIES_RELEASE} 72 | ) 73 | set (GMOCK_MAIN_LIBRARIES 74 | debug ${GMOCK_MAIN_LIBRARIES_DEBUG} 75 | optimized ${GMOCK_MAIN_LIBRARIES_RELEASE} 76 | ) 77 | # message (STATUS "GMOCK_BOTH_LIBRARIES ARE ${GMOCK_BOTH_LIBRARIES}") 78 | else () 79 | find_library (GMOCK_LIBRARIES gmock ${GMOCK_BUILD}) 80 | find_library (GMOCK_MAIN_LIBRARIES gmock_main ${GMOCK_BUILD}) 81 | find_library (GTEST_LIBRARIES gtest ${GMOCK_BUILD}/gtest) 82 | find_library (GTEST_MAIN_LIBRARIES gtest_main ${GMOCK_BUILD}) 83 | endif () 84 | set (GMOCK_BOTH_LIBRARIES 85 | ${GMOCK_LIBRARIES} 86 | ${GMOCK_MAIN_LIBRARIES} 87 | ${GTEST_LIBRARIES} 88 | ${GTEST_MAIN_LIBRARIES} 89 | ) 90 | -------------------------------------------------------------------------------- /base_regression.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #cd bld 3 | #make -j5 4 | #cd .. 5 | mkdir -p tests/outputs 6 | ./test_use_base.sh 7 | ./regression_tester ./dcc_original -s -c; diff -wB tests/prev/ tests/outputs/ 8 | -------------------------------------------------------------------------------- /common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRC 2 | perfhlib.cpp 3 | perfhlib.h 4 | PatternCollector.h 5 | 6 | ) 7 | add_library(dcc_hash STATIC ${SRC}) 8 | -------------------------------------------------------------------------------- /common/PatternCollector.h: -------------------------------------------------------------------------------- 1 | #ifndef PATTERNCOLLECTOR 2 | #define PATTERNCOLLECTOR 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define SYMLEN 16 /* Number of chars in the symbol name, incl null */ 9 | #define PATLEN 23 /* Number of bytes in the pattern part */ 10 | 11 | struct HASHENTRY 12 | { 13 | char name[SYMLEN]; /* The symbol name */ 14 | uint8_t pat [PATLEN]; /* The pattern */ 15 | uint16_t offset; /* Offset (needed temporarily) */ 16 | }; 17 | 18 | struct PatternCollector { 19 | uint8_t buf[100], bufSave[7]; /* Temp buffer for reading the file */ 20 | uint16_t readShort(FILE *f) 21 | { 22 | uint8_t b1, b2; 23 | 24 | if (fread(&b1, 1, 1, f) != 1) 25 | { 26 | printf("Could not read\n"); 27 | exit(11); 28 | } 29 | if (fread(&b2, 1, 1, f) != 1) 30 | { 31 | printf("Could not read\n"); 32 | exit(11); 33 | } 34 | return (b2 << 8) + b1; 35 | } 36 | 37 | void grab(FILE *f,int n) 38 | { 39 | if (fread(buf, 1, n, f) != (size_t)n) 40 | { 41 | printf("Could not read\n"); 42 | exit(11); 43 | } 44 | } 45 | 46 | uint8_t readByte(FILE *f) 47 | { 48 | uint8_t b; 49 | 50 | if (fread(&b, 1, 1, f) != 1) 51 | { 52 | printf("Could not read\n"); 53 | exit(11); 54 | } 55 | return b; 56 | } 57 | 58 | uint16_t readWord(FILE *fl) 59 | { 60 | uint8_t b1, b2; 61 | 62 | b1 = readByte(fl); 63 | b2 = readByte(fl); 64 | 65 | return b1 + (b2 << 8); 66 | } 67 | 68 | /* Called by map(). Return the i+1th key in *pKeys */ 69 | uint8_t *getKey(int i) 70 | { 71 | return keys[i].pat; 72 | } 73 | /* Display key i */ 74 | void dispKey(int i) 75 | { 76 | printf("%s", keys[i].name); 77 | } 78 | std::vector keys; /* array of keys */ 79 | virtual int readSyms(FILE *f)=0; 80 | }; 81 | #endif // PATTERNCOLLECTOR 82 | 83 | -------------------------------------------------------------------------------- /common/perfhlib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | /** Perfect hashing function library. Contains functions to generate perfect 4 | hashing functions */ 5 | struct PatternCollector; 6 | struct PerfectHash { 7 | uint16_t *T1base; 8 | uint16_t *T2base; /* Pointers to start of T1, T2 */ 9 | short *g; /* g[] */ 10 | 11 | int NumEntry; /* Number of entries in the hash table (# keys) */ 12 | int EntryLen; /* Size (bytes) of each entry (size of keys) */ 13 | int SetSize; /* Size of the char set */ 14 | char SetMin; /* First char in the set */ 15 | int NumVert; /* c times NumEntry */ 16 | /** Set the parameters for the hash table */ 17 | void setHashParams(int _numEntry, int _entryLen, int _setSize, char _setMin, int _numVert); 18 | 19 | public: 20 | void map(PatternCollector * collector); /* Part 1 of creating the tables */ 21 | void hashCleanup(); /* Frees memory allocated by setHashParams() */ 22 | void assign(); /* Part 2 of creating the tables */ 23 | int hash(uint8_t *string); /* Hash the string to an int 0 .. NUMENTRY-1 */ 24 | const uint16_t *readT1(void) const { return T1base; } 25 | const uint16_t *readT2(void) const { return T2base; } 26 | const uint16_t *readG(void) const { return (uint16_t *)g; } 27 | uint16_t *readT1(void){ return T1base; } 28 | uint16_t *readT2(void){ return T2base; } 29 | uint16_t *readG(void) { return (uint16_t *)g; } 30 | private: 31 | void initGraph(); 32 | void addToGraph(int e, int v1, int v2); 33 | bool isCycle(); 34 | bool DFS(int parentE, int v); 35 | void traverse(int u); 36 | PatternCollector *m_collector; /* used to retrieve the keys */ 37 | 38 | }; 39 | -------------------------------------------------------------------------------- /covproc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | lcov -z -d bld/CMakeFiles/dcc_original.dir/src 3 | ./regression_tester.rb bld/dcc_original -a2 -m -s -c -V 2>stderr >stdout 4 | lcov -c -d bld/CMakeFiles/dcc_original.dir/src -o cover1.info 5 | lcov -e cover1.info *dcc_* -o cover2.info 6 | genhtml -o coverage -f --demangle-cpp cover2.info 7 | 8 | -------------------------------------------------------------------------------- /full_regression.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | makedir -p tests/outputs 3 | ./test_use_all.sh 4 | ./regression_tester ./dcc_original -s -c; diff -wB tests/prev/ tests/outputs/ 5 | -------------------------------------------------------------------------------- /include/BinaryImage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | struct PROG /* Loaded program image parameters */ 6 | { 7 | int16_t initCS=0; 8 | int16_t initIP=0; /* These are initial load values */ 9 | int16_t initSS=0; /* Probably not of great interest */ 10 | uint16_t initSP=0; 11 | bool fCOM=false; /* Flag set if COM program (else EXE)*/ 12 | int cReloc=0; /* No. of relocation table entries */ 13 | std::vector relocTable; /* Ptr. to relocation table */ 14 | uint8_t * map=nullptr; /* Memory bitmap ptr */ 15 | int cProcs=0; /* Number of procedures so far */ 16 | int offMain=0; /* The offset of the main() proc */ 17 | uint16_t segMain=0; /* The segment of the main() proc */ 18 | bool bSigs=false; /* True if signatures loaded */ 19 | int cbImage=0; /* Length of image in bytes */ 20 | uint8_t * Imagez=nullptr; /* Allocated by loader to hold entire program image */ 21 | int addressingMode=0; 22 | public: 23 | const uint8_t *image() const {return Imagez;} 24 | void displayLoadInfo(); 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /include/CallConvention.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ast.h" 3 | 4 | class QTextStream; 5 | 6 | struct CConv { 7 | enum Type { 8 | eUnknown=0, 9 | eCdecl, 10 | ePascal 11 | }; 12 | virtual void processHLI(Function *func, Expr *_exp, iICODE picode)=0; 13 | virtual void writeComments(QTextStream &)=0; 14 | static CConv * create(Type v); 15 | protected: 16 | 17 | }; 18 | 19 | struct C_CallingConvention : public CConv { 20 | virtual void processHLI(Function *func, Expr *_exp, iICODE picode); 21 | virtual void writeComments(QTextStream &); 22 | 23 | private: 24 | int processCArg(Function *callee, Function *pProc, ICODE *picode, size_t numArgs); 25 | }; 26 | struct Pascal_CallingConvention : public CConv { 27 | virtual void processHLI(Function *func, Expr *_exp, iICODE picode); 28 | virtual void writeComments(QTextStream &); 29 | }; 30 | struct Unknown_CallingConvention : public CConv { 31 | void processHLI(Function *func, Expr *_exp, iICODE picode) {} 32 | virtual void writeComments(QTextStream &); 33 | }; 34 | -------------------------------------------------------------------------------- /include/CallGraph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Procedure.h" 3 | /* CALL GRAPH NODE */ 4 | struct CALL_GRAPH 5 | { 6 | ilFunction proc; /* Pointer to procedure in pProcList */ 7 | std::vector outEdges; /* array of out edges */ 8 | public: 9 | void write(); 10 | CALL_GRAPH() 11 | { 12 | } 13 | public: 14 | void writeNodeCallGraph(int indIdx); 15 | bool insertCallGraph(ilFunction caller, ilFunction callee); 16 | bool insertCallGraph(Function *caller, ilFunction callee); 17 | void insertArc(ilFunction newProc); 18 | }; 19 | //extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */ 20 | -------------------------------------------------------------------------------- /include/DccFrontend.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | class Project; 4 | class DccFrontend : public QObject 5 | { 6 | Q_OBJECT 7 | void LoadImage(); 8 | void parse(Project &proj); 9 | std::string m_fname; 10 | public: 11 | explicit DccFrontend(QObject *parent = 0); 12 | bool FrontEnd(); /* frontend.c */ 13 | 14 | signals: 15 | 16 | public slots: 17 | }; 18 | -------------------------------------------------------------------------------- /include/IdentType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ast.h" 3 | #include "types.h" 4 | #include "machine_x86.h" 5 | struct GlobalVariable; 6 | struct AstIdent; 7 | struct IDENTTYPE 8 | { 9 | friend struct GlobalVariable; 10 | friend struct Constant; 11 | friend struct AstIdent; 12 | protected: 13 | condId idType; 14 | public: 15 | condId type() {return idType;} 16 | void type(condId t) {idType=t;} 17 | union _idNode { 18 | int localIdx; /* idx into localId, LOCAL_VAR */ 19 | int paramIdx; /* idx into args symtab, PARAMS */ 20 | uint32_t strIdx; /* idx into image, for STRING */ 21 | int longIdx; /* idx into LOCAL_ID table, LONG_VAR*/ 22 | struct { /* for OTHER; tmp struct */ 23 | eReg seg; /* segment */ 24 | eReg regi; /* index mode */ 25 | int16_t off; /* offset */ 26 | } other; 27 | } idNode; 28 | IDENTTYPE() : idType(UNDEF) 29 | {} 30 | }; 31 | -------------------------------------------------------------------------------- /include/StackFrame.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include "Enums.h" 4 | #include "symtab.h" 5 | 6 | struct STKFRAME : public SymbolTableCommon 7 | { 8 | //std::vector sym; 9 | //STKSYM * sym; /* Symbols */ 10 | int16_t m_minOff=0; /* Initial offset in stack frame*/ 11 | int16_t maxOff=0; /* Maximum offset in stack frame*/ 12 | int cb=0; /* Number of bytes in arguments */ 13 | int numArgs=0; /* No. of arguments in the table*/ 14 | 15 | void adjustForArgType(size_t numArg_, hlType actType_); 16 | size_t getLocVar(int off); 17 | public: 18 | void updateFrameOff(int16_t off, int size, uint16_t duFlag); 19 | }; 20 | -------------------------------------------------------------------------------- /include/boost_fwd.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * Project: dcc 3 | * File: boost_fwd.h 4 | * Purpose: Declare somoe of boost types to reduce header inclusion overhead. 5 | ****************************************************************************/ 6 | #pragma once 7 | 8 | namespace boost { 9 | template 10 | class iterator_range; 11 | } 12 | -------------------------------------------------------------------------------- /include/bundle.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * Project: dcc 3 | * File: bundle.h 4 | * Purpose: Module to handle the bundle type (array of pointers to strings). 5 | * (C) Cristina Cifuentes 6 | ****************************************************************************/ 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | class QIODevice; 14 | 15 | struct strTable 16 | { 17 | /* Returns the next available index into the table */ 18 | size_t nextIdx() {return entries.size();} 19 | public: 20 | void addLabelBundle(int idx, int label); 21 | std::vector entries; 22 | }; 23 | 24 | struct bundle 25 | { 26 | public: 27 | void appendCode(const char *format, ...); 28 | void appendCode(const QString &s); 29 | void appendDecl(const char *format, ...); 30 | void appendDecl(const QString &); 31 | void init() 32 | { 33 | decl.entries.clear(); 34 | code.entries.clear(); 35 | } 36 | strTable decl; /* Declarations */ 37 | strTable code; /* C code */ 38 | int current_indent; 39 | }; 40 | 41 | extern bundle cCode; 42 | #define lineSize 360 /* 3 lines in the mean time */ 43 | 44 | //void newBundle (bundle *procCode); 45 | void writeBundle (QIODevice & ios, bundle procCode); 46 | void freeBundle (bundle *procCode); 47 | 48 | -------------------------------------------------------------------------------- /include/dcc.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * dcc project general header 3 | * (C) Cristina Cifuentes, Mike van Emmerik 4 | ****************************************************************************/ 5 | #pragma once 6 | //TODO: Remove boolT 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "Enums.h" 14 | #include "types.h" 15 | #include "ast.h" 16 | #include "icode.h" 17 | #include "locident.h" 18 | #include "error.h" 19 | #include "graph.h" 20 | #include "bundle.h" 21 | #include "Procedure.h" 22 | #include "BasicBlock.h" 23 | class Project; 24 | /* CALL GRAPH NODE */ 25 | extern bundle cCode; /* Output C procedure's declaration and code */ 26 | 27 | /**** Global variables ****/ 28 | 29 | extern QString asm1_name, asm2_name; /* Assembler output filenames */ 30 | 31 | /** Command line option flags */ 32 | struct OPTION 33 | { 34 | bool verbose; 35 | bool VeryVerbose; 36 | bool asm1; /* Early disassembly listing */ 37 | bool asm2; /* Disassembly listing after restruct */ 38 | bool Map; 39 | bool Stats; 40 | bool Interact; /* Interactive mode */ 41 | bool Calls; /* Follow register indirect calls */ 42 | QString filename; /* The input filename */ 43 | uint32_t CustomEntryPoint; 44 | }; 45 | 46 | extern OPTION option; /* Command line options */ 47 | 48 | #include "BinaryImage.h" 49 | 50 | /* Memory map states */ 51 | enum eAreaType 52 | { 53 | BM_UNKNOWN = 0, /* Unscanned memory */ 54 | BM_DATA = 1, /* Data */ 55 | BM_CODE = 2, /* Code */ 56 | BM_IMPURE = 3 /* Used as Data and Code*/ 57 | }; 58 | 59 | /* Intermediate instructions statistics */ 60 | struct STATS 61 | { 62 | int numBBbef; /* number of basic blocks initially */ 63 | int numBBaft; /* number of basic blocks at the end */ 64 | int nOrder; /* n-th order */ 65 | int numLLIcode; /* number of low-level Icode instructions */ 66 | int numHLIcode; /* number of high-level Icode instructions */ 67 | int totalLL; /* total number of low-level Icode insts */ 68 | int totalHL; /* total number of high-level Icod insts */ 69 | }; 70 | 71 | extern STATS stats; /* Icode statistics */ 72 | 73 | 74 | /**** Global function prototypes ****/ 75 | 76 | void udm(); /* udm.c */ 77 | void freeCFG(BB * cfg); /* graph.c */ 78 | BB * newBB(BB *, int, int, uint8_t, int, Function *); /* graph.c */ 79 | void BackEnd(CALL_GRAPH *); /* backend.c */ 80 | extern char *cChar(uint8_t c); /* backend.c */ 81 | eErrorId scan(uint32_t ip, ICODE &p); /* scanner.c */ 82 | void parse (CALL_GRAPH * *); /* parser.c */ 83 | 84 | extern int strSize (const uint8_t *, char); /* parser.c */ 85 | //void disassem(int pass, Function * pProc); /* disassem.c */ 86 | void interactDis(Function *, int initIC); /* disassem.c */ 87 | bool JmpInst(llIcode opcode); /* idioms.c */ 88 | queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */ 89 | 90 | bool SetupLibCheck(void); /* chklib.c */ 91 | void CleanupLibCheck(void); /* chklib.c */ 92 | bool LibCheck(Function &p); /* chklib.c */ 93 | 94 | 95 | /* Exported functions from hlicode.c */ 96 | QString writeJcond(const HLTYPE &, Function *, int *); 97 | QString writeJcondInv(HLTYPE, Function *, int *); 98 | 99 | 100 | /* Exported funcions from locident.c */ 101 | bool checkLongEq(LONG_STKID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &atOffset); 102 | bool checkLongRegEq(LONGID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &); 103 | 104 | extern const char *indentStr(int level); 105 | -------------------------------------------------------------------------------- /include/dcc_interface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Procedure.h" 3 | 4 | #include 5 | #include 6 | 7 | class IXmlTarget; 8 | 9 | struct IDcc { 10 | static IDcc *get(); 11 | virtual void BaseInit()=0; 12 | virtual void Init(QObject *tgt)=0; 13 | virtual lFunction::iterator GetFirstFuncHandle()=0; 14 | virtual lFunction::iterator GetCurFuncHandle()=0; 15 | virtual void analysis_Once()=0; 16 | virtual void load(QString name)=0; // load and preprocess -> find entry point 17 | virtual void prtout_asm(IXmlTarget *,int level=0)=0; 18 | virtual void prtout_cpp(IXmlTarget *,int level=0)=0; 19 | virtual size_t getFuncCount()=0; 20 | virtual const lFunction &validFunctions() const =0; 21 | virtual void SetCurFunc_by_Name(QString )=0; 22 | virtual QDir installDir()=0; 23 | virtual QDir dataDir(QString kind)=0; 24 | }; 25 | -------------------------------------------------------------------------------- /include/disassem.h: -------------------------------------------------------------------------------- 1 | /* 2 | *************************************************************************** 3 | dcc project disassembler header 4 | (C) Mike van Emmerik 5 | *************************************************************************** 6 | */ 7 | #pragma once 8 | #include "bundle.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | struct LLInst; 15 | struct Function; 16 | struct Disassembler 17 | { 18 | protected: 19 | int pass; 20 | int g_lab; 21 | //bundle &cCode; 22 | QIODevice *m_disassembly_target; 23 | QTextStream m_fp; 24 | std::vector m_decls; 25 | std::vector m_code; 26 | 27 | public: 28 | Disassembler(int _p) : pass(_p) 29 | { 30 | g_lab=0; 31 | } 32 | public: 33 | void disassem(Function *ppProc); 34 | void disassem(Function *ppProc, int i); 35 | void dis1Line(LLInst &inst, int loc_ip, int pass); 36 | }; 37 | -------------------------------------------------------------------------------- /include/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | **************************************************************************** 4 | * Error codes 5 | * (C) Cristina Cifuentes 6 | *************************************************************************** 7 | */ 8 | #pragma once 9 | 10 | /* These definitions refer to errorMessage in error.c */ 11 | enum eErrorId 12 | { 13 | NO_ERR =0, 14 | USAGE, 15 | INVALID_ARG, 16 | INVALID_OPCODE, 17 | INVALID_386OP, 18 | FUNNY_SEGOVR, 19 | FUNNY_REP, 20 | CANNOT_OPEN, 21 | CANNOT_READ, 22 | MALLOC_FAILED, 23 | NEWEXE_FORMAT, 24 | 25 | NO_BB, 26 | INVALID_SYNTHETIC_BB, 27 | INVALID_INT_BB, 28 | IP_OUT_OF_RANGE, 29 | DEF_NOT_FOUND, 30 | JX_NOT_DEF, 31 | NOT_DEF_USE, 32 | REPEAT_FAIL, 33 | WHILE_FAIL 34 | }; 35 | 36 | 37 | void fatalError(eErrorId errId, ...); 38 | void reportError(eErrorId errId, ...); 39 | 40 | -------------------------------------------------------------------------------- /include/graph.h: -------------------------------------------------------------------------------- 1 | /* 2 | **************************************************************************** 3 | * CFG, BB and interval related definitions 4 | * ( C ) Cristina Cifuentes 5 | **************************************************************************** 6 | */ 7 | #pragma once 8 | #include 9 | #include 10 | 11 | struct Function; 12 | /* Types of basic block nodes */ 13 | /* Real basic blocks: type defined according to their out-edges */ 14 | 15 | enum eBBKind 16 | { 17 | ONE_BRANCH = 0, /* unconditional branch */ 18 | TWO_BRANCH = 1, /* conditional branch */ 19 | MULTI_BRANCH = 2, /* case branch */ 20 | FALL_NODE = 3, /* fall through */ 21 | RETURN_NODE = 4, /* procedure/program return */ 22 | CALL_NODE = 5, /* procedure call */ 23 | LOOP_NODE = 6, /* loop instruction */ 24 | REP_NODE = 7, /* repeat instruction */ 25 | INTERVAL_NODE = 8, /* contains interval list */ 26 | 27 | TERMINATE_NODE = 11, /* Exit to DOS */ 28 | NOWHERE_NODE = 12 /* No outedges going anywhere */ 29 | }; 30 | 31 | /* Depth-first traversal constants */ 32 | enum eDFS 33 | { 34 | DFS_NONE, 35 | DFS_DISP=1, /* Display graph pass */ 36 | DFS_MERGE=2, /* Merge nodes pass */ 37 | DFS_NUM=3, /* DFS numbering pass */ 38 | DFS_CASE=4, /* Case pass */ 39 | DFS_ALPHA=5, /* Alpha code generation*/ 40 | DFS_JMP=9 /* rmJMP pass - must be largest flag */ 41 | }; 42 | 43 | /* Control flow analysis constants */ 44 | enum eNodeHeaderType 45 | { 46 | NO_TYPE=0, /* node is not a loop header*/ 47 | WHILE_TYPE=1, /* node is a while header */ 48 | REPEAT_TYPE=2, /* node is a repeat header */ 49 | ENDLESS_TYPE=3 /* endless loop header */ 50 | }; 51 | 52 | /* Uninitialized values for certain fields */ 53 | #define NO_NODE MAX /* node has no associated node */ 54 | #define NO_DOM MAX /* node has no dominator */ 55 | #define UN_INIT MAX /* uninitialized variable */ 56 | 57 | enum eEdgeType { 58 | THEN = 0, /* then edge, always first */ 59 | ELSE = 1 /* else edge, always second */ 60 | }; 61 | 62 | 63 | /* Basic Block (BB) flags */ 64 | 65 | #define INVALID_BB 0x0001 /* BB is not valid any more */ 66 | #define IS_LATCH_NODE 0x0002 /* BB is the latching node of a loop */ 67 | 68 | struct BB; 69 | /* Interval structure */ 70 | using queue = std::list; 71 | 72 | struct interval 73 | { 74 | uint8_t numInt=0; /* # of the interval */ 75 | uint8_t numOutEdges=0; /* Number of out edges */ 76 | queue nodes; /* Nodes of the interval*/ 77 | queue::iterator currNode; /* Current node */ 78 | interval * next=0; /* Next interval */ 79 | BB * firstOfInt(); 80 | interval() : currNode(nodes.end()){ 81 | } 82 | void appendNodeInt(queue &pqH, BB *node); 83 | }; 84 | 85 | 86 | /* Derived Sequence structure */ 87 | struct derSeq_Entry 88 | { 89 | BB * Gi=nullptr; /* Graph pointer */ 90 | std::list m_intervals; 91 | interval * Ii=nullptr; /* Interval list of Gi */ 92 | ~derSeq_Entry(); 93 | public: 94 | void findIntervals(Function *c); 95 | }; 96 | class derSeq 97 | { 98 | public: 99 | void display(); 100 | std::list entries; 101 | }; 102 | void freeDerivedSeq(derSeq &derivedG); /* reducible.c */ 103 | 104 | -------------------------------------------------------------------------------- /include/idioms/arith_idioms.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "idiom.h" 3 | #include "icode.h" 4 | 5 | struct Idiom5 : public Idiom 6 | { 7 | protected: 8 | iICODE m_icodes[2]; 9 | public: 10 | virtual ~Idiom5() {} 11 | Idiom5(Function *f) : Idiom(f) 12 | { 13 | } 14 | uint8_t minimum_match_length() {return 2;} 15 | bool match(iICODE pIcode); 16 | int action(); 17 | }; 18 | 19 | struct Idiom6 : public Idiom 20 | { 21 | protected: 22 | iICODE m_icodes[2]; 23 | public: 24 | virtual ~Idiom6() {} 25 | Idiom6(Function *f) : Idiom(f) 26 | { 27 | } 28 | uint8_t minimum_match_length() {return 2;} 29 | bool match(iICODE pIcode); 30 | int action(); 31 | }; 32 | 33 | struct Idiom18 : public Idiom 34 | { 35 | protected: 36 | iICODE m_icodes[4]; 37 | bool m_is_dec; 38 | /* type of variable: 1 = reg-var, 2 = local */ 39 | int m_idiom_type; 40 | public: 41 | Idiom18(Function *f) : Idiom(f) 42 | { 43 | } 44 | uint8_t minimum_match_length() {return 4;} 45 | bool match(iICODE picode); 46 | int action(); 47 | }; 48 | 49 | struct Idiom19 : public Idiom 50 | { 51 | protected: 52 | iICODE m_icodes[2]; 53 | bool m_is_dec; 54 | public: 55 | Idiom19(Function *f) : Idiom(f) 56 | { 57 | } 58 | uint8_t minimum_match_length() {return 2;} 59 | bool match(iICODE picode); 60 | int action(); 61 | }; 62 | 63 | struct Idiom20 : public Idiom 64 | { 65 | protected: 66 | iICODE m_icodes[4]; 67 | condNodeType m_is_dec; 68 | public: 69 | Idiom20(Function *f) : Idiom(f) 70 | { 71 | } 72 | uint8_t minimum_match_length() {return 4;} 73 | bool match(iICODE picode); 74 | int action(); 75 | }; 76 | -------------------------------------------------------------------------------- /include/idioms/call_idioms.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "idiom.h" 3 | #include "icode.h" 4 | 5 | #include 6 | 7 | struct CallIdiom : public Idiom 8 | { 9 | protected: 10 | int m_param_count; 11 | public: 12 | virtual ~CallIdiom() {} 13 | CallIdiom(Function *f) : Idiom(f) 14 | { 15 | } 16 | 17 | }; 18 | 19 | struct Idiom3 : public CallIdiom 20 | { 21 | protected: 22 | iICODE m_icodes[2]; 23 | public: 24 | virtual ~Idiom3() {} 25 | Idiom3(Function *f) : CallIdiom(f) 26 | { 27 | } 28 | uint8_t minimum_match_length() {return 2;} 29 | bool match(iICODE pIcode); 30 | int action(); 31 | }; 32 | 33 | struct Idiom17 : public CallIdiom 34 | { 35 | protected: 36 | std::vector m_icodes; 37 | public: 38 | virtual ~Idiom17() {} 39 | Idiom17(Function *f) : CallIdiom(f) 40 | { 41 | } 42 | uint8_t minimum_match_length() {return 2;} 43 | bool match(iICODE pIcode); 44 | int action(); 45 | }; 46 | -------------------------------------------------------------------------------- /include/idioms/epilogue_idioms.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "idiom.h" 3 | #include "icode.h" 4 | 5 | #include 6 | 7 | struct EpilogIdiom : public Idiom 8 | { 9 | protected: 10 | std::deque m_icodes; // deque to push_front optional icodes from popStkVars 11 | void popStkVars (iICODE pIcode); 12 | public: 13 | virtual ~EpilogIdiom() {} 14 | EpilogIdiom(Function *f) : Idiom(f) 15 | { 16 | } 17 | 18 | }; 19 | struct Idiom2 : public EpilogIdiom 20 | { 21 | virtual ~Idiom2() {} 22 | Idiom2(Function *f) : EpilogIdiom(f) 23 | { 24 | } 25 | uint8_t minimum_match_length() {return 3;} 26 | bool match(iICODE pIcode); 27 | int action(); 28 | }; 29 | struct Idiom4 : public EpilogIdiom 30 | { 31 | protected: 32 | int m_param_count; 33 | public: 34 | virtual ~Idiom4() {} 35 | Idiom4(Function *f) : EpilogIdiom(f) 36 | { 37 | } 38 | uint8_t minimum_match_length() {return 1;} 39 | bool match(iICODE pIcode); 40 | int action(); 41 | }; 42 | -------------------------------------------------------------------------------- /include/idioms/idiom.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct ICODE; 7 | struct Function; 8 | 9 | using iICODE=std::list::iterator; 10 | 11 | struct Idiom 12 | { 13 | protected: 14 | Function *m_func; 15 | iICODE m_end; 16 | public: 17 | Idiom(Function *f); 18 | virtual uint8_t minimum_match_length()=0; 19 | virtual bool match(iICODE at)=0; 20 | virtual int action()=0; 21 | int operator ()(iICODE at) 22 | { 23 | if(match(at)) 24 | return action(); 25 | return 1; 26 | } 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /include/idioms/idiom1.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "idiom.h" 4 | #include 5 | 6 | struct Idiom1 : public Idiom 7 | { 8 | protected: 9 | std::vector m_icodes; 10 | int m_min_off; 11 | int checkStkVars (iICODE pIcode); 12 | public: 13 | Idiom1(Function *f) : Idiom(f) 14 | { 15 | } 16 | uint8_t minimum_match_length() {return 1;} 17 | bool match(iICODE picode); 18 | int action(); 19 | size_t match_length() {return m_icodes.size();} 20 | }; 21 | -------------------------------------------------------------------------------- /include/idioms/mov_idioms.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "idiom.h" 3 | #include "icode.h" 4 | 5 | struct Idiom14 : public Idiom 6 | { 7 | protected: 8 | iICODE m_icodes[2]; 9 | eReg m_regL; 10 | eReg m_regH; 11 | public: 12 | virtual ~Idiom14() {} 13 | Idiom14(Function *f) : Idiom(f),m_regL(rUNDEF),m_regH(rUNDEF) 14 | { 15 | } 16 | uint8_t minimum_match_length() {return 2;} 17 | bool match(iICODE pIcode); 18 | int action(); 19 | }; 20 | 21 | struct Idiom13 : public Idiom 22 | { 23 | protected: 24 | iICODE m_icodes[2]; 25 | eReg m_loaded_reg; 26 | public: 27 | virtual ~Idiom13() {} 28 | Idiom13(Function *f) : Idiom(f) 29 | { 30 | } 31 | uint8_t minimum_match_length() {return 2;} 32 | bool match(iICODE pIcode); 33 | int action(); 34 | }; 35 | -------------------------------------------------------------------------------- /include/idioms/neg_idioms.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "idiom.h" 3 | #include "icode.h" 4 | 5 | struct Idiom11 : public Idiom 6 | { 7 | protected: 8 | iICODE m_icodes[3]; 9 | public: 10 | virtual ~Idiom11() {} 11 | Idiom11(Function *f) : Idiom(f) 12 | { 13 | } 14 | uint8_t minimum_match_length() {return 3;} 15 | bool match(iICODE pIcode); 16 | int action(); 17 | }; 18 | 19 | struct Idiom16 : public Idiom 20 | { 21 | protected: 22 | iICODE m_icodes[3]; 23 | public: 24 | virtual ~Idiom16() {} 25 | Idiom16(Function *f) : Idiom(f) 26 | { 27 | } 28 | uint8_t minimum_match_length() {return 3;} 29 | bool match(iICODE pIcode); 30 | int action(); 31 | }; 32 | -------------------------------------------------------------------------------- /include/idioms/shift_idioms.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "idiom.h" 3 | #include "icode.h" 4 | 5 | struct Idiom8 : public Idiom 6 | { 7 | protected: 8 | iICODE m_icodes[2]; 9 | uint8_t m_loaded_reg; 10 | public: 11 | virtual ~Idiom8() {} 12 | Idiom8(Function *f) : Idiom(f) 13 | { 14 | } 15 | uint8_t minimum_match_length() {return 2;} 16 | bool match(iICODE pIcode); 17 | int action(); 18 | }; 19 | 20 | struct Idiom15 : public Idiom 21 | { 22 | protected: 23 | std::vector m_icodes; 24 | public: 25 | virtual ~Idiom15() {} 26 | Idiom15(Function *f) : Idiom(f) 27 | { 28 | } 29 | uint8_t minimum_match_length() {return 2;} 30 | bool match(iICODE pIcode); 31 | int action(); 32 | }; 33 | 34 | struct Idiom12 : public Idiom 35 | { 36 | protected: 37 | iICODE m_icodes[2]; 38 | uint8_t m_loaded_reg; 39 | public: 40 | virtual ~Idiom12() {} 41 | Idiom12(Function *f) : Idiom(f) 42 | { 43 | } 44 | uint8_t minimum_match_length() {return 2;} 45 | bool match(iICODE pIcode); 46 | int action(); 47 | }; 48 | 49 | 50 | struct Idiom9 : public Idiom 51 | { 52 | protected: 53 | iICODE m_icodes[2]; 54 | uint8_t m_loaded_reg; 55 | public: 56 | virtual ~Idiom9() {} 57 | Idiom9(Function *f) : Idiom(f) 58 | { 59 | } 60 | uint8_t minimum_match_length() {return 2;} 61 | bool match(iICODE pIcode); 62 | int action(); 63 | }; 64 | 65 | -------------------------------------------------------------------------------- /include/idioms/xor_idioms.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "idiom.h" 4 | #include "icode.h" 5 | #include 6 | 7 | struct Idiom21 : public Idiom 8 | { 9 | protected: 10 | iICODE m_icodes[2]; 11 | public: 12 | virtual ~Idiom21() {} 13 | Idiom21(Function *f) : Idiom(f) 14 | { 15 | } 16 | uint8_t minimum_match_length() {return 2;} 17 | bool match(iICODE pIcode); 18 | int action(); 19 | }; 20 | 21 | struct Idiom7 : public Idiom 22 | { 23 | protected: 24 | iICODE m_icode; 25 | public: 26 | virtual ~Idiom7() {} 27 | Idiom7(Function *f) : Idiom(f) 28 | { 29 | } 30 | uint8_t minimum_match_length() {return 1;} 31 | bool match(iICODE pIcode); 32 | int action(); 33 | }; 34 | struct Idiom10 : public Idiom 35 | { 36 | protected: 37 | iICODE m_icodes[2]; 38 | public: 39 | virtual ~Idiom10() {} 40 | Idiom10(Function *f) : Idiom(f) 41 | { 42 | } 43 | uint8_t minimum_match_length() {return 1;} 44 | bool match(iICODE pIcode); 45 | int action(); 46 | }; 47 | -------------------------------------------------------------------------------- /include/loader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class ILoader 4 | { 5 | 6 | }; 7 | 8 | class LoaderManger 9 | { 10 | 11 | }; 12 | -------------------------------------------------------------------------------- /include/machine_x86.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class QTextStream; 8 | 9 | struct LivenessSet; 10 | /* Machine registers */ 11 | enum eReg 12 | { 13 | rUNDEF = 0, 14 | rAX = 1, /* These are numbered relative to real 8086 */ 15 | rCX = 2, 16 | rDX = 3, 17 | rBX = 4, 18 | rSP = 5, 19 | rBP = 6, 20 | rSI = 7, 21 | rDI = 8, 22 | 23 | rES = 9, 24 | rCS = 10, 25 | rSS = 11, 26 | rDS = 12, 27 | 28 | rAL = 13, 29 | rCL = 14, 30 | rDL = 15, 31 | rBL = 16, 32 | rAH = 17, 33 | rCH = 18, 34 | rDH = 19, 35 | rBH = 20, 36 | 37 | rTMP= 21, /* temp register for DIV/IDIV/MOD */ 38 | rTMP2= 22, /* temp register for DIV/IDIV/MOD */ 39 | /* Indexed modes go from INDEXBASE to INDEXBASE+7 */ 40 | INDEX_BX_SI = 23, // "bx+si" 41 | INDEX_BX_DI, // "bx+di" 42 | INDEX_BP_SI, // "bp+si" 43 | INDEX_BP_DI, // "bp+di" 44 | INDEX_SI, // "si" 45 | INDEX_DI, // "di" 46 | INDEX_BP, // "bp" 47 | INDEX_BX, // "bx" 48 | LAST_REG 49 | }; 50 | class SourceMachine 51 | { 52 | public: 53 | virtual bool physicalReg(eReg r)=0; 54 | 55 | }; 56 | //class Machine_X86_Disassembler 57 | //{ 58 | // void formatRM(std::ostringstream &p, uint32_t flg, const LLOperand &pm); 59 | //}; 60 | class Machine_X86 : public SourceMachine 61 | { 62 | public: 63 | Machine_X86(); 64 | virtual ~Machine_X86() {} 65 | static const QString & regName(eReg r); 66 | static const QString & opcodeName(unsigned r); 67 | static const QString & floatOpName(unsigned r); 68 | bool physicalReg(eReg r); 69 | /* Writes the registers that are set in the bitvector */ 70 | //TODO: move this into Machine_X86 ? 71 | static void writeRegVector (QTextStream & ostr, const LivenessSet ®i); 72 | static eReg subRegH(eReg reg); 73 | static eReg subRegL(eReg reg); 74 | static bool isMemOff(eReg r); 75 | static bool isSubRegisterOf(eReg reg, eReg parent); 76 | static bool hasSubregisters(eReg reg); 77 | 78 | static bool isPartOfComposite(eReg reg); 79 | static eReg compositeParent(eReg reg); 80 | 81 | }; 82 | -------------------------------------------------------------------------------- /include/msvc_fixes.h: -------------------------------------------------------------------------------- 1 | #ifdef _MSC_VER 2 | #include 3 | #endif -------------------------------------------------------------------------------- /include/project.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "symtab.h" 9 | #include "BinaryImage.h" 10 | #include "Procedure.h" 11 | class QString; 12 | class SourceMachine; 13 | struct CALL_GRAPH; 14 | class IProject 15 | { 16 | virtual PROG *binary()=0; 17 | virtual const QString & project_name() const =0; 18 | virtual const QString & binary_path() const =0; 19 | }; 20 | class Project : public IProject 21 | { 22 | static Project *s_instance; 23 | QString m_fname; 24 | QString m_project_name; 25 | QString m_output_path; 26 | public: 27 | 28 | typedef std::list FunctionListType; 29 | typedef FunctionListType lFunction; 30 | typedef FunctionListType::iterator ilFunction; 31 | 32 | SYMTAB symtab; /* Global symbol table */ 33 | FunctionListType pProcList; 34 | CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */ 35 | PROG prog; /* Loaded program image parameters */ 36 | // no copies 37 | Project(const Project&) = delete; 38 | const Project & operator=(const Project & l) =delete; 39 | // only moves 40 | Project(); // default constructor, 41 | 42 | public: 43 | void create(const QString &a); 44 | bool load(); 45 | const QString & output_path() const {return m_output_path; } 46 | void set_output_path(const QString &path) { m_output_path=path; } 47 | const QString & project_name() const {return m_project_name;} 48 | const QString & binary_path() const {return m_fname;} 49 | QString output_name(const char *ext); 50 | ilFunction funcIter(Function *to_find); 51 | ilFunction findByEntry(uint32_t entry); 52 | ilFunction createFunction(FunctionType *f, const QString & name); 53 | bool valid(ilFunction iter); 54 | 55 | int getSymIdxByAddr(uint32_t adr); 56 | bool validSymIdx(size_t idx); 57 | size_t symbolSize(size_t idx); 58 | hlType symbolType(size_t idx); 59 | const QString & symbolName(size_t idx); 60 | const SYM & getSymByIdx(size_t idx) const; 61 | 62 | static Project * get(); 63 | PROG * binary() {return &prog;} 64 | SourceMachine *machine(); 65 | 66 | const FunctionListType &functions() const { return pProcList; } 67 | FunctionListType &functions() { return pProcList; } 68 | protected: 69 | void initialize(); 70 | void writeGlobSymTable(); 71 | }; 72 | //extern Project g_proj; 73 | -------------------------------------------------------------------------------- /include/scanner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* Scanner functions 3 | * (C) Cristina Cifuentes, Jeff Ledermann 4 | */ 5 | #include 6 | #include "error.h" 7 | 8 | #define REG(x) ((uint8_t)(x & 0x38) >> 3) 9 | //#define LH(p) ((int)((uint8_t *)(p))[0] + ((int)((uint8_t *)(p))[1] << 8)) 10 | struct ICODE; 11 | /* Extracts reg bits from middle of mod-reg-rm uint8_t */ 12 | extern eErrorId scan(uint32_t ip, ICODE &p); 13 | -------------------------------------------------------------------------------- /include/state.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * dcc project header 3 | * (C) Cristina Cifuentes, Mike van Emmerik 4 | ****************************************************************************/ 5 | #pragma once 6 | #include 7 | #include 8 | #include "machine_x86.h" 9 | 10 | /* STATE TABLE */ 11 | struct STATE 12 | { 13 | uint32_t IP=0; /* Offset into Image */ 14 | int16_t r[INDEX_BX_SI]; /* Value of segs and AX */ 15 | bool f[INDEX_BX_SI]; /* True if r[.] has a value */ 16 | struct 17 | { /* For case stmt indexed reg */ 18 | uint8_t regi=0; /* Last conditional jump */ 19 | int16_t immed=0; /* Contents of the previous register */ 20 | } JCond; 21 | 22 | void setState(uint16_t reg, int16_t value); 23 | void checkStartup(); 24 | bool isKnown(eReg v) {return f[v];} 25 | void kill(eReg v) { f[v]=false;} 26 | void setMemoryByte(uint32_t addr,uint8_t val) 27 | { 28 | //TODO: make this into a full scale value tracking class ! 29 | } 30 | 31 | STATE() 32 | { 33 | memset(r,0,sizeof(int16_t)*INDEX_BX_SI); //TODO: move this to machine_x86 34 | memset(f,0,sizeof(uint8_t)*INDEX_BX_SI); 35 | } 36 | }; 37 | 38 | 39 | -------------------------------------------------------------------------------- /include/symtab.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Symbol table prototypes 3 | * (C) Mike van Emmerik 4 | */ 5 | #pragma once 6 | #include "Enums.h" 7 | #include "types.h" 8 | #include "msvc_fixes.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | struct Expr; 16 | struct AstIdent; 17 | struct TypeContainer; 18 | class QTextStream; 19 | 20 | /* * * * * * * * * * * * * * * * * */ 21 | /* Symbol table structs and protos */ 22 | /* * * * * * * * * * * * * * * * * */ 23 | struct SymbolCommon 24 | { 25 | QString name; /* New name for this variable/symbol/argument */ 26 | int size; /* Size/maximum size */ 27 | hlType type; /* probable type */ 28 | eDuVal duVal; /* DEF, USE, VAL */ 29 | SymbolCommon(hlType t=TYPE_UNKNOWN) : size(0),type(t) 30 | {} 31 | }; 32 | struct SYM : public SymbolCommon 33 | { 34 | typedef uint32_t tLabel; 35 | SYM() : label(0),flg(0) 36 | { 37 | 38 | } 39 | uint32_t label; /* physical address (20 bit) */ 40 | uint32_t flg; /* SEG_IMMED, IMPURE, WORD_OFF */ 41 | }; 42 | /* STACK FRAME */ 43 | struct STKSYM : public SymbolCommon 44 | { 45 | typedef int16_t tLabel; 46 | Expr * actual=0; /* Expression tree of actual parameter */ 47 | AstIdent * regs=0; /* For register arguments only */ 48 | tLabel label=0; /* Immediate off from BP (+:args, -:params) */ 49 | uint8_t regOff=0; /* Offset is a register (e.g. SI, DI) */ 50 | bool hasMacro=false; /* This type needs a macro */ 51 | QString macro; /* Macro name */ 52 | bool invalid=false; /* Boolean: invalid entry in formal arg list*/ 53 | void setArgName(int i) 54 | { 55 | char buf[32]; 56 | sprintf (buf, "arg%d", i); 57 | name = buf; 58 | } 59 | STKSYM(hlType t=TYPE_UNKNOWN) : SymbolCommon(t) {} 60 | }; 61 | template 62 | class SymbolTableCommon 63 | { 64 | std::vector storage; 65 | public: 66 | typedef typename std::vector::iterator iterator; 67 | typedef typename std::vector::const_iterator const_iterator; 68 | 69 | iterator findByLabel(typename T::tLabel lab) 70 | { 71 | auto iter = std::find_if(storage.begin(),storage.end(), 72 | [lab](T &s)->bool {return s.label==lab;}); 73 | return iter; 74 | } 75 | const_iterator findByLabel(typename T::tLabel lab) const 76 | { 77 | auto iter = std::find_if(storage.begin(),storage.end(), 78 | [lab](const T &s)->bool {return s.label==lab;}); 79 | return iter; 80 | } 81 | const T& operator[](size_t idx) const { 82 | return storage[idx]; 83 | } 84 | T& operator[](size_t idx) { 85 | return storage[idx]; 86 | } 87 | 88 | void push_back(const T &entry) { 89 | storage.push_back(entry); 90 | } 91 | iterator begin() { return storage.begin(); } 92 | const_iterator begin() const { return storage.cbegin(); } 93 | iterator end() { return storage.end(); } 94 | const_iterator end() const { return storage.cend(); } 95 | 96 | T &back() { return storage.back(); } 97 | 98 | size_t size() const { return storage.size(); } 99 | 100 | bool empty() const { return storage.empty(); } 101 | 102 | }; 103 | /* SYMBOL TABLE */ 104 | class SYMTAB : public SymbolTableCommon 105 | { 106 | 107 | public: 108 | void updateSymType(uint32_t symbol, const TypeContainer &tc); 109 | SYM *updateGlobSym(uint32_t operand, int size, uint16_t duFlag, bool &inserted_new); 110 | }; 111 | struct Function; 112 | struct SYMTABLE 113 | { 114 | std::string pSymName; /* Ptr to symbolic name or comment */ 115 | uint32_t symOff; /* Symbol image offset */ 116 | Function *symProc; /* Procedure pointer */ 117 | SYMTABLE() : symOff(0),symProc(0) {} 118 | SYMTABLE(uint32_t _sym,Function *_proc) : symOff(_sym),symProc(_proc) 119 | {} 120 | bool operator == (const SYMTABLE &other) const 121 | { 122 | // does not yse pSymName, to ease finding by symOff/symProc combo 123 | // in map 124 | return (symOff==other.symOff) and symProc==(other.symProc); 125 | } 126 | }; 127 | 128 | enum tableType /* The table types */ 129 | { 130 | Label=0, /* The label table */ 131 | Comment /* The comment table */ 132 | }; 133 | constexpr int NUM_TABLE_TYPES = int(Comment)+1; /* Number of entries: must be last */ 134 | 135 | void createSymTables(); 136 | void destroySymTables(); 137 | bool readVal (QTextStream & symName, uint32_t symOff, Function *symProc); 138 | void selectTable(tableType); /* Select a particular table */ 139 | 140 | -------------------------------------------------------------------------------- /include/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | *************************************************************************** 3 | * dcc project general header 4 | * (C) Cristina Cifuentes, Mike van Emmerik 5 | *************************************************************************** 6 | */ 7 | #pragma once 8 | #include "Enums.h" 9 | #include "msvc_fixes.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | /**** Common definitions and macros ****/ 16 | #define MAX 0x7FFFFFFF 17 | 18 | /* Type definitions used in the program */ 19 | 20 | #define SYNTHESIZED_MIN 0x100000 /* Synthesized labs use bits 21..32 */ 21 | 22 | /* These are for C library signature detection */ 23 | #define SYMLEN 16 /* Length of proc symbols, incl null */ 24 | #define PATLEN 23 /* Length of proc patterns */ 25 | #define WILD 0xF4 /* The wild byte */ 26 | 27 | /* MACROS */ 28 | 29 | // Macro reads a LH word from the image regardless of host convention 30 | // Returns a 16 bit quantity, e.g. C000 is read into an Int as C000 31 | //#define LH(p) ((int16)((byte *)(p))[0] + ((int16)((byte *)(p))[1] << 8)) 32 | #define LH(p) ((uint16_t)((uint8_t *)(p))[0] + ((uint16_t)((uint8_t *)(p))[1] << 8)) 33 | 34 | 35 | /* Macro reads a LH word from the image regardless of host convention */ 36 | /* Returns a signed quantity, e.g. C000 is read into an Int as FFFFC000 */ 37 | #define LH_SIGNED(p) (((uint8_t *)(p))[0] + (((char *)(p))[1] << 8)) 38 | 39 | /* Macro tests bit b for type t in prog.map */ 40 | #define BITMAP(b, t) (prog.map[(b) >> 2] & ((t) << (((b) & 3) << 1))) 41 | 42 | /* Macro to convert a segment, offset definition into a 20 bit address */ 43 | #define opAdr(seg,off) ((seg << 4) + off) 44 | 45 | /* duVal FLAGS */ 46 | struct eDuVal 47 | { 48 | eDuVal() 49 | { 50 | def=use=val=0; 51 | } 52 | enum flgs 53 | { 54 | DEF=1, 55 | USE=2, 56 | VAL=4 57 | }; 58 | uint8_t def :1; //!< Variable was first defined than used 59 | uint8_t use :1; //!< Variable was first used than defined 60 | uint8_t val :1; /* Variable has an initial value. 2 cases: 61 | 1. When variable is used first (ie. global) 62 | 2. When a value is moved into the variable 63 | for the first time. 64 | */ 65 | void setFlags(uint16_t x) 66 | { 67 | def = x&DEF; 68 | use = x&USE; 69 | val = x&VAL; 70 | } 71 | bool isUSE_VAL() {return use and val;} //Use and Val 72 | }; 73 | static constexpr const char * hlTypes[13] = { 74 | "", 75 | "char", 76 | "unsigned char", 77 | "int", 78 | "unsigned int", 79 | "long", 80 | "unsigned long", 81 | "record", 82 | "int *", 83 | "char *", 84 | "", 85 | "float", 86 | "double" 87 | }; 88 | 89 | struct TypeContainer 90 | { 91 | hlType m_type; 92 | size_t m_size; 93 | TypeContainer(hlType t,size_t sz) : m_type(t),m_size(sz) 94 | { 95 | } 96 | static size_t typeSize(hlType t) 97 | { 98 | switch(t) 99 | { 100 | case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: 101 | return 2; 102 | case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: 103 | return 1; 104 | case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: 105 | return 4; 106 | case TYPE_FLOAT: 107 | return 4; 108 | default: 109 | return ~0; 110 | } 111 | return 0; 112 | } 113 | static hlType defaultTypeForSize(size_t x) 114 | { 115 | /* Type of the symbol according to the number of bytes it uses */ 116 | static hlType cbType[] = {TYPE_UNKNOWN, TYPE_BYTE_UNSIGN, TYPE_WORD_SIGN, 117 | TYPE_UNKNOWN, TYPE_LONG_SIGN}; 118 | 119 | assert(x < sizeof(cbType)/sizeof(hlType)); 120 | return cbType[x]; 121 | } 122 | static constexpr const char *typeName(hlType t) 123 | { 124 | return hlTypes[t]; 125 | } 126 | }; 127 | -------------------------------------------------------------------------------- /prototypes/dcclibs.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/prototypes/dcclibs.dat -------------------------------------------------------------------------------- /regression_tester.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | print("Regression tester 0.0.1\n") 4 | def path_local(from) 5 | 6 | return from #from.gsub('/','//') 7 | from.gsub('/','\\\\') 8 | end 9 | TESTS_DIR="./tests" 10 | def perform_test(exepath,filepath,outname,args) 11 | output_path=path_local(TESTS_DIR+"/outputs/"+outname) 12 | exepath=path_local(exepath) 13 | output_path=path_local(output_path) 14 | filepath=path_local(filepath) 15 | joined_args = args.join(' ') 16 | printf("calling:" + "#{exepath} -a1 #{joined_args} -o#{output_path}.a1 #{filepath}\n") 17 | STDERR << "Errors for : #{filepath}\n" 18 | result = `#{exepath} -a 1 -o#{output_path}.a1 #{filepath}` 19 | result = `#{exepath} -a 2 #{joined_args} -o#{output_path}.a2 #{filepath}` 20 | result = `#{exepath} #{joined_args} -o#{output_path} #{filepath}` 21 | puts result 22 | p $? 23 | end 24 | `rm -rf #{TESTS_DIR}/outputs/*.*` 25 | #exit(1) 26 | Dir.open(TESTS_DIR+"/inputs").each() {|f| 27 | next if f=="." or f==".." 28 | perform_test(".//"+ARGV[0],TESTS_DIR+"/inputs/"+f,f,ARGV[1..-1]) 29 | } 30 | Dir.open(TESTS_DIR+"/inputs").each() {|f| 31 | next if f=="." or f==".." 32 | FileUtils.mv(TESTS_DIR+"/inputs/"+f,TESTS_DIR+"/outputs/"+f) if f.end_with?(".b") 33 | } 34 | puts "**************************************\n" -------------------------------------------------------------------------------- /sigs/dccb2c.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dccb2c.sig -------------------------------------------------------------------------------- /sigs/dccb2l.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dccb2l.sig -------------------------------------------------------------------------------- /sigs/dccb2s.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dccb2s.sig -------------------------------------------------------------------------------- /sigs/dccb3c.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dccb3c.sig -------------------------------------------------------------------------------- /sigs/dccb3m.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dccb3m.sig -------------------------------------------------------------------------------- /sigs/dccm5l.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dccm5l.sig -------------------------------------------------------------------------------- /sigs/dccm5s.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dccm5s.sig -------------------------------------------------------------------------------- /sigs/dccm8l.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dccm8l.sig -------------------------------------------------------------------------------- /sigs/dccm8m.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dccm8m.sig -------------------------------------------------------------------------------- /sigs/dccm8s.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dccm8s.sig -------------------------------------------------------------------------------- /sigs/dcct3p.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dcct3p.sig -------------------------------------------------------------------------------- /sigs/dcct4p.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dcct4p.sig -------------------------------------------------------------------------------- /sigs/dcct5p.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/sigs/dcct5p.sig -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(dcc_test_SOURCES 2 | tests/comwrite.cpp 3 | tests/project.cpp 4 | tests/loader.cpp 5 | 6 | ) 7 | include_directories(${GMOCK_INCLUDE_DIRS} ${GMOCK_ROOT}/gtest/include) 8 | add_executable(tester ${dcc_test_SOURCES}) 9 | ADD_DEPENDENCIES(tester dcc_lib) 10 | 11 | target_link_libraries(tester dcc_lib disasm_s 12 | ${GMOCK_BOTH_LIBRARIES} ${REQ_LLVM_LIBRARIES}) 13 | add_test(dcc-tests tester) 14 | -------------------------------------------------------------------------------- /src/CallConvention.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CallConvention.h" 4 | #include 5 | 6 | CConv *CConv::create(Type v) 7 | { 8 | static C_CallingConvention *c_call = nullptr; 9 | static Pascal_CallingConvention *p_call = nullptr; 10 | static Unknown_CallingConvention *u_call= nullptr; 11 | if(nullptr==c_call) 12 | c_call = new C_CallingConvention; 13 | if(nullptr==p_call) 14 | p_call = new Pascal_CallingConvention; 15 | if(nullptr==u_call) 16 | u_call = new Unknown_CallingConvention; 17 | switch(v) { 18 | case eUnknown: return u_call; 19 | case eCdecl: return c_call; 20 | case ePascal: return p_call; 21 | } 22 | assert(false); 23 | return nullptr; 24 | } 25 | 26 | void C_CallingConvention::writeComments(QTextStream & ostr) 27 | { 28 | ostr << " * C calling convention.\n"; 29 | } 30 | void Pascal_CallingConvention::writeComments(QTextStream & ostr) 31 | { 32 | ostr << " * Pascal calling convention.\n"; 33 | } 34 | void Unknown_CallingConvention::writeComments(QTextStream & ostr) 35 | { 36 | ostr << " * Unknown calling convention.\n"; 37 | } 38 | -------------------------------------------------------------------------------- /src/Procedure.cpp: -------------------------------------------------------------------------------- 1 | #include "Procedure.h" 2 | 3 | #include "msvc_fixes.h" 4 | #include "project.h" 5 | #include "scanner.h" 6 | 7 | //FunctionType *Function::getFunctionType() const 8 | //{ 9 | // return &m_type; 10 | //} 11 | 12 | /* Does some heuristic pruning. Looks for ptrs. into the table 13 | * and for addresses that don't appear to point to valid code. 14 | */ 15 | void JumpTable::pruneEntries(uint16_t cs) 16 | { 17 | PROG *prg(Project::get()->binary()); 18 | for (uint32_t i = start; i < finish; i += 2) 19 | { 20 | uint32_t target = cs + LH(&prg->image()[i]); 21 | if (target < finish and target >= start) 22 | finish = target; 23 | else if (target >= (uint32_t)prg->cbImage) 24 | finish = i; 25 | } 26 | ICODE _Icode; // used as scan input 27 | for (uint32_t i = start; i < finish; i += 2) 28 | { 29 | uint32_t target = cs + LH(&prg->image()[i]); 30 | /* Be wary of 00 00 as code - it's probably data */ 31 | if (not (prg->image()[target] or prg->image()[target+1]) or scan(target, _Icode)) 32 | finish = i; 33 | } 34 | 35 | } 36 | 37 | 38 | void Function::callingConv(CConv::Type v) { 39 | m_call_conv=CConv::create(v); 40 | } 41 | -------------------------------------------------------------------------------- /src/RegisterNode.cpp: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "msvc_fixes.h" 3 | #include "ast.h" 4 | #include "bundle.h" 5 | #include "machine_x86.h" 6 | #include "project.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | using namespace boost::adaptors; 18 | RegisterNode::RegisterNode(const LLOperand &op, LOCAL_ID *locsym) 19 | { 20 | m_syms = locsym; 21 | ident.type(REGISTER); 22 | hlType type_sel; 23 | regType reg_type; 24 | if (op.byteWidth()==1) 25 | { 26 | type_sel = TYPE_BYTE_SIGN; 27 | reg_type = BYTE_REG; 28 | } 29 | else /* uint16_t */ 30 | { 31 | type_sel = TYPE_WORD_SIGN; 32 | reg_type = WORD_REG; 33 | } 34 | regiIdx = locsym->newByteWordReg(type_sel, op.regi); 35 | regiType = reg_type; 36 | } 37 | 38 | //RegisterNode::RegisterNode(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym) 39 | //{ 40 | // ident.type(REGISTER); 41 | // hlType type_sel; 42 | // regType reg_type; 43 | // if ((icodeFlg & B) or (icodeFlg & SRC_B)) 44 | // { 45 | // type_sel = TYPE_BYTE_SIGN; 46 | // reg_type = BYTE_REG; 47 | // } 48 | // else /* uint16_t */ 49 | // { 50 | // type_sel = TYPE_WORD_SIGN; 51 | // reg_type = WORD_REG; 52 | // } 53 | // regiIdx = locsym->newByteWordReg(type_sel, regi); 54 | // regiType = reg_type; 55 | //} 56 | 57 | QString RegisterNode::walkCondExpr(Function *pProc, int *numLoc) const 58 | { 59 | QString codeOut; 60 | QString o; 61 | 62 | assert(&pProc->localId==m_syms); 63 | ID *id = &pProc->localId.id_arr[regiIdx]; 64 | if (id->name[0] == '\0') /* no name */ 65 | { 66 | id->setLocalName(++(*numLoc)); 67 | codeOut += QString("%1 %2; ").arg(TypeContainer::typeName(id->type),id->name); 68 | codeOut += QString("/* %1 */\n").arg(Machine_X86::regName(id->id.regi)); 69 | } 70 | if (id->hasMacro) 71 | o += QString("%1(%2)").arg(id->macro,id->name); 72 | else 73 | o += id->name; 74 | 75 | cCode.appendDecl(codeOut); 76 | return o; 77 | } 78 | 79 | int RegisterNode::hlTypeSize(Function *) const 80 | { 81 | if (regiType == BYTE_REG) 82 | return 1; 83 | 84 | return 2; 85 | } 86 | 87 | hlType RegisterNode::expType(Function *) const 88 | { 89 | if (regiType == BYTE_REG) 90 | return TYPE_BYTE_SIGN; 91 | 92 | return TYPE_WORD_SIGN; 93 | } 94 | 95 | Expr *RegisterNode::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym) 96 | { 97 | assert(locsym==m_syms); 98 | eReg treeReg = locsym->id_arr[regiIdx].id.regi; 99 | if (treeReg == regi) /* uint16_t reg */ 100 | { 101 | return _expr; 102 | } 103 | else if(Machine_X86::isSubRegisterOf(treeReg,regi)) /* uint16_t/uint8_t reg */ 104 | { 105 | return _expr; 106 | } 107 | return nullptr; 108 | } 109 | bool RegisterNode::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId) 110 | { 111 | uint8_t regi = locId.id_arr[regiIdx].id.regi; 112 | range_to_check.advance_begin(1); 113 | auto all_valid_and_high_level_after_start = range_to_check | filtered(ICODE::select_valid_high_level); 114 | for (ICODE &i : all_valid_and_high_level_after_start) 115 | { 116 | if (i.du.def.testRegAndSubregs(regi)) 117 | { 118 | return false; 119 | } 120 | } 121 | 122 | return all_valid_and_high_level_after_start.end().base() != lastBBinst; 123 | } 124 | -------------------------------------------------------------------------------- /src/bundle.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * File: bundle.c 3 | * Module that handles the bundle type (array of pointers to strings). 4 | * (C) Cristina Cifuentes 5 | ****************************************************************************/ 6 | 7 | #include "dcc.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #define deltaProcLines 20 15 | 16 | using namespace std; 17 | /* Allocates memory for a new bundle and initializes it to zero. */ 18 | 19 | 20 | /* Adds the given label to the start of the line strTab[idx]. The first 21 | * tab is removed and replaced by this label */ 22 | void strTable::addLabelBundle (int idx, int label) 23 | { 24 | QString &processedLine(entries.at(idx)); 25 | QString s = QString("l%1: ").arg(label); 26 | if(processedLine.size()<4) 27 | processedLine = s; 28 | else 29 | processedLine = s+processedLine.mid(4); 30 | } 31 | 32 | 33 | /* Writes the contents of the string table on the file fp. */ 34 | static void writeStrTab (QIODevice &ios, strTable &strTab) 35 | { 36 | for (const QString & entr : strTab.entries) 37 | ios.write(entr.toLatin1()); 38 | } 39 | 40 | 41 | /* Writes the contents of the bundle (procedure code and declaration) to 42 | * a file. */ 43 | void writeBundle (QIODevice &ios, bundle procCode) 44 | { 45 | writeStrTab (ios, procCode.decl); 46 | writeStrTab (ios, procCode.code); 47 | } 48 | 49 | 50 | /* Frees the storage allocated by the string table. */ 51 | static void freeStrTab (strTable &strTab) 52 | { 53 | strTab.entries.clear(); 54 | } 55 | 56 | 57 | /* Deallocates the space taken by the bundle procCode */ 58 | void freeBundle (bundle *procCode) 59 | { 60 | freeStrTab (procCode->decl); 61 | freeStrTab (procCode->code); 62 | } 63 | 64 | void bundle::appendCode(const char *format,...) 65 | { 66 | va_list args; 67 | char buf[lineSize]={0}; 68 | va_start (args, format); 69 | vsprintf (buf, format, args); 70 | code.entries.push_back(buf); 71 | va_end (args); 72 | } 73 | void bundle::appendCode(const QString & s) 74 | { 75 | code.entries.push_back(s); 76 | } 77 | 78 | void bundle::appendDecl(const char *format,...) 79 | { 80 | va_list args; 81 | char buf[lineSize]={0}; 82 | va_start (args, format); 83 | vsprintf (buf, format, args); 84 | decl.entries.push_back(buf); 85 | va_end (args); 86 | } 87 | 88 | void bundle::appendDecl(const QString &v) 89 | { 90 | decl.entries.push_back(v); 91 | } 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/dcc_interface.cpp: -------------------------------------------------------------------------------- 1 | #include "dcc_interface.h" 2 | #include "dcc.h" 3 | #include "project.h" 4 | struct DccImpl : public IDcc { 5 | ilFunction m_current_func; 6 | // IDcc interface 7 | public: 8 | void BaseInit() override 9 | { 10 | m_current_func = Project::get()->functions().end(); 11 | } 12 | void Init(QObject *tgt) override 13 | { 14 | } 15 | ilFunction GetFirstFuncHandle() override 16 | { 17 | return Project::get()->functions().begin(); 18 | } 19 | ilFunction GetCurFuncHandle() override 20 | { 21 | return m_current_func; 22 | } 23 | void analysis_Once() override 24 | { 25 | } 26 | void load(QString name) override 27 | { 28 | option.filename = name; 29 | Project::get()->create(name); 30 | } 31 | void prtout_asm(IXmlTarget *, int level) override 32 | { 33 | } 34 | void prtout_cpp(IXmlTarget *, int level) override 35 | { 36 | } 37 | size_t getFuncCount() override 38 | { 39 | return Project::get()->functions().size(); 40 | } 41 | const lFunction &validFunctions() const override 42 | { 43 | return Project::get()->functions(); 44 | } 45 | void SetCurFunc_by_Name(QString v) override 46 | { 47 | lFunction & funcs(Project::get()->functions()); 48 | for(auto iter=funcs.begin(),fin=funcs.end(); iter!=fin; ++iter) { 49 | if(iter->name==v) { 50 | m_current_func = iter; 51 | return; 52 | } 53 | } 54 | } 55 | QDir installDir() override { 56 | return QDir("."); 57 | } 58 | QDir dataDir(QString kind) override { // return directory containing decompilation helper data -> signatures/includes/etc. 59 | QDir res(installDir()); 60 | res.cd(kind); 61 | return res; 62 | } 63 | }; 64 | 65 | IDcc* IDcc::get() { 66 | static IDcc *v=nullptr; 67 | if(nullptr == v) 68 | v = new DccImpl; 69 | return v; 70 | } 71 | -------------------------------------------------------------------------------- /src/error.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * dcc project error messages 3 | * (C) Cristina Cifuentes 4 | ***************************************************************************/ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "dcc.h" 13 | 14 | static const std::map errorMessage = 15 | { 16 | {INVALID_ARG ,"Invalid option -%c\n"}, 17 | {INVALID_OPCODE ,"Invalid instruction %02X at location %06lX\n"}, 18 | {INVALID_386OP ,"Don't understand 80386 instruction %02X at location %06lX\n"}, 19 | {FUNNY_SEGOVR ,"Segment override with no memory operand at location %06lX\n"}, 20 | {FUNNY_REP ,"REP prefix without a string instruction at location %06lX\n"}, 21 | {CANNOT_OPEN ,"Cannot open %s\n"}, 22 | {CANNOT_READ ,"Error while reading %s\n"}, 23 | {MALLOC_FAILED ,"malloc of %ld bytes failed\n"}, 24 | {NEWEXE_FORMAT ,"Don't understand new EXE format\n"}, 25 | {NO_BB ,"Failed to find a BB for jump to %ld in proc %s\n"}, 26 | {INVALID_SYNTHETIC_BB,"Basic Block is a synthetic jump\n"}, 27 | {INVALID_INT_BB ,"Failed to find a BB for interval\n"}, 28 | {IP_OUT_OF_RANGE ,"Instruction at location %06lX goes beyond loaded image\n"}, 29 | {DEF_NOT_FOUND ,"Definition not found for condition code usage at opcode %d\n"}, 30 | {JX_NOT_DEF ,"JX use, definition not supported at opcode #%d\n"}, 31 | {NOT_DEF_USE ,"%x: Def - use not supported. Def op = %d, use op = %d.\n"}, 32 | {REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"}, 33 | {WHILE_FAIL ,"Failed to construct while() condition.\n"}, 34 | }; 35 | 36 | /**************************************************************************** 37 | fatalError: displays error message and exits the program. 38 | ****************************************************************************/ 39 | void fatalError(eErrorId errId, ...) 40 | { 41 | va_list args; 42 | //#ifdef __UNIX__ /* ultrix */ 43 | #if 0 44 | int errId; 45 | 46 | va_start(args); 47 | errId = va_arg(args, int); 48 | #else 49 | va_start(args, errId); 50 | #endif 51 | 52 | if (errId == USAGE) 53 | fprintf(stderr,"Usage: dcc [-a1a2cmpsvVi][-o asmfile] DOS_executable\n"); 54 | else { 55 | auto msg_iter = errorMessage.find(errId); 56 | assert(msg_iter!=errorMessage.end()); 57 | fprintf(stderr, "dcc: "); 58 | vfprintf(stderr, msg_iter->second.c_str(), args); 59 | } 60 | va_end(args); 61 | exit((int)errId); 62 | } 63 | 64 | 65 | /**************************************************************************** 66 | reportError: reports the warning/error and continues with the program. 67 | ****************************************************************************/ 68 | void reportError(eErrorId errId, ...) 69 | { 70 | va_list args; 71 | //#ifdef __UNIX__ /* ultrix */ 72 | #if 0 73 | int errId; 74 | 75 | va_start(args); 76 | errId = va_arg(args, int); 77 | #else /* msdos or windows*/ 78 | va_start(args, errId); 79 | #endif 80 | fprintf(stderr, "dcc: "); 81 | auto msg_iter = errorMessage.find(errId); 82 | assert(msg_iter!=errorMessage.end()); 83 | vfprintf(stderr, msg_iter->second.c_str(), args); 84 | va_end(args); 85 | } 86 | -------------------------------------------------------------------------------- /src/hltype.cpp: -------------------------------------------------------------------------------- 1 | #include "icode.h" 2 | #include "ast.h" 3 | 4 | void HLTYPE::replaceExpr(Expr *e) 5 | { 6 | assert(e); 7 | delete exp.v; 8 | exp.v=e; 9 | } 10 | 11 | 12 | HlTypeSupport *HLTYPE::get() 13 | { 14 | switch(opcode) 15 | { 16 | case HLI_ASSIGN: return &asgn; 17 | case HLI_RET: 18 | case HLI_POP: 19 | case HLI_JCOND: 20 | case HLI_PUSH: return &exp; 21 | case HLI_CALL: return &call; 22 | default: 23 | return nullptr; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/icode.cpp: -------------------------------------------------------------------------------- 1 | // Object oriented icode code for dcc 2 | // (C) 1997 Mike Van Emmerik 3 | #include "icode.h" 4 | 5 | #include "ast.h" // Some icode types depend on these 6 | #include "dcc.h" 7 | #include "msvc_fixes.h" 8 | #include "types.h" // Common types like uint8_t, etc 9 | 10 | #include 11 | 12 | ICODE::TypeFilter ICODE::select_high_level; 13 | ICODE::TypeAndValidFilter ICODE::select_valid_high_level; 14 | CIcodeRec::CIcodeRec() 15 | { 16 | } 17 | 18 | /* Copies the icode that is pointed to by pIcode to the icode array. 19 | * If there is need to allocate extra memory, it is done so, and 20 | * the alloc variable is adjusted. */ 21 | ICODE * CIcodeRec::addIcode(ICODE *pIcode) 22 | { 23 | entries.push_back(*pIcode); 24 | entries.back().loc_ip = entries.size()-1; 25 | return &entries.back(); 26 | } 27 | 28 | void CIcodeRec::SetInBB(rCODE &rang, BB *pnewBB) 29 | { 30 | for(ICODE &ic : rang) 31 | ic.setParent(pnewBB); 32 | } 33 | 34 | /* labelSrchRepl - Searches the icodes for instruction with label = target, and 35 | replaces *pIndex with an icode index */ 36 | bool CIcodeRec::labelSrch(uint32_t target, uint32_t &pIndex) 37 | { 38 | iICODE location=labelSrch(target); 39 | if(entries.end()==location) 40 | return false; 41 | pIndex=location->loc_ip; 42 | return true; 43 | } 44 | 45 | bool CIcodeRec::alreadyDecoded(uint32_t target) 46 | { 47 | iICODE location=labelSrch(target); 48 | return location!=entries.end(); 49 | } 50 | CIcodeRec::iterator CIcodeRec::labelSrch(uint32_t target) 51 | { 52 | return find_if(entries.begin(),entries.end(),[target](ICODE &l) -> bool { 53 | return l.ll()->label==target; 54 | }); 55 | } 56 | ICODE * CIcodeRec::GetIcode(size_t ip) 57 | { 58 | assert(ip=rAX) and (regi<=rTMP); 92 | } 93 | void LLOperand::addProcInformation(int param_count, CConv::Type call_conv) 94 | { 95 | proc.proc->cbParam = (int16_t)param_count; 96 | proc.cb = param_count; 97 | proc.proc->callingConv(call_conv); 98 | } 99 | void HLTYPE::setCall(Function *proc) 100 | { 101 | opcode = HLI_CALL; 102 | call.proc = proc; 103 | call.args = new STKFRAME; 104 | } 105 | bool AssignType::removeRegFromLong(eReg regi, LOCAL_ID *locId) 106 | { 107 | m_lhs=lhs()->performLongRemoval(regi,locId); 108 | return true; 109 | } 110 | void AssignType::lhs(Expr *l) 111 | { 112 | assert(dynamic_cast(l)); 113 | m_lhs=l; 114 | } 115 | 116 | 117 | LivenessSet &LivenessSet::operator&=(const LivenessSet &other) 118 | { 119 | std::set res; 120 | std::set_intersection(registers.begin(),registers.end(), 121 | other.registers.begin(),other.registers.end(), 122 | std::inserter(res, res.end())); 123 | registers = res; 124 | return *this; 125 | } 126 | 127 | LivenessSet &LivenessSet::operator-=(const LivenessSet &other) 128 | { 129 | std::set res; 130 | std::set_difference(registers.begin(),registers.end(), 131 | other.registers.begin(),other.registers.end(), 132 | std::inserter(res, res.end())); 133 | registers = res; 134 | return *this; 135 | } 136 | -------------------------------------------------------------------------------- /src/idioms/call_idioms.cpp: -------------------------------------------------------------------------------- 1 | #include "call_idioms.h" 2 | 3 | #include "dcc.h" 4 | #include "msvc_fixes.h" 5 | 6 | using namespace std; 7 | /***************************************************************************** 8 | * idiom3 - C calling convention. 9 | * CALL(F) proc_X 10 | * ADD SP, immed 11 | * Eg: CALL proc_X 12 | * ADD SP, 6 13 | * => pProc->cbParam = immed 14 | * Special case: when the call is at the end of the procedure, 15 | * sometimes the stack gets restored by a MOV sp, bp. 16 | * Need to flag the procedure in these cases. 17 | * Used by compilers to restore the stack when invoking a procedure using 18 | * the C calling convention. 19 | ****************************************************************************/ 20 | bool Idiom3::match(iICODE picode) 21 | { 22 | if(distance(picode,m_end)<2) 23 | return false; 24 | m_param_count=0; 25 | /* Match ADD SP, immed */ 26 | for(auto & tgt : m_icodes){ 27 | tgt = picode++; 28 | } 29 | if ( m_icodes[1]->ll()->testFlags(I) and m_icodes[1]->ll()->match(iADD,rSP)) 30 | { 31 | m_param_count = m_icodes[1]->ll()->src().getImm2(); 32 | return true; 33 | } 34 | else if (m_icodes[1]->ll()->match(iMOV,rSP,rBP)) 35 | { 36 | m_icodes[0]->ll()->setFlags(REST_STK); 37 | return true; 38 | } 39 | return false; 40 | } 41 | int Idiom3::action() 42 | { 43 | if (m_icodes[0]->ll()->testFlags(I) ) 44 | { 45 | m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::eCdecl); 46 | } 47 | else 48 | { 49 | printf("Indirect call at idiom3\n"); 50 | } 51 | m_icodes[1]->invalidate(); 52 | return 2; 53 | } 54 | 55 | 56 | /***************************************************************************** 57 | * idiom 17 - C calling convention. 58 | * CALL(F) xxxx 59 | * POP reg 60 | * [POP reg] reg in {AX, BX, CX, DX} 61 | * Eg: CALL proc_X 62 | * POP cx 63 | * POP cx (4 bytes of arguments) 64 | * => pProc->cbParam = # pops * 2 65 | * Found in Turbo C when restoring the stack for a procedure that uses the 66 | * C calling convention. Used to restore the stack of 2 or 4 bytes args. 67 | ****************************************************************************/ 68 | bool Idiom17::match(iICODE picode) 69 | { 70 | if(distance(picode,m_end)<2) 71 | return false; 72 | m_param_count=0; /* Count on # pops */ 73 | m_icodes.clear(); 74 | 75 | /* Match ADD SP, immed */ 76 | for(int i=0; i<2; ++i) 77 | m_icodes.push_back(picode++); 78 | uint8_t regi; 79 | 80 | /* Match POP reg */ 81 | if (m_icodes[1]->ll()->match(iPOP)) 82 | { 83 | int i=0; 84 | regi = m_icodes[1]->ll()->m_dst.regi; 85 | if ((regi >= rAX) and (regi <= rBX)) 86 | i++; 87 | 88 | while (picode != m_end and picode->ll()->match(iPOP)) 89 | { 90 | if (picode->ll()->m_dst.regi != regi) 91 | break; 92 | i++; 93 | m_icodes.push_back(picode++); 94 | } 95 | m_param_count = i*2; 96 | } 97 | return m_param_count!=0; 98 | } 99 | int Idiom17::action() 100 | { 101 | if (m_icodes[0]->ll()->testFlags(I)) 102 | { 103 | m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::eCdecl); 104 | for(size_t idx=1; idxinvalidate(); 107 | } 108 | } 109 | // TODO : it's a calculated call 110 | else 111 | { 112 | printf("Indirect call at idiom17\n"); 113 | } 114 | return m_icodes.size(); 115 | } 116 | -------------------------------------------------------------------------------- /src/idioms/idiom.cpp: -------------------------------------------------------------------------------- 1 | #include "idiom.h" 2 | #include "Procedure.h" 3 | 4 | Idiom::Idiom(Function *f) : m_func(f),m_end(f->Icode.entries.end()) 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /src/idioms/mov_idioms.cpp: -------------------------------------------------------------------------------- 1 | #include "mov_idioms.h" 2 | 3 | #include "Procedure.h" 4 | #include "msvc_fixes.h" 5 | 6 | using namespace std; 7 | 8 | /***************************************************************************** 9 | * idiom 14 - Long uint16_t assign 10 | * MOV regL, mem/reg 11 | * XOR regH, regH 12 | * Eg: MOV ax, di 13 | * XOR dx, dx 14 | * => MOV dx:ax, di 15 | * Note: only the following combinations are allowed: 16 | * dx:ax 17 | * cx:bx 18 | * this is to remove the possibility of making errors in situations 19 | * like this: 20 | * MOV dx, offH 21 | * MOV ax, offL 22 | * XOR cx, cx 23 | * Found in Borland Turbo C, used for division of unsigned integer 24 | * operands. 25 | ****************************************************************************/ 26 | 27 | bool Idiom14::match(iICODE pIcode) 28 | { 29 | if(distance(pIcode,m_end)<2) 30 | return false; 31 | m_icodes[0]=pIcode++; 32 | m_icodes[1]=pIcode++; 33 | LLInst * matched [] {m_icodes[0]->ll(),m_icodes[1]->ll()}; 34 | /* Check for regL */ 35 | m_regL = matched[0]->m_dst.regi; 36 | if (not matched[0]->testFlags(I) and ((m_regL == rAX) or (m_regL ==rBX))) 37 | { 38 | /* Check for XOR regH, regH */ 39 | if (matched[1]->match(iXOR) and not matched[1]->testFlags(I)) 40 | { 41 | m_regH = matched[1]->m_dst.regi; 42 | if (m_regH == matched[1]->src().getReg2()) 43 | { 44 | if ((m_regL == rAX) and (m_regH == rDX)) 45 | return true; 46 | if ((m_regL == rBX) and (m_regH == rCX)) 47 | return true; 48 | } 49 | } 50 | } 51 | return false; 52 | } 53 | int Idiom14::action() 54 | { 55 | 56 | int idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(m_regH,m_regL), m_icodes[0]); 57 | AstIdent *lhs = AstIdent::LongIdx (idx); 58 | m_icodes[0]->setRegDU( m_regH, eDEF); 59 | Expr *rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE); 60 | m_icodes[0]->setAsgn(lhs, rhs); 61 | m_icodes[1]->invalidate(); 62 | return 2; 63 | } 64 | 65 | 66 | /***************************************************************************** 67 | * idiom 13 - uint16_t assign 68 | * MOV regL, mem 69 | * MOV regH, 0 70 | * Eg: MOV al, [bp-2] 71 | * MOV ah, 0 72 | * => MOV ax, [bp-2] 73 | * Found in Borland Turbo C, used for multiplication and division of 74 | * uint8_t operands (ie. they need to be extended to words). 75 | ****************************************************************************/ 76 | bool Idiom13::match(iICODE pIcode) 77 | { 78 | if(distance(pIcode,m_end)<2) 79 | return false; 80 | m_icodes[0]=pIcode++; 81 | m_icodes[1]=pIcode++; 82 | m_loaded_reg = rUNDEF; 83 | eReg regi; 84 | 85 | /* Check for regL */ 86 | regi = m_icodes[0]->ll()->m_dst.regi; 87 | if (not m_icodes[0]->ll()->testFlags(I) and (regi >= rAL) and (regi <= rBH)) 88 | { 89 | /* Check for MOV regH, 0 */ 90 | if (m_icodes[1]->ll()->match(iMOV,I) and (m_icodes[1]->ll()->src().getImm2() == 0)) 91 | { 92 | if (m_icodes[1]->ll()->m_dst.regi == (regi + 4)) //WARNING: based on distance between AH-AL,BH-BL etc. 93 | { 94 | m_loaded_reg=(eReg)(regi - rAL + rAX); 95 | return true; 96 | } 97 | } 98 | } 99 | return false; 100 | } 101 | 102 | int Idiom13::action() 103 | { 104 | AstIdent *lhs; 105 | Expr *rhs; 106 | eReg regi = m_icodes[0]->ll()->m_dst.regi; 107 | m_icodes[0]->du1.removeDef(regi); 108 | //m_icodes[0]->du1.numRegsDef--; /* prev uint8_t reg def */ 109 | lhs = new RegisterNode(LLOperand(m_loaded_reg, 0), &m_func->localId); 110 | m_icodes[0]->setRegDU( m_loaded_reg, eDEF); 111 | rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE); 112 | m_icodes[0]->setAsgn(lhs, rhs); 113 | m_icodes[1]->invalidate(); 114 | return 2; 115 | } 116 | 117 | -------------------------------------------------------------------------------- /src/idioms/neg_idioms.cpp: -------------------------------------------------------------------------------- 1 | #include "neg_idioms.h" 2 | 3 | #include "dcc.h" 4 | #include "msvc_fixes.h" 5 | 6 | using namespace std; 7 | 8 | 9 | /***************************************************************************** 10 | * idiom11 - Negate long integer 11 | * NEG regH 12 | * NEG regL 13 | * SBB regH, 0 14 | * Eg: NEG dx 15 | * NEG ax 16 | * SBB dx, 0 17 | * => dx:ax = - dx:ax 18 | * Found in Borland Turbo C. 19 | ****************************************************************************/ 20 | bool Idiom11::match (iICODE picode) 21 | { 22 | //const char *matchstring="(oNEG rH) (oNEG rL) (SBB \rH i0)"; 23 | condId type; /* type of argument */ 24 | if(distance(picode,m_end)<3) 25 | return false; 26 | for(int i=0; i<3; ++i) 27 | m_icodes[i]=picode++; 28 | type = m_icodes[0]->ll()->idType(DST); 29 | if(type==CONSTANT or type == OTHER) 30 | return false; 31 | /* Check NEG reg/mem 32 | * SBB reg/mem, 0*/ 33 | if (not m_icodes[1]->ll()->match(iNEG) or not m_icodes[2]->ll()->match(iSBB)) 34 | return false; 35 | switch (type) 36 | { 37 | case GLOB_VAR: 38 | if ((m_icodes[2]->ll()->m_dst.segValue == m_icodes[0]->ll()->m_dst.segValue) and 39 | (m_icodes[2]->ll()->m_dst.off == m_icodes[0]->ll()->m_dst.off)) 40 | return true; 41 | break; 42 | case REGISTER: 43 | if (m_icodes[2]->ll()->m_dst.regi == m_icodes[0]->ll()->m_dst.regi) 44 | return true; 45 | break; 46 | case PARAM: 47 | case LOCAL_VAR: 48 | if (m_icodes[2]->ll()->m_dst.off == m_icodes[0]->ll()->m_dst.off) 49 | return true; 50 | break; 51 | default: 52 | fprintf(stderr,"Idiom11::match unhandled type %d\n",type); 53 | } 54 | return false; 55 | } 56 | int Idiom11::action() 57 | { 58 | AstIdent *lhs; 59 | Expr *rhs; 60 | lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0], HIGH_FIRST,m_icodes[0], USE_DEF, *m_icodes[1]->ll()); 61 | rhs = UnaryOperator::Create(NEGATION, lhs); 62 | m_icodes[0]->setAsgn(lhs, rhs); 63 | m_icodes[1]->invalidate(); 64 | m_icodes[2]->invalidate(); 65 | return 3; 66 | } 67 | 68 | /***************************************************************************** 69 | * idiom 16: Bitwise negation 70 | * NEG reg 71 | * SBB reg, reg 72 | * INC reg 73 | * => ASGN reg, !reg 74 | * Eg: NEG ax 75 | * SBB ax, ax 76 | * INC ax 77 | * => ax = !ax 78 | * Found in Borland Turbo C when negating bitwise. 79 | ****************************************************************************/ 80 | bool Idiom16::match (iICODE picode) 81 | { 82 | //const char *matchstring="(oNEG rR) (oSBB rR rR) (oINC rR)"; 83 | if(distance(picode,m_end)<3) 84 | return false; 85 | for(int i=0; i<3; ++i) 86 | m_icodes[i]=picode++; 87 | 88 | uint8_t regi = m_icodes[0]->ll()->m_dst.regi; 89 | if ((regi >= rAX) and (regi < INDEX_BX_SI)) 90 | { 91 | if (m_icodes[1]->ll()->match(iSBB) and m_icodes[2]->ll()->match(iINC)) 92 | if ((m_icodes[1]->ll()->m_dst.regi == (m_icodes[1]->ll()->src().getReg2())) and 93 | m_icodes[1]->ll()->match((eReg)regi) and 94 | m_icodes[2]->ll()->match((eReg)regi)) 95 | return true; 96 | } 97 | return false; 98 | } 99 | int Idiom16::action() 100 | { 101 | AstIdent *lhs; 102 | Expr *rhs; 103 | lhs = new RegisterNode(*m_icodes[0]->ll()->get(DST),&m_func->localId); 104 | rhs = UnaryOperator::Create(NEGATION, lhs->clone()); 105 | m_icodes[0]->setAsgn(lhs, rhs); 106 | m_icodes[1]->invalidate(); 107 | m_icodes[2]->invalidate(); 108 | return 3; 109 | } 110 | -------------------------------------------------------------------------------- /src/liveness_set.cpp: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "machine_x86.h" 3 | 4 | /* DU bit definitions for each reg value - including index registers */ 5 | LivenessSet duReg[] = { {}, 6 | //AH AL . . AX, BH 7 | {rAH,rAL,rAX},{rCH,rCL,rCX},{rDH,rDL,rDX},{rBH,rBL,rBX}, 8 | /* uint16_t regs */ 9 | {rSP},{rBP},{rSI},{rDI}, 10 | /* seg regs */ 11 | {rES},{rCS},{rSS},{rDS}, 12 | /* uint8_t regs */ 13 | {rAL},{rCL},{rDL},{rBL}, 14 | {rAH},{rCH},{rDH},{rBH}, 15 | /* tmp reg */ 16 | {rTMP},{rTMP2}, 17 | /* index regs */ 18 | {rBX,rSI},{rBX,rDI},{rBP,rSI},{rBP,rDI}, 19 | {rSI},{rDI},{rBP},{rBX} 20 | }; 21 | 22 | LivenessSet &LivenessSet::setReg(int r) 23 | { 24 | this->reset(); 25 | *this |= duReg[r]; 26 | return *this; 27 | } 28 | LivenessSet &LivenessSet::clrReg(int r) 29 | { 30 | return *this -= duReg[r]; 31 | } 32 | 33 | LivenessSet &LivenessSet::addReg(int r) 34 | { 35 | *this |= duReg[r]; 36 | // postProcessCompositeRegs(); 37 | return *this; 38 | } 39 | 40 | bool LivenessSet::testRegAndSubregs(int r) const 41 | { 42 | return (*this & duReg[r]).any(); 43 | } 44 | void LivenessSet::postProcessCompositeRegs() 45 | { 46 | if(testReg(rAL) and testReg(rAH)) 47 | registers.insert(rAX); 48 | if(testReg(rCL) and testReg(rCH)) 49 | registers.insert(rCX); 50 | if(testReg(rDL) and testReg(rDH)) 51 | registers.insert(rDX); 52 | if(testReg(rBL) and testReg(rBH)) 53 | registers.insert(rBX); 54 | } 55 | -------------------------------------------------------------------------------- /src/project.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "dcc.h" 5 | #include "CallGraph.h" 6 | #include "project.h" 7 | #include "Procedure.h" 8 | 9 | using namespace std; 10 | 11 | QString asm1_name, asm2_name; /* Assembler output filenames */ 12 | STATS stats; /* cfg statistics */ 13 | OPTION option; /* Command line options */ 14 | Project *Project::s_instance = nullptr; 15 | Project::Project() : callGraph(nullptr) 16 | { 17 | } 18 | void Project::initialize() 19 | { 20 | delete callGraph; 21 | callGraph = nullptr; 22 | } 23 | void Project::create(const QString &a) 24 | { 25 | initialize(); 26 | QFileInfo fi(a); 27 | m_fname=a; 28 | m_project_name = fi.completeBaseName(); 29 | m_output_path = fi.path(); 30 | } 31 | 32 | QString Project::output_name(const char *ext) { 33 | return m_output_path+QDir::separator()+m_project_name+"."+ext; 34 | } 35 | bool Project::valid(ilFunction iter) 36 | { 37 | return iter!=pProcList.end(); 38 | } 39 | ilFunction Project::funcIter(Function *to_find) 40 | { 41 | auto iter=std::find_if(pProcList.begin(),pProcList.end(), 42 | [to_find](const Function &f)->bool {return to_find==&f;}); 43 | assert(iter!=pProcList.end()); 44 | return iter; 45 | } 46 | 47 | ilFunction Project::findByEntry(uint32_t entry) 48 | { 49 | /* Search procedure list for one with appropriate entry point */ 50 | ilFunction iter= std::find_if(pProcList.begin(),pProcList.end(), 51 | [entry](const Function &f) { return f.procEntry==entry; }); 52 | return iter; 53 | } 54 | 55 | ilFunction Project::createFunction(FunctionType *f,const QString &name) 56 | { 57 | pProcList.push_back(*Function::Create(f,0,name,nullptr)); 58 | return (++pProcList.rbegin()).base(); 59 | } 60 | 61 | int Project::getSymIdxByAddr(uint32_t adr) 62 | { 63 | size_t i; 64 | for (i = 0; i < symtab.size(); i++) { 65 | if (symtab[i].label == adr) { 66 | break; 67 | } 68 | } 69 | return i; 70 | } 71 | 72 | bool Project::validSymIdx(size_t idx) 73 | { 74 | return idx 3 | #include 4 | 5 | TEST(CowriteTest, HandlesZeroInput) { 6 | EXPECT_EQ(1, 1); 7 | } 8 | 9 | int main(int argc, char** argv) { 10 | // The following line must be executed to initialize Google Mock 11 | // (and Google Test) before running the tests. 12 | ::testing::InitGoogleMock(&argc, argv); 13 | return RUN_ALL_TESTS(); 14 | } 15 | -------------------------------------------------------------------------------- /src/tests/loader.cpp: -------------------------------------------------------------------------------- 1 | #include "project.h" 2 | #include "loader.h" 3 | #include 4 | #include 5 | 6 | TEST(Loader, NewProjectIsInitalized) { 7 | Project p; 8 | EXPECT_EQ(nullptr,p.callGraph); 9 | ASSERT_TRUE(p.pProcList.empty()); 10 | ASSERT_TRUE(p.binary_path().empty()); 11 | ASSERT_TRUE(p.project_name().empty()); 12 | ASSERT_TRUE(p.symtab.empty()); 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/tests/project.cpp: -------------------------------------------------------------------------------- 1 | #include "project.h" 2 | #include 3 | #include 4 | 5 | TEST(Project, NewProjectIsInitalized) { 6 | Project p; 7 | EXPECT_EQ(nullptr,p.callGraph); 8 | ASSERT_TRUE(p.pProcList.empty()); 9 | ASSERT_TRUE(p.binary_path().empty()); 10 | ASSERT_TRUE(p.project_name().empty()); 11 | ASSERT_TRUE(p.symtab.empty()); 12 | } 13 | 14 | TEST(Project, CreatedProjectHasValidNames) { 15 | Project p; 16 | std::vector strs = {"./Project1.EXE","/home/Project2.EXE","/home/Pro\\ ject3"}; 17 | std::vector expected = {"Project1","Project2","Pro\\ ject3"}; 18 | for(size_t i=0; i 12 | #include 13 | #include 14 | #include 15 | #include 16 | extern Project g_proj; 17 | //static void displayCFG(Function * pProc); 18 | //static void displayDfs(BB * pBB); 19 | 20 | /**************************************************************************** 21 | * udm 22 | ****************************************************************************/ 23 | void Function::buildCFG(Disassembler &ds) 24 | { 25 | if(flg & PROC_ISLIB) 26 | return; // Ignore library functions 27 | createCFG(); 28 | if (option.VeryVerbose) 29 | displayCFG(); 30 | 31 | compressCFG(); // Remove redundancies and add in-edge information 32 | 33 | if (option.asm2) 34 | { 35 | ds.disassem(this); // Print 2nd pass assembler listing 36 | return; 37 | } 38 | 39 | /* Idiom analysis and propagation of long type */ 40 | lowLevelAnalysis(); 41 | 42 | /* Generate HIGH_LEVEL icodes whenever possible */ 43 | highLevelGen(); 44 | } 45 | void Function::controlFlowAnalysis() 46 | { 47 | if (flg & PROC_ISLIB) 48 | return; /* Ignore library functions */ 49 | derSeq *derivedG=nullptr; 50 | 51 | /* Make cfg reducible and build derived sequences */ 52 | derivedG=checkReducibility(); 53 | 54 | if (option.VeryVerbose) 55 | derivedG->display(); 56 | 57 | /* Structure the graph */ 58 | structure(derivedG); 59 | 60 | /* Check for compound conditions */ 61 | compoundCond (); 62 | 63 | if (option.verbose) 64 | { 65 | qDebug() <<"\nDepth first traversal - Proc" <displayDfs(); 67 | //m_cfg.front()->displayDfs(); 68 | } 69 | 70 | /* Free storage occupied by this procedure */ 71 | freeDerivedSeq(*derivedG); 72 | 73 | } 74 | void udm() 75 | { 76 | 77 | /* Build the control flow graph, find idioms, and convert low-level 78 | * icodes to high-level ones */ 79 | Project *proj = Project::get(); 80 | Disassembler ds(2); 81 | for (auto iter = proj->pProcList.rbegin(); iter!=proj->pProcList.rend(); ++iter) 82 | { 83 | Function &f(*iter); 84 | if(option.CustomEntryPoint) { 85 | if(f.procEntry!=option.CustomEntryPoint) { 86 | continue; 87 | } 88 | } 89 | iter->buildCFG(ds); 90 | } 91 | if (option.asm2) 92 | return; 93 | 94 | 95 | /* Data flow analysis - eliminate condition codes, extraneous registers 96 | * and intermediate instructions. Find expressions by forward 97 | * substitution algorithm */ 98 | LivenessSet live_regs; 99 | if(option.CustomEntryPoint) { 100 | ilFunction iter = proj->findByEntry(option.CustomEntryPoint); 101 | if(iter==proj->pProcList.end()) { 102 | qCritical()<< "No function found at entry point" << QString::number(option.CustomEntryPoint,16); 103 | return; 104 | } 105 | iter->dataFlow(live_regs); 106 | iter->controlFlowAnalysis(); 107 | delete proj->callGraph; 108 | proj->callGraph = new CALL_GRAPH; 109 | proj->callGraph->proc = iter; 110 | return; 111 | } 112 | proj->pProcList.front().dataFlow (live_regs); 113 | 114 | /* Control flow analysis - structuring algorithm */ 115 | for (auto iter = proj->pProcList.rbegin(); iter!=proj->pProcList.rend(); ++iter) 116 | { 117 | iter->controlFlowAnalysis(); 118 | } 119 | } 120 | 121 | /**************************************************************************** 122 | * displayCFG - Displays the Basic Block list 123 | ***************************************************************************/ 124 | void Function::displayCFG() 125 | { 126 | qDebug() << "\nBasic Block List - Proc"<display(); 130 | } 131 | } 132 | 133 | 134 | -------------------------------------------------------------------------------- /test_use_all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm tests/prev 3 | rm tests/inputs 4 | ln -s inputs_all tests/inputs 5 | ln -s prev_all tests/prev -------------------------------------------------------------------------------- /test_use_base.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm tests/prev 3 | rm tests/inputs 4 | ln -s inputs_base tests/inputs 5 | ln -s prev_base tests/prev -------------------------------------------------------------------------------- /tests/initial_base/BENCHFN.C: -------------------------------------------------------------------------------- 1 | /* benchfn - benchmark for function calls 2 | * Thomas Plum, Plum Hall Inc, 609-927-3770 3 | * Let T be the execution time in milliseconds 4 | * Then average time per operator = T/major usec 5 | * (Because the inner loop has exactly 1000 operations) 6 | */ 7 | #include 8 | 9 | f3() { ;} 10 | f2() { f3();f3();f3();f3();f3();f3();f3();f3();f3();f3();} /* 10 */ 11 | f1() { f2();f2();f2();f2();f2();f2();f2();f2();f2();f2();} /* 10 */ 12 | f0() { f1();f1();f1();f1();f1();f1();f1();f1();f1();} /* 9 */ 13 | 14 | main(int ac, char *av[]) 15 | { long d, major; 16 | 17 | printf ("enter number of iterations "); 18 | scanf ("%ld", &major); 19 | printf("executing %ld iterations\n", major); 20 | for (d = 1; d <= major; ++d) 21 | f0(); /* executes 1000 calls */ 22 | printf ("finished\n"); 23 | } -------------------------------------------------------------------------------- /tests/initial_base/BENCHFN.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\benchfn.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void proc_4 () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | } 15 | 16 | 17 | void proc_3 () 18 | /* Takes no parameters. 19 | * High-level language prologue code. 20 | */ 21 | { 22 | proc_4 (); 23 | proc_4 (); 24 | proc_4 (); 25 | proc_4 (); 26 | proc_4 (); 27 | proc_4 (); 28 | proc_4 (); 29 | proc_4 (); 30 | proc_4 (); 31 | proc_4 (); 32 | } 33 | 34 | 35 | void proc_2 () 36 | /* Takes no parameters. 37 | * High-level language prologue code. 38 | */ 39 | { 40 | proc_3 (); 41 | proc_3 (); 42 | proc_3 (); 43 | proc_3 (); 44 | proc_3 (); 45 | proc_3 (); 46 | proc_3 (); 47 | proc_3 (); 48 | proc_3 (); 49 | proc_3 (); 50 | } 51 | 52 | 53 | void proc_1 () 54 | /* Takes no parameters. 55 | * High-level language prologue code. 56 | */ 57 | { 58 | proc_2 (); 59 | proc_2 (); 60 | proc_2 (); 61 | proc_2 (); 62 | proc_2 (); 63 | proc_2 (); 64 | proc_2 (); 65 | proc_2 (); 66 | proc_2 (); 67 | } 68 | 69 | 70 | void main () 71 | /* Takes no parameters. 72 | * High-level language prologue code. 73 | */ 74 | { 75 | long loc1; 76 | long loc2; 77 | 78 | printf ("enter number of iterations "); 79 | scanf ("%ld", &loc0); 80 | printf ("executing %ld iterations\n", loc2); 81 | loc1 = 1; 82 | while ((loc1 <= loc2)) { 83 | proc_1 (); 84 | loc1 = (loc1 + 1); 85 | } 86 | printf ("finished\n"); 87 | } 88 | 89 | -------------------------------------------------------------------------------- /tests/initial_base/BENCHLNG.C: -------------------------------------------------------------------------------- 1 | /* benchlng - benchmark for long integers 2 | * Thomas Plum, Plum Hall Inc, 609-927-3770 3 | * If machine traps overflow, use an unsigned type 4 | * Let T be the execution time in milliseconds 5 | * Then average time per operator = T/major usec 6 | * (Because the inner loop has exactly 1000 operations) 7 | */ 8 | #define STOR_CL auto 9 | #define TYPE long 10 | #include 11 | main(int ac, char *av[]) 12 | { TYPE a, b, c; 13 | long d, major; 14 | 15 | scanf ("%ld", &major); 16 | printf("executing %ld iterations\n", major); 17 | scanf ("%ld", &a); 18 | scanf ("%ld", &b); 19 | for (d = 1; d <= major; ++d) 20 | { 21 | /* inner loop executes 1000 selected operations */ 22 | for (c = 1; c <= 40; ++c) 23 | { 24 | a = a + b + c; 25 | b = a >> 1; 26 | a = b % 10; 27 | a = b == c; 28 | b = a | c; 29 | a = !b; 30 | b = a + c; 31 | a = b > c; 32 | } 33 | } 34 | printf("a=%d\n", a); 35 | } 36 |  -------------------------------------------------------------------------------- /tests/initial_base/BENCHLNG.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\benchlng.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | long LMOD@ (long arg0, int arg2int arg3) 10 | /* Takes 8 bytes of parameters. 11 | * Runtime support routine of the compiler. 12 | * Untranslatable routine. Assembler provided. 13 | * Return value in registers dx:ax. 14 | * Pascal calling convention. 15 | */ 16 | { 17 | MOV cx, 2 18 | PUSH bp 19 | PUSH si 20 | PUSH di 21 | MOV bp, sp 22 | MOV di, cx 23 | MOV ax, [bp+0Ah] 24 | MOV dx, [bp+0Ch] 25 | MOV bx, [bp+0Eh] 26 | MOV cx, [bp+10h] 27 | CMP cx, 0 28 | JNE L1 29 | OR dx, dx 30 | JE L2 31 | OR bx, bx 32 | JE L2 33 | 34 | L1: TEST di, 1 35 | JNE L3 36 | OR dx, dx 37 | JNS L4 38 | NEG dx 39 | NEG ax 40 | SBB dx, 0 41 | OR di, 0Ch 42 | 43 | L4: OR cx, cx 44 | JNS L3 45 | NEG cx 46 | NEG bx 47 | SBB cx, 0 48 | XOR di, 4 49 | 50 | L3: MOV bp, cx 51 | MOV cx, 20h 52 | PUSH di 53 | XOR di, 0 54 | XOR si, 0 55 | 56 | L5: SHL ax, 1 57 | RCL dx, 1 58 | RCL si, 1 59 | RCL di, 1 60 | CMP di, bp 61 | JB L6 62 | JA L7 63 | CMP si, bx 64 | JB L6 65 | 66 | L7: SUB si, bx 67 | SBB di, bp 68 | INC ax 69 | 70 | L6: LOOP L5 71 | POP bx 72 | TEST bx, 2 73 | JE L8 74 | MOV ax, si 75 | MOV dx, di 76 | SHR bx, 1 77 | 78 | L8: TEST bx, 4 79 | JE L9 80 | NEG dx 81 | NEG ax 82 | SBB dx, 0 83 | 84 | L9: POP di 85 | POP si 86 | POP bp 87 | RETF 8 88 | 89 | L2: MOV tmp, dx:ax ;Synthetic inst 90 | DIV bx 91 | MOD bx ;Synthetic inst 92 | TEST di, 2 93 | JE L10 94 | MOV ax, dx 95 | 96 | L10: XOR dx, dx 97 | JMP L9 98 | } 99 | 100 | 101 | void main () 102 | /* Takes no parameters. 103 | * High-level language prologue code. 104 | */ 105 | { 106 | long loc1; 107 | long loc2; 108 | long loc3; 109 | long loc4; 110 | long loc5; 111 | int loc6; /* ax */ 112 | 113 | scanf ("%ld", &loc0); 114 | printf ("executing %ld iterations\n", loc5); 115 | scanf ("%ld", &loc2); 116 | scanf ("%ld", &loc3); 117 | loc3 = 1; 118 | while ((loc3 <= loc5)) { 119 | loc2 = 1; 120 | while ((loc2 <= 40)) { 121 | loc4 = ((loc4 + loc1) + loc2); 122 | loc1 = (loc4 >> 1); 123 | loc4 = LMOD@ (loc1, 10); 124 | if (loc1 == loc2) { 125 | loc6 = 1; 126 | } 127 | else { 128 | loc6 = 0; 129 | } 130 | loc4 = loc6; 131 | loc1 = (loc4 | loc2); 132 | if ((loc3 | loc9) == 0) { 133 | loc6 = 1; 134 | } 135 | else { 136 | loc6 = 0; 137 | } 138 | loc4 = loc6; 139 | loc1 = (loc4 + loc2); 140 | if (loc1 > loc2) { 141 | loc6 = 1; 142 | } 143 | else { 144 | loc6 = 0; 145 | } 146 | loc4 = loc6; 147 | loc2 = (loc2 + 1); 148 | } 149 | loc3 = (loc3 + 1); 150 | } 151 | printf ("a=%d\n", loc4); 152 | } 153 | 154 | -------------------------------------------------------------------------------- /tests/initial_base/BENCHMUL.C: -------------------------------------------------------------------------------- 1 | /* benchmul - benchmark for int multiply 2 | * Thomas Plum, Plum Hall Inc, 609-927-3770 3 | * If machine traps overflow, use an unsigned type 4 | * Let T be the execution time in milliseconds 5 | * Then average time per operator = T/major usec 6 | * (Because the inner loop has exactly 1000 operations) 7 | */ 8 | #define STOR_CL auto 9 | #define TYPE int 10 | #include 11 | main(int ac, char *av[]) 12 | { STOR_CL TYPE a, b, c; 13 | long d, major; 14 | 15 | printf ("enter number of iterations\n"); 16 | scanf ("%ld", &major); 17 | printf("executing %ld iterations\n", major); 18 | scanf ("%d", &a); 19 | scanf ("%d", &b); 20 | for (d = 1; d <= major; ++d) 21 | { 22 | /* inner loop executes 1000 selected operations */ 23 | for (c = 1; c <= 40; ++c) 24 | { 25 | a = 3 *a*a*a*a*a*a*a*a * a*a*a*a*a*a*a*a * a*a*a*a*a*a*a*a * a; /* 25 * */ 26 | } 27 | } 28 | printf("a=%d\n", a); 29 | } 30 |  -------------------------------------------------------------------------------- /tests/initial_base/BENCHMUL.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\benchmul.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | int loc2; 16 | long loc3; 17 | long loc4; 18 | int loc5; 19 | 20 | printf ("enter number of iterations\n"); 21 | scanf ("%ld", &loc0); 22 | printf ("executing %ld iterations\n", loc4); 23 | scanf ("%d", &loc1); 24 | scanf ("%d", &loc2); 25 | loc3 = 1; 26 | while ((loc3 <= loc4)) { 27 | loc5 = 1; 28 | while ((loc5 <= 40)) { 29 | loc1 = (((((((((((((((((((((((((loc1 * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * 3); 30 | loc5 = (loc5 + 1); 31 | } 32 | loc3 = (loc3 + 1); 33 | } 34 | printf ("a=%d\n", loc1); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /tests/initial_base/BENCHMUS.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\benchmus.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | long loc2; 16 | long loc3; 17 | int loc4; 18 | int loc5; 19 | 20 | printf ("enter number of iterations\n"); 21 | scanf ("%ld", &loc0); 22 | printf ("executing %ld iterations\n", loc3); 23 | loc4 = 20; 24 | loc1 = loc4; 25 | loc2 = 1; 26 | while ((loc2 <= loc3)) { 27 | loc5 = 1; 28 | while ((loc5 <= 40)) { 29 | loc4 = (((((((((((((((((((((((((loc4 * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * 3); 30 | loc5 = (loc5 + 1); 31 | } 32 | loc2 = (loc2 + 1); 33 | } 34 | printf ("a=%d\n", loc4); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /tests/initial_base/BENCHSHO.C: -------------------------------------------------------------------------------- 1 | /* benchsho - benchmark for short integers 2 | * Thomas Plum, Plum Hall Inc, 609-927-3770 3 | * If machine traps overflow, use an unsigned type 4 | * Let T be the execution time in milliseconds 5 | * Then average time per operator = T/major usec 6 | * (Because the inner loop has exactly 1000 operations) 7 | */ 8 | #define STOR_CL auto 9 | #define TYPE short 10 | #include 11 | 12 | main(int ac, char *av[]) 13 | { STOR_CL TYPE a, b, c; 14 | long d, major; 15 | 16 | scanf ("%ld", &major); 17 | printf("executing %ld iterations\n", major); 18 | scanf ("%ld", &a); 19 | scanf ("%ld", &b); 20 | for (d = 1; d <= major; ++d) 21 | { 22 | /* inner loop executes 1000 selected operations */ 23 | for (c = 1; c <= 40; ++c) 24 | { 25 | a = a + b + c; 26 | b = a >> 1; 27 | a = b % 10; 28 | a = b == c; 29 | b = a | c; 30 | a = !b; 31 | b = a + c; 32 | a = b > c; 33 | } 34 | } 35 | printf("a=%d\n", a); 36 | } 37 |  -------------------------------------------------------------------------------- /tests/initial_base/BENCHSHO.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\benchsho.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | int loc2; 16 | int loc3; 17 | long loc4; 18 | long loc5; 19 | int loc6; /* ax */ 20 | 21 | scanf ("%ld", &loc0); 22 | printf ("executing %ld iterations\n", loc5); 23 | scanf ("%ld", &loc1); 24 | scanf ("%ld", &loc2); 25 | loc4 = 1; 26 | while ((loc4 <= loc5)) { 27 | loc3 = 1; 28 | while ((loc3 <= 40)) { 29 | loc1 = ((loc1 + loc2) + loc3); 30 | loc2 = (loc1 >> 1); 31 | loc1 = (loc2 % 10); 32 | if (loc2 == loc3) { 33 | loc6 = 1; 34 | } 35 | else { 36 | loc6 = 0; 37 | } 38 | loc1 = loc6; 39 | loc2 = (loc1 | loc3); 40 | loc1 = !loc2; 41 | loc2 = (loc1 + loc3); 42 | if (loc2 > loc3) { 43 | loc6 = 1; 44 | } 45 | else { 46 | loc6 = 0; 47 | } 48 | loc1 = loc6; 49 | loc3 = (loc3 + 1); 50 | } 51 | loc4 = (loc4 + 1); 52 | } 53 | printf ("a=%d\n", loc1); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /tests/initial_base/BYTEOPS.C: -------------------------------------------------------------------------------- 1 | #define TYPE unsigned char 2 | 3 | main() 4 | { TYPE a, b; 5 | 6 | a = 255; 7 | b = 143; 8 | b = a + b; 9 | a = a - b; 10 | a = a * b; 11 | b = b / a; 12 | b = b % a; 13 | a = a << 5; 14 | b = b >> a; 15 | printf ("a = %d, b = %d\n", a, b); 16 | } -------------------------------------------------------------------------------- /tests/initial_base/BYTEOPS.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\byteops.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | int loc2; 16 | 17 | loc1 = 255; 18 | loc2 = 143; 19 | loc2 = (loc1 + loc2); 20 | loc1 = (loc1 - loc2); 21 | loc1 = (loc1 * loc2); 22 | loc2 = (loc2 / loc1); 23 | loc2 = (loc2 % loc1); 24 | loc1 = (loc1 << 5); 25 | loc2 = (loc2 >> loc1); 26 | printf ("a = %d, b = %d\n", loc1, loc2); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /tests/initial_base/FIBO.C: -------------------------------------------------------------------------------- 1 | /* Fibonacci */ 2 | 3 | #include 4 | 5 | int main() 6 | { int i, numtimes, number; 7 | unsigned value, fib(); 8 | 9 | printf("Input number of iterations: "); 10 | scanf ("%d", &numtimes); 11 | for (i = 1; i <= numtimes; i++) 12 | { 13 | printf ("Input number: "); 14 | scanf ("%d", &number); 15 | value = fib(number); 16 | printf("fibonacci(%d) = %u\n", number, value); 17 | } 18 | exit(0); 19 | } 20 | 21 | unsigned fib(x) /* compute fibonacci number recursively */ 22 | int x; 23 | { 24 | if (x > 2) 25 | return (fib(x - 1) + fib(x - 2)); 26 | else 27 | return (1); 28 | } 29 |  -------------------------------------------------------------------------------- /tests/initial_base/FIBOL.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\fibol.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | int proc_1 (int arg0) 10 | /* Takes 2 bytes of parameters. 11 | * High-level language prologue code. 12 | * C calling convention. 13 | */ 14 | { 15 | int loc1; 16 | int loc2; /* ax */ 17 | 18 | loc1 = arg0; 19 | if (loc1 > 2) { 20 | loc2 = (proc_1 ((loc1 - 1)) + proc_1 ((loc1 + 0xFFFE))); 21 | } 22 | else { 23 | loc2 = 1; 24 | } 25 | return (loc2); 26 | } 27 | 28 | 29 | void main () 30 | /* Takes no parameters. 31 | * High-level language prologue code. 32 | * Contains instructions not normally used by compilers. 33 | */ 34 | { 35 | int loc1; 36 | int loc2; 37 | int loc3; 38 | int loc4; 39 | 40 | printf ("Input number of iterations: "); 41 | scanf ("%d", &loc1, ); 42 | loc3 = 1; 43 | while ((loc3 <= loc1)) { 44 | printf ("Input number: "); 45 | scanf ("%d", &loc2, ); 46 | loc4 = proc_1 (loc2); 47 | printf ("fibonacci(%d) = %u\n", loc2, loc4); 48 | loc3 = (loc3 + 1); 49 | } 50 | exit (0); 51 | } 52 | 53 | -------------------------------------------------------------------------------- /tests/initial_base/FIBOS.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\fibos.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | int proc_1 (int arg0) 10 | /* Takes 2 bytes of parameters. 11 | * High-level language prologue code. 12 | * C calling convention. 13 | */ 14 | { 15 | int loc1; 16 | int loc2; /* ax */ 17 | 18 | loc1 = arg0; 19 | if (loc1 > 2) { 20 | loc2 = (proc_1 ((loc1 - 1)) + proc_1 ((loc1 + 0xFFFE))); 21 | } 22 | else { 23 | loc2 = 1; 24 | } 25 | return (loc2); 26 | } 27 | 28 | 29 | void main () 30 | /* Takes no parameters. 31 | * High-level language prologue code. 32 | */ 33 | { 34 | int loc1; 35 | int loc2; 36 | int loc3; 37 | int loc4; 38 | 39 | printf ("Input number of iterations: "); 40 | scanf ("%d", &loc1); 41 | loc3 = 1; 42 | while ((loc3 <= loc1)) { 43 | printf ("Input number: "); 44 | scanf ("%d", &loc2); 45 | loc4 = proc_1 (loc2); 46 | printf ("fibonacci(%d) = %u\n", loc2, loc4); 47 | loc3 = (loc3 + 1); 48 | } 49 | exit (0); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /tests/initial_base/INTOPS.C: -------------------------------------------------------------------------------- 1 | #define TYPE int 2 | 3 | main() 4 | { TYPE a, b; 5 | 6 | a = 255; 7 | b = 143; 8 | b = a + b; 9 | a = a - b; 10 | a = a * b; 11 | b = b / a; 12 | b = b % a; 13 | a = a << 5; 14 | b = b >> a; 15 | printf ("a = %d, b = %d\n", a, b); 16 | } -------------------------------------------------------------------------------- /tests/initial_base/INTOPS.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\intops.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | int loc2; 16 | long loc3; /* dx:ax */ 17 | int loc4; /* tmp */ 18 | 19 | loc1 = 255; 20 | loc2 = 143; 21 | loc2 = (loc1 + loc2); 22 | loc1 = (loc1 - loc2); 23 | loc1 = (loc1 * loc2); 24 | loc3 = loc2; 25 | loc2 = (loc4 / loc1); 26 | loc3 = loc2; 27 | LO(loc3) = (loc4 / loc1); 28 | loc2 = (loc4 % loc1); 29 | loc1 = (loc1 << 5); 30 | loc2 = (loc2 >> loc1); 31 | printf ("a = %d, b = %d\n", loc1, loc2); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /tests/initial_base/LONGOPS.C: -------------------------------------------------------------------------------- 1 | #define TYPE long 2 | 3 | main() 4 | { TYPE a, b; 5 | 6 | a = 255; 7 | b = 143; 8 | b = a + b; 9 | a = a - b; 10 | a = a * b; 11 | b = b / a; 12 | b = b % a; 13 | a = a << 5; 14 | b = b >> a; 15 | printf ("a = %ld, b = %ld\n", a, b); 16 | } -------------------------------------------------------------------------------- /tests/initial_base/MATRIXMU.C: -------------------------------------------------------------------------------- 1 | #define n 5 2 | #define m 4 3 | 4 | static void multMatrix (int a[n][m], int b[m][n], int c[n][n]) 5 | { int i,j,k; 6 | 7 | for (i=0; i y) 13 | return (x); 14 | return (y); 15 | } -------------------------------------------------------------------------------- /tests/initial_base/MAX.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\max.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | int proc_1 (int arg0, int arg1) 10 | /* Takes 4 bytes of parameters. 11 | * High-level language prologue code. 12 | * C calling convention. 13 | */ 14 | { 15 | int loc1; /* ax */ 16 | 17 | if (arg0 > arg1) { 18 | loc1 = arg0; 19 | } 20 | else { 21 | loc1 = arg1; 22 | } 23 | return (loc1); 24 | } 25 | 26 | 27 | void main () 28 | /* Takes no parameters. 29 | * High-level language prologue code. 30 | */ 31 | { 32 | int loc1; 33 | int loc2; 34 | 35 | printf ("Enter 2 numbers: "); 36 | scanf ("%d %d", &loc2, &loc1); 37 | if (loc2 != loc1) { 38 | printf ("Maximum: %d\n", proc_1 (loc2, loc1)); 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /tests/initial_base/STRLEN.C: -------------------------------------------------------------------------------- 1 | main() 2 | { char *s = "test"; 3 | 4 | strlen(s); 5 | } 6 | 7 | strlen(char *s) 8 | { int n = 0; 9 | 10 | while (*s++) 11 | n++; 12 | return (n); 13 | } -------------------------------------------------------------------------------- /tests/initial_base/STRLEN.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\strlen.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void proc_1 (int arg0) 10 | /* Takes 2 bytes of parameters. 11 | * High-level language prologue code. 12 | * C calling convention. 13 | */ 14 | { 15 | int loc1; 16 | 17 | loc1 = 0; 18 | arg0 = (arg0 + 1); 19 | while ((*arg0 != 0)) { 20 | loc1 = (loc1 + 1); 21 | arg0 = (arg0 + 1); 22 | } 23 | } 24 | 25 | 26 | void main () 27 | /* Takes no parameters. 28 | */ 29 | { 30 | int loc1; 31 | 32 | loc1 = 404; 33 | proc_1 (loc1); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /tests/initial_base/TESTLONG.C: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | main() 4 | { long a, d; 5 | 6 | scanf ("%d", &d); 7 | scanf ("%d", &a); 8 | scanf ("%d %d", &a, &d); 9 | printf ("%ld %ld", a, d); 10 | } -------------------------------------------------------------------------------- /tests/initial_base/TESTLONG.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : test\testlong.exe 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | int loc2; 16 | int loc3; 17 | int loc4; 18 | 19 | scanf ("%d", &loc1); 20 | scanf ("%d", &loc2); 21 | scanf ("%d %d", &loc2, &loc1); 22 | printf ("%ld %ld", loc2, loc4, loc1, loc3); 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/inputs_base/BENCHFN.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/BENCHFN.EXE -------------------------------------------------------------------------------- /tests/inputs_base/BENCHLNG.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/BENCHLNG.EXE -------------------------------------------------------------------------------- /tests/inputs_base/BENCHMUL.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/BENCHMUL.EXE -------------------------------------------------------------------------------- /tests/inputs_base/BENCHMUS.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/BENCHMUS.EXE -------------------------------------------------------------------------------- /tests/inputs_base/BENCHSHO.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/BENCHSHO.EXE -------------------------------------------------------------------------------- /tests/inputs_base/BYTEOPS.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/BYTEOPS.EXE -------------------------------------------------------------------------------- /tests/inputs_base/DHAMP.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/DHAMP.EXE -------------------------------------------------------------------------------- /tests/inputs_base/FIBOL.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/FIBOL.EXE -------------------------------------------------------------------------------- /tests/inputs_base/FIBOS.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/FIBOS.EXE -------------------------------------------------------------------------------- /tests/inputs_base/INTOPS.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/INTOPS.EXE -------------------------------------------------------------------------------- /tests/inputs_base/LONGOPS.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/LONGOPS.EXE -------------------------------------------------------------------------------- /tests/inputs_base/MATRIXMU.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/MATRIXMU.EXE -------------------------------------------------------------------------------- /tests/inputs_base/MAX.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/MAX.EXE -------------------------------------------------------------------------------- /tests/inputs_base/MIN.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/MIN.EXE -------------------------------------------------------------------------------- /tests/inputs_base/STRLEN.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/STRLEN.EXE -------------------------------------------------------------------------------- /tests/inputs_base/TESTLONG.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nemerle/dcc/e0585cc7107e68fad07afd63f90d5eb00f65faee/tests/inputs_base/TESTLONG.EXE -------------------------------------------------------------------------------- /tests/prev_base/BENCHFN.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/BENCHFN.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void proc_4 () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | } 15 | 16 | 17 | void proc_3 () 18 | /* Takes no parameters. 19 | * High-level language prologue code. 20 | */ 21 | { 22 | proc_4 (); 23 | proc_4 (); 24 | proc_4 (); 25 | proc_4 (); 26 | proc_4 (); 27 | proc_4 (); 28 | proc_4 (); 29 | proc_4 (); 30 | proc_4 (); 31 | proc_4 (); 32 | } 33 | 34 | 35 | void proc_2 () 36 | /* Takes no parameters. 37 | * High-level language prologue code. 38 | */ 39 | { 40 | proc_3 (); 41 | proc_3 (); 42 | proc_3 (); 43 | proc_3 (); 44 | proc_3 (); 45 | proc_3 (); 46 | proc_3 (); 47 | proc_3 (); 48 | proc_3 (); 49 | proc_3 (); 50 | } 51 | 52 | 53 | void proc_1 () 54 | /* Takes no parameters. 55 | * High-level language prologue code. 56 | */ 57 | { 58 | proc_2 (); 59 | proc_2 (); 60 | proc_2 (); 61 | proc_2 (); 62 | proc_2 (); 63 | proc_2 (); 64 | proc_2 (); 65 | proc_2 (); 66 | proc_2 (); 67 | } 68 | 69 | 70 | void main () 71 | /* Takes no parameters. 72 | * High-level language prologue code. 73 | */ 74 | { 75 | long loc1; 76 | long loc2; 77 | printf ("enter number of iterations "); 78 | scanf ("%ld", &loc0); 79 | printf ("executing %ld iterations\n", loc2); 80 | loc1 = 1; 81 | 82 | while ((loc1 <= loc2)) { 83 | proc_1 (); 84 | loc1 = (loc1 + 1); 85 | } /* end of while */ 86 | printf ("finished\n"); 87 | } 88 | 89 | -------------------------------------------------------------------------------- /tests/prev_base/BENCHMUL.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/BENCHMUL.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | int loc2; 16 | long loc3; 17 | long loc4; 18 | int loc5; 19 | printf ("enter number of iterations\n"); 20 | scanf ("%ld", &loc0); 21 | printf ("executing %ld iterations\n", loc4); 22 | scanf ("%d", &loc1); 23 | scanf ("%d", &loc2); 24 | loc3 = 1; 25 | 26 | while ((loc3 <= loc4)) { 27 | loc5 = 1; 28 | 29 | while ((loc5 <= 40)) { 30 | loc1 = (((((((((((((((((((((((((loc1 * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * 3); 31 | loc5 = (loc5 + 1); 32 | } /* end of while */ 33 | loc3 = (loc3 + 1); 34 | } /* end of while */ 35 | printf ("a=%d\n", loc1); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /tests/prev_base/BENCHMUS.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/BENCHMUS.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | long loc2; 16 | long loc3; 17 | int loc4; 18 | int loc5; 19 | printf ("enter number of iterations\n"); 20 | scanf ("%ld", &loc0); 21 | printf ("executing %ld iterations\n", loc3); 22 | loc4 = 20; 23 | loc1 = loc4; 24 | loc2 = 1; 25 | 26 | while ((loc2 <= loc3)) { 27 | loc5 = 1; 28 | 29 | while ((loc5 <= 40)) { 30 | loc4 = (((((((((((((((((((((((((loc4 * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * 3); 31 | loc5 = (loc5 + 1); 32 | } /* end of while */ 33 | loc2 = (loc2 + 1); 34 | } /* end of while */ 35 | printf ("a=%d\n", loc4); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /tests/prev_base/BENCHSHO.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/BENCHSHO.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | int loc2; 16 | int loc3; 17 | long loc4; 18 | long loc5; 19 | int loc6; /* ax */ 20 | scanf ("%ld", &loc0); 21 | printf ("executing %ld iterations\n", loc5); 22 | scanf ("%ld", &loc1); 23 | scanf ("%ld", &loc2); 24 | loc4 = 1; 25 | 26 | while ((loc4 <= loc5)) { 27 | loc3 = 1; 28 | 29 | while ((loc3 <= 40)) { 30 | loc1 = ((loc1 + loc2) + loc3); 31 | loc2 = (loc1 >> 1); 32 | loc1 = (loc2 % 10); 33 | 34 | if (loc2 == loc3) { 35 | loc6 = 1; 36 | } 37 | else { 38 | loc6 = 0; 39 | } 40 | loc1 = loc6; 41 | loc2 = (loc1 | loc3); 42 | loc1 = !loc2; 43 | loc2 = (loc1 + loc3); 44 | 45 | if (loc2 > loc3) { 46 | loc6 = 1; 47 | } 48 | else { 49 | loc6 = 0; 50 | } 51 | loc1 = loc6; 52 | loc3 = (loc3 + 1); 53 | } /* end of while */ 54 | loc4 = (loc4 + 1); 55 | } /* end of while */ 56 | printf ("a=%d\n", loc1); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /tests/prev_base/BYTEOPS.EXE.a1: -------------------------------------------------------------------------------- 1 | main PROC NEAR 2 | 000 0002FA 55 PUSH bp 3 | 001 0002FB 8BEC MOV bp, sp 4 | 002 0002FD 83EC02 SUB sp, 2 5 | 003 000300 C646FEFF MOV byte ptr [bp-2], 0FFh 6 | 004 000304 C646FF8F MOV byte ptr [bp-1], 8Fh 7 | 005 000308 8A46FE MOV al, [bp-2] 8 | 006 00030B 0246FF ADD al, [bp-1] 9 | 007 00030E 8846FF MOV [bp-1], al 10 | 008 000311 8A46FE MOV al, [bp-2] 11 | 009 000314 2A46FF SUB al, [bp-1] 12 | 010 000317 8846FE MOV [bp-2], al 13 | 011 00031A 8A46FE MOV al, [bp-2] 14 | 012 00031D B400 MOV ah, 0 15 | 013 00031F 8A56FF MOV dl, [bp-1] 16 | 014 000322 B600 MOV dh, 0 17 | 015 000324 F7E2 MUL dx 18 | 016 000326 8846FE MOV [bp-2], al 19 | 017 000329 8A46FF MOV al, [bp-1] 20 | 018 00032C B400 MOV ah, 0 21 | 019 00032E 8A56FE MOV dl, [bp-2] 22 | 020 000331 B600 MOV dh, 0 23 | 021 000333 8BDA MOV bx, dx 24 | 022 000335 99 CWD 25 | 024 000336 F7FB IDIV bx 26 | 026 000338 8846FF MOV [bp-1], al 27 | 027 00033B 8A46FF MOV al, [bp-1] 28 | 028 00033E B400 MOV ah, 0 29 | 029 000340 8A56FE MOV dl, [bp-2] 30 | 030 000343 B600 MOV dh, 0 31 | 031 000345 8BDA MOV bx, dx 32 | 032 000347 99 CWD 33 | 034 000348 F7FB IDIV bx 34 | 036 00034A 8856FF MOV [bp-1], dl 35 | 037 00034D 8A46FE MOV al, [bp-2] 36 | 038 000350 B105 MOV cl, 5 37 | 039 000352 D2E0 SHL al, cl 38 | 040 000354 8846FE MOV [bp-2], al 39 | 041 000357 8A46FF MOV al, [bp-1] 40 | 042 00035A 8A4EFE MOV cl, [bp-2] 41 | 043 00035D D2E8 SHR al, cl 42 | 044 00035F 8846FF MOV [bp-1], al 43 | 045 000362 8A46FF MOV al, [bp-1] 44 | 046 000365 B400 MOV ah, 0 45 | 047 000367 50 PUSH ax 46 | 048 000368 8A46FE MOV al, [bp-2] 47 | 049 00036B B400 MOV ah, 0 48 | 050 00036D 50 PUSH ax 49 | 051 00036E B89401 MOV ax, 194h 50 | 052 000371 50 PUSH ax 51 | 053 000372 E8AB06 CALL near ptr printf 52 | 054 000375 83C406 ADD sp, 6 53 | 055 000378 8BE5 MOV sp, bp 54 | 056 00037A 5D POP bp 55 | 057 00037B C3 RET 56 | 57 | main ENDP 58 | 59 | -------------------------------------------------------------------------------- /tests/prev_base/BYTEOPS.EXE.a2: -------------------------------------------------------------------------------- 1 | main PROC NEAR 2 | 000 0002FA 55 PUSH bp 3 | 001 0002FB 8BEC MOV bp, sp 4 | 002 0002FD 83EC02 SUB sp, 2 5 | 003 000300 C646FEFF MOV byte ptr [bp-2], 0FFh 6 | 004 000304 C646FF8F MOV byte ptr [bp-1], 8Fh 7 | 005 000308 8A46FE MOV al, [bp-2] 8 | 006 00030B 0246FF ADD al, [bp-1] 9 | 007 00030E 8846FF MOV [bp-1], al 10 | 008 000311 8A46FE MOV al, [bp-2] 11 | 009 000314 2A46FF SUB al, [bp-1] 12 | 010 000317 8846FE MOV [bp-2], al 13 | 011 00031A 8A46FE MOV al, [bp-2] 14 | 012 00031D B400 MOV ah, 0 15 | 013 00031F 8A56FF MOV dl, [bp-1] 16 | 014 000322 B600 MOV dh, 0 17 | 015 000324 F7E2 MUL dx 18 | 016 000326 8846FE MOV [bp-2], al 19 | 017 000329 8A46FF MOV al, [bp-1] 20 | 018 00032C B400 MOV ah, 0 21 | 019 00032E 8A56FE MOV dl, [bp-2] 22 | 020 000331 B600 MOV dh, 0 23 | 021 000333 8BDA MOV bx, dx 24 | 022 000335 99 CWD 25 | 023 MOV tmp, dx:ax ;Synthetic inst 26 | 024 000336 F7FB IDIV bx 27 | 025 MOD bx ;Synthetic inst 28 | 026 000338 8846FF MOV [bp-1], al 29 | 027 00033B 8A46FF MOV al, [bp-1] 30 | 028 00033E B400 MOV ah, 0 31 | 029 000340 8A56FE MOV dl, [bp-2] 32 | 030 000343 B600 MOV dh, 0 33 | 031 000345 8BDA MOV bx, dx 34 | 032 000347 99 CWD 35 | 033 MOV tmp, dx:ax ;Synthetic inst 36 | 034 000348 F7FB IDIV bx 37 | 035 MOD bx ;Synthetic inst 38 | 036 00034A 8856FF MOV [bp-1], dl 39 | 037 00034D 8A46FE MOV al, [bp-2] 40 | 038 000350 B105 MOV cl, 5 41 | 039 000352 D2E0 SHL al, cl 42 | 040 000354 8846FE MOV [bp-2], al 43 | 041 000357 8A46FF MOV al, [bp-1] 44 | 042 00035A 8A4EFE MOV cl, [bp-2] 45 | 043 00035D D2E8 SHR al, cl 46 | 044 00035F 8846FF MOV [bp-1], al 47 | 045 000362 8A46FF MOV al, [bp-1] 48 | 046 000365 B400 MOV ah, 0 49 | 047 000367 50 PUSH ax 50 | 048 000368 8A46FE MOV al, [bp-2] 51 | 049 00036B B400 MOV ah, 0 52 | 050 00036D 50 PUSH ax 53 | 051 00036E B89401 MOV ax, 194h 54 | 052 000371 50 PUSH ax 55 | 053 000372 E8AB06 CALL near ptr printf 56 | 054 000375 83C406 ADD sp, 6 57 | 055 000378 8BE5 MOV sp, bp 58 | 056 00037A 5D POP bp 59 | 057 00037B C3 RET 60 | 61 | main ENDP 62 | 63 | -------------------------------------------------------------------------------- /tests/prev_base/BYTEOPS.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/BYTEOPS.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | int loc2; 16 | loc1 = 255; 17 | loc2 = 143; 18 | loc2 = (loc1 + loc2); 19 | loc1 = (loc1 - loc2); 20 | loc1 = (loc1 * loc2); 21 | loc2 = (loc2 / loc1); 22 | loc2 = (loc2 % loc1); 23 | loc1 = (loc1 << 5); 24 | loc2 = (loc2 >> loc1); 25 | printf ("a = %d, b = %d\n", loc1, loc2); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /tests/prev_base/FIBOL.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/FIBOL.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | int proc_1 (int arg0) 10 | /* Takes 2 bytes of parameters. 11 | * High-level language prologue code. 12 | * C calling convention. 13 | */ 14 | { 15 | int loc1; /* si */ 16 | int loc2; /* ax */ 17 | loc1 = arg0; 18 | 19 | if (loc1 > 2) { 20 | loc2 = (proc_1 ((loc1 - 1)) + proc_1 ((loc1 + 0xfffe))); 21 | } 22 | else { 23 | loc2 = 1; 24 | } 25 | return (loc2); 26 | } 27 | 28 | 29 | void main () 30 | /* Takes no parameters. 31 | * High-level language prologue code. 32 | * Contains instructions not normally used by compilers. 33 | */ 34 | { 35 | int loc1; 36 | int loc2; 37 | int loc3; 38 | int loc4; 39 | printf ("Input number of iterations: "); 40 | scanf ("%d", &loc1, ); 41 | loc3 = 1; 42 | 43 | while ((loc3 <= loc1)) { 44 | printf ("Input number: "); 45 | scanf ("%d", &loc2, ); 46 | printf ("fibonacci(%d) = %u\n", loc2, proc_1 (loc2)); 47 | loc3 = (loc3 + 1); 48 | } /* end of while */ 49 | exit (0); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /tests/prev_base/FIBOS.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/FIBOS.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | int proc_1 (int arg0) 10 | /* Takes 2 bytes of parameters. 11 | * High-level language prologue code. 12 | * C calling convention. 13 | */ 14 | { 15 | int loc1; /* si */ 16 | int loc2; /* ax */ 17 | loc1 = arg0; 18 | 19 | if (loc1 > 2) { 20 | loc2 = (proc_1 ((loc1 - 1)) + proc_1 ((loc1 + 0xfffe))); 21 | } 22 | else { 23 | loc2 = 1; 24 | } 25 | return (loc2); 26 | } 27 | 28 | 29 | void main () 30 | /* Takes no parameters. 31 | * High-level language prologue code. 32 | */ 33 | { 34 | int loc1; 35 | int loc2; 36 | int loc3; 37 | int loc4; 38 | printf ("Input number of iterations: "); 39 | scanf ("%d", &loc1); 40 | loc3 = 1; 41 | 42 | while ((loc3 <= loc1)) { 43 | printf ("Input number: "); 44 | scanf ("%d", &loc2); 45 | printf ("fibonacci(%d) = %u\n", loc2, proc_1 (loc2)); 46 | loc3 = (loc3 + 1); 47 | } /* end of while */ 48 | exit (0); 49 | } 50 | 51 | -------------------------------------------------------------------------------- /tests/prev_base/INTOPS.EXE.a1: -------------------------------------------------------------------------------- 1 | main PROC NEAR 2 | 000 0002FA 55 PUSH bp 3 | 001 0002FB 8BEC MOV bp, sp 4 | 002 0002FD 83EC02 SUB sp, 2 5 | 003 000300 56 PUSH si 6 | 004 000301 C746FEFF00 MOV word ptr [bp-2], 0FFh 7 | 005 000306 BE8F00 MOV si, 8Fh 8 | 006 000309 8B46FE MOV ax, [bp-2] 9 | 007 00030C 03C6 ADD ax, si 10 | 008 00030E 8BF0 MOV si, ax 11 | 009 000310 8B46FE MOV ax, [bp-2] 12 | 010 000313 2BC6 SUB ax, si 13 | 011 000315 8946FE MOV [bp-2], ax 14 | 012 000318 8B46FE MOV ax, [bp-2] 15 | 013 00031B F7E6 MUL si 16 | 014 00031D 8946FE MOV [bp-2], ax 17 | 015 000320 8BC6 MOV ax, si 18 | 016 000322 99 CWD 19 | 018 000323 F77EFE IDIV word ptr [bp-2] 20 | 020 000326 8BF0 MOV si, ax 21 | 021 000328 8BC6 MOV ax, si 22 | 022 00032A 99 CWD 23 | 024 00032B F77EFE IDIV word ptr [bp-2] 24 | 026 00032E 8BF2 MOV si, dx 25 | 027 000330 8B46FE MOV ax, [bp-2] 26 | 028 000333 B105 MOV cl, 5 27 | 029 000335 D3E0 SHL ax, cl 28 | 030 000337 8946FE MOV [bp-2], ax 29 | 031 00033A 8BC6 MOV ax, si 30 | 032 00033C 8A4EFE MOV cl, [bp-2] 31 | 033 00033F D3F8 SAR ax, cl 32 | 034 000341 8BF0 MOV si, ax 33 | 035 000343 56 PUSH si 34 | 036 000344 FF76FE PUSH word ptr [bp-2] 35 | 037 000347 B89401 MOV ax, 194h 36 | 038 00034A 50 PUSH ax 37 | 039 00034B E8AC06 CALL near ptr printf 38 | 040 00034E 83C406 ADD sp, 6 39 | 041 000351 5E POP si 40 | 042 000352 8BE5 MOV sp, bp 41 | 043 000354 5D POP bp 42 | 044 000355 C3 RET 43 | 44 | main ENDP 45 | 46 | -------------------------------------------------------------------------------- /tests/prev_base/INTOPS.EXE.a2: -------------------------------------------------------------------------------- 1 | main PROC NEAR 2 | 000 0002FA 55 PUSH bp 3 | 001 0002FB 8BEC MOV bp, sp 4 | 002 0002FD 83EC02 SUB sp, 2 5 | 003 000300 56 PUSH si 6 | 004 000301 C746FEFF00 MOV word ptr [bp-2], 0FFh 7 | 005 000306 BE8F00 MOV si, 8Fh 8 | 006 000309 8B46FE MOV ax, [bp-2] 9 | 007 00030C 03C6 ADD ax, si 10 | 008 00030E 8BF0 MOV si, ax 11 | 009 000310 8B46FE MOV ax, [bp-2] 12 | 010 000313 2BC6 SUB ax, si 13 | 011 000315 8946FE MOV [bp-2], ax 14 | 012 000318 8B46FE MOV ax, [bp-2] 15 | 013 00031B F7E6 MUL si 16 | 014 00031D 8946FE MOV [bp-2], ax 17 | 015 000320 8BC6 MOV ax, si 18 | 016 000322 99 CWD 19 | 017 MOV tmp, dx:ax ;Synthetic inst 20 | 018 000323 F77EFE IDIV word ptr [bp-2] 21 | 019 MOD word ptr [bp-2] ;Synthetic inst 22 | 020 000326 8BF0 MOV si, ax 23 | 021 000328 8BC6 MOV ax, si 24 | 022 00032A 99 CWD 25 | 023 MOV tmp, dx:ax ;Synthetic inst 26 | 024 00032B F77EFE IDIV word ptr [bp-2] 27 | 025 MOD word ptr [bp-2] ;Synthetic inst 28 | 026 00032E 8BF2 MOV si, dx 29 | 027 000330 8B46FE MOV ax, [bp-2] 30 | 028 000333 B105 MOV cl, 5 31 | 029 000335 D3E0 SHL ax, cl 32 | 030 000337 8946FE MOV [bp-2], ax 33 | 031 00033A 8BC6 MOV ax, si 34 | 032 00033C 8A4EFE MOV cl, [bp-2] 35 | 033 00033F D3F8 SAR ax, cl 36 | 034 000341 8BF0 MOV si, ax 37 | 035 000343 56 PUSH si 38 | 036 000344 FF76FE PUSH word ptr [bp-2] 39 | 037 000347 B89401 MOV ax, 194h 40 | 038 00034A 50 PUSH ax 41 | 039 00034B E8AC06 CALL near ptr printf 42 | 040 00034E 83C406 ADD sp, 6 43 | 041 000351 5E POP si 44 | 042 000352 8BE5 MOV sp, bp 45 | 043 000354 5D POP bp 46 | 044 000355 C3 RET 47 | 48 | main ENDP 49 | 50 | -------------------------------------------------------------------------------- /tests/prev_base/INTOPS.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/INTOPS.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | int loc2; 16 | loc1 = 255; 17 | loc2 = (loc1 + 143); 18 | loc1 = (loc1 - loc2); 19 | loc1 = (loc1 * loc2); 20 | loc1 = (loc1 << 5); 21 | printf ("a = %d, b = %d\n", loc1, (((loc2 / loc1) % loc1) >> loc1)); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /tests/prev_base/MATRIXMU.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/MATRIXMU.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void proc_1 (int arg0, int arg1, int arg2) 10 | /* Takes 6 bytes of parameters. 11 | * High-level language prologue code. 12 | * C calling convention. 13 | */ 14 | { 15 | int loc1; 16 | int loc2; 17 | int loc3; 18 | 19 | loc2 = 0; 20 | while ((loc2 < 5)) { 21 | loc3 = 0; 22 | while ((loc3 < 4)) { 23 | loc1 = 0; 24 | while ((loc1 < 4)) { 25 | *((((loc2 * 10) + arg2) + (loc3 << 1))) = ((*((((loc2 << 3) + arg0) + (loc1 << 1))) * *((((loc1 * 10) + arg1) + (loc3 << 1)))) + *((((loc2 * 10) + arg2) + (loc3 << 1)))); 26 | loc1 = (loc1 + 1); 27 | } /* end of while */ 28 | loc3 = (loc3 + 1); 29 | } /* end of while */ 30 | loc2 = (loc2 + 1); 31 | } /* end of while */ 32 | } 33 | 34 | 35 | void main () 36 | /* Takes no parameters. 37 | * High-level language prologue code. 38 | */ 39 | { 40 | int loc1; 41 | int loc2; 42 | int loc3; 43 | 44 | proc_1 (&loc3, &loc2, &loc1); 45 | } 46 | 47 | -------------------------------------------------------------------------------- /tests/prev_base/MAX.EXE.a1: -------------------------------------------------------------------------------- 1 | main PROC NEAR 2 | 000 0002FA 55 PUSH bp 3 | 001 0002FB 8BEC MOV bp, sp 4 | 002 0002FD 83EC04 SUB sp, 4 5 | 003 000300 B89401 MOV ax, 194h 6 | 004 000303 50 PUSH ax 7 | 005 000304 E8D10B CALL near ptr printf 8 | 006 000307 59 POP cx 9 | 007 000308 8D46FE LEA ax, [bp-2] 10 | 008 00030B 50 PUSH ax 11 | 009 00030C 8D46FC LEA ax, [bp-4] 12 | 010 00030F 50 PUSH ax 13 | 011 000310 B8A601 MOV ax, 1A6h 14 | 012 000313 50 PUSH ax 15 | 013 000314 E84A14 CALL near ptr scanf 16 | 014 000317 83C406 ADD sp, 6 17 | 015 00031A 8B46FC MOV ax, [bp-4] 18 | 016 00031D 3B46FE CMP ax, [bp-2] 19 | 017 000320 7415 JE L1 20 | 018 000322 FF76FE PUSH word ptr [bp-2] 21 | 019 000325 FF76FC PUSH word ptr [bp-4] 22 | 020 000328 E81000 CALL near ptr proc_1 23 | 021 00032B 59 POP cx 24 | 022 00032C 59 POP cx 25 | 023 00032D 50 PUSH ax 26 | 024 00032E B8AC01 MOV ax, 1ACh 27 | 025 000331 50 PUSH ax 28 | 026 000332 E8A30B CALL near ptr printf 29 | 027 000335 59 POP cx 30 | 028 000336 59 POP cx 31 | 32 | 029 000337 8BE5 L1: MOV sp, bp 33 | 030 000339 5D POP bp 34 | 031 00033A C3 RET 35 | 36 | main ENDP 37 | 38 | proc_1 PROC NEAR 39 | 000 00033B 55 PUSH bp 40 | 001 00033C 8BEC MOV bp, sp 41 | 002 00033E 8B4604 MOV ax, [bp+4] 42 | 003 000341 3B4606 CMP ax, [bp+6] 43 | 004 000344 7E05 JLE L2 44 | 005 000346 8B4604 MOV ax, [bp+4] 45 | 006 000349 EB05 JMP L3 46 | 47 | 007 000350 5D L3: POP bp 48 | 008 000351 C3 RET 49 | 50 | 009 00034B 8B4606 L2: MOV ax, [bp+6] 51 | 010 00034E EB00 JMP L3 52 | 53 | proc_1 ENDP 54 | 55 | -------------------------------------------------------------------------------- /tests/prev_base/MAX.EXE.a2: -------------------------------------------------------------------------------- 1 | proc_1 PROC NEAR 2 | 000 00033B 55 PUSH bp 3 | 001 00033C 8BEC MOV bp, sp 4 | 002 00033E 8B4604 MOV ax, [bp+4] 5 | 003 000341 3B4606 CMP ax, [bp+6] 6 | 004 000344 7E05 JLE L1 7 | 005 000346 8B4604 MOV ax, [bp+4] 8 | 9 | 007 000350 5D L2: POP bp 10 | 008 000351 C3 RET 11 | 12 | 009 00034B 8B4606 L1: MOV ax, [bp+6] 13 | 010 00034E EB00 JMP L2 14 | 15 | proc_1 ENDP 16 | 17 | main PROC NEAR 18 | 000 0002FA 55 PUSH bp 19 | 001 0002FB 8BEC MOV bp, sp 20 | 002 0002FD 83EC04 SUB sp, 4 21 | 003 000300 B89401 MOV ax, 194h 22 | 004 000303 50 PUSH ax 23 | 005 000304 E8D10B CALL near ptr printf 24 | 006 000307 59 POP cx 25 | 007 000308 8D46FE LEA ax, [bp-2] 26 | 008 00030B 50 PUSH ax 27 | 009 00030C 8D46FC LEA ax, [bp-4] 28 | 010 00030F 50 PUSH ax 29 | 011 000310 B8A601 MOV ax, 1A6h 30 | 012 000313 50 PUSH ax 31 | 013 000314 E84A14 CALL near ptr scanf 32 | 014 000317 83C406 ADD sp, 6 33 | 015 00031A 8B46FC MOV ax, [bp-4] 34 | 016 00031D 3B46FE CMP ax, [bp-2] 35 | 017 000320 7415 JE L3 36 | 018 000322 FF76FE PUSH word ptr [bp-2] 37 | 019 000325 FF76FC PUSH word ptr [bp-4] 38 | 020 000328 E81000 CALL near ptr proc_1 39 | 021 00032B 59 POP cx 40 | 022 00032C 59 POP cx 41 | 023 00032D 50 PUSH ax 42 | 024 00032E B8AC01 MOV ax, 1ACh 43 | 025 000331 50 PUSH ax 44 | 026 000332 E8A30B CALL near ptr printf 45 | 027 000335 59 POP cx 46 | 028 000336 59 POP cx 47 | 48 | 029 000337 8BE5 L3: MOV sp, bp 49 | 030 000339 5D POP bp 50 | 031 00033A C3 RET 51 | 52 | main ENDP 53 | 54 | -------------------------------------------------------------------------------- /tests/prev_base/MAX.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/MAX.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | int proc_1 (int arg0, int arg1) 10 | /* Takes 4 bytes of parameters. 11 | * High-level language prologue code. 12 | * C calling convention. 13 | */ 14 | { 15 | int loc1; /* ax */ 16 | 17 | if (arg0 > arg1) { 18 | loc1 = arg0; 19 | } 20 | else { 21 | loc1 = arg1; 22 | } 23 | return (loc1); 24 | } 25 | 26 | 27 | void main () 28 | /* Takes no parameters. 29 | * High-level language prologue code. 30 | */ 31 | { 32 | int loc1; 33 | int loc2; 34 | printf ("Enter 2 numbers: "); 35 | scanf ("%d %d", &loc2, &loc1); 36 | 37 | if (loc2 != loc1) { 38 | printf ("Maximum: %d\n", proc_1 (loc2, loc1)); 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /tests/prev_base/MIN.EXE.a1: -------------------------------------------------------------------------------- 1 | start PROC NEAR 2 | 000 000100 55 PUSH bp 3 | 001 000101 8BEC MOV bp, sp 4 | 002 000103 83EC02 SUB sp, 2 5 | 003 000106 C746FE0000 MOV word ptr [bp-2], 0 6 | 004 00010B 8B46FE MOV ax, [bp-2] 7 | 005 00010E 3D0600 CMP ax, 6 8 | 006 000111 7735 JA L1 9 | 007 000113 8BD8 MOV bx, ax 10 | 008 000115 D1E3 SHL bx, 1 11 | 009 000117 2EFFA71C00 JMP word ptr cs:[bx+1Ch];Switch 12 | 13 | 010 00012A B80200 MOV ax, 2 ;Case l0 14 | 011 00012D EB1E JMP L2 15 | 16 | 012 00014D 8BE5 L2: MOV sp, bp 17 | 013 00014F 5D POP bp 18 | 014 000150 C3 RET 19 | 20 | 015 00012F B80300 MOV ax, 3 ;Case l1 21 | 016 000132 EB19 JMP L2 22 | 23 | 017 000134 B80700 MOV ax, 7 ;Case l2 24 | 018 000137 EB14 JMP L2 25 | 26 | 019 000139 B80D00 MOV ax, 0Dh ;Case l3 27 | 020 00013C EB0F JMP L2 28 | 29 | 021 000148 B82C00 L1: MOV ax, 2Ch ;Case l4 30 | 022 00014B EB00 JMP L2 31 | 32 | 023 00013E B81700 MOV ax, 17h ;Case l5 33 | 024 000141 EB0A JMP L2 34 | 35 | 025 000143 B80D00 MOV ax, 0Dh ;Case l6 36 | 026 000146 EB05 JMP L2 37 | 38 | start ENDP 39 | 40 | -------------------------------------------------------------------------------- /tests/prev_base/MIN.EXE.a2: -------------------------------------------------------------------------------- 1 | start PROC NEAR 2 | 000 000100 55 PUSH bp 3 | 001 000101 8BEC MOV bp, sp 4 | 002 000103 83EC02 SUB sp, 2 5 | 003 000106 C746FE0000 MOV word ptr [bp-2], 0 6 | 004 00010B 8B46FE MOV ax, [bp-2] 7 | 005 00010E 3D0600 CMP ax, 6 8 | 006 000111 7735 JA L1 9 | 007 000113 8BD8 MOV bx, ax 10 | 008 000115 D1E3 SHL bx, 1 11 | 009 000117 2EFFA71C00 JMP word ptr cs:[bx+1Ch];Switch 12 | 13 | 010 00012A B80200 MOV ax, 2 ;Case l0 14 | 15 | 012 00014D 8BE5 L2: MOV sp, bp 16 | 013 00014F 5D POP bp 17 | 014 000150 C3 RET 18 | 19 | 015 00012F B80300 MOV ax, 3 ;Case l1 20 | 016 000132 EB19 JMP L2 21 | 22 | 017 000134 B80700 MOV ax, 7 ;Case l2 23 | 018 000137 EB14 JMP L2 24 | 25 | 019 000139 B80D00 MOV ax, 0Dh ;Case l3 26 | 020 00013C EB0F JMP L2 27 | 28 | 021 000148 B82C00 L1: MOV ax, 2Ch ;Case l4 29 | 022 00014B EB00 JMP L2 30 | 31 | 023 00013E B81700 MOV ax, 17h ;Case l5 32 | 024 000141 EB0A JMP L2 33 | 34 | 025 000143 B80D00 MOV ax, 0Dh ;Case l6 35 | 026 000146 EB05 JMP L2 36 | 37 | start ENDP 38 | 39 | -------------------------------------------------------------------------------- /tests/prev_base/MIN.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/MIN.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void start () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | int loc2; /* ax */ 16 | int loc3; /* bx */ 17 | loc1 = 0; 18 | loc2 = loc1; 19 | 20 | if (loc2 <= 6) { 21 | loc3 = loc2; 22 | } 23 | else { 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /tests/prev_base/STRLEN.EXE.a1: -------------------------------------------------------------------------------- 1 | main PROC NEAR 2 | 000 0002FA 56 PUSH si 3 | 001 0002FB BE9401 MOV si, 194h 4 | 002 0002FE 56 PUSH si 5 | 003 0002FF E80300 CALL near ptr proc_1 6 | 004 000302 59 POP cx 7 | 005 000303 5E POP si 8 | 006 000304 C3 RET 9 | 10 | main ENDP 11 | 12 | proc_1 PROC NEAR 13 | 000 000305 55 PUSH bp 14 | 001 000306 8BEC MOV bp, sp 15 | 002 000308 56 PUSH si 16 | 003 000309 33F6 XOR si, si 17 | 004 00030B EB01 JMP L1 18 | 19 | 005 00030E 8B5E04 L1: MOV bx, [bp+4] 20 | 006 000311 FF4604 INC word ptr [bp+4] 21 | 007 000314 803F00 CMP byte ptr [bx], 0 22 | 008 000317 75F4 JNE L2 23 | 009 000319 8BC6 MOV ax, si 24 | 010 00031B EB00 JMP L3 25 | 26 | 011 00031D 5E L3: POP si 27 | 012 00031E 5D POP bp 28 | 013 00031F C3 RET 29 | 30 | 014 00030D 46 L2: INC si 31 | 015 JMP L1 ;Synthetic inst 32 | 33 | proc_1 ENDP 34 | 35 | -------------------------------------------------------------------------------- /tests/prev_base/STRLEN.EXE.a2: -------------------------------------------------------------------------------- 1 | proc_1 PROC NEAR 2 | 000 000305 55 PUSH bp 3 | 001 000306 8BEC MOV bp, sp 4 | 002 000308 56 PUSH si 5 | 003 000309 33F6 XOR si, si 6 | 7 | 005 00030E 8B5E04 L1: MOV bx, [bp+4] 8 | 006 000311 FF4604 INC word ptr [bp+4] 9 | 007 000314 803F00 CMP byte ptr [bx], 0 10 | 008 000317 75F4 JNE L2 11 | 009 000319 8BC6 MOV ax, si 12 | 011 00031D 5E POP si 13 | 012 00031E 5D POP bp 14 | 013 00031F C3 RET 15 | 16 | 014 00030D 46 L2: INC si 17 | 015 JMP L1 ;Synthetic inst 18 | 19 | proc_1 ENDP 20 | 21 | main PROC NEAR 22 | 000 0002FA 56 PUSH si 23 | 001 0002FB BE9401 MOV si, 194h 24 | 002 0002FE 56 PUSH si 25 | 003 0002FF E80300 CALL near ptr proc_1 26 | 004 000302 59 POP cx 27 | 005 000303 5E POP si 28 | 006 000304 C3 RET 29 | 30 | main ENDP 31 | 32 | -------------------------------------------------------------------------------- /tests/prev_base/STRLEN.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/STRLEN.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void proc_1 (int arg0) 10 | /* Takes 2 bytes of parameters. 11 | * High-level language prologue code. 12 | * C calling convention. 13 | */ 14 | { 15 | int loc1; /* si */ 16 | loc1 = 0; 17 | arg0 = (arg0 + 1); 18 | 19 | while ((*arg0 != 0)) { 20 | loc1 = (loc1 + 1); 21 | arg0 = (arg0 + 1); 22 | } /* end of while */ 23 | } 24 | 25 | 26 | void main () 27 | /* Takes no parameters. 28 | */ 29 | { 30 | int loc1; 31 | loc1 = 404; 32 | proc_1 (loc1); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /tests/prev_base/TESTLONG.EXE.a1: -------------------------------------------------------------------------------- 1 | main PROC NEAR 2 | 000 0002FA 55 PUSH bp 3 | 001 0002FB 8BEC MOV bp, sp 4 | 002 0002FD 83EC08 SUB sp, 8 5 | 003 000300 8D46FC LEA ax, [bp-4] 6 | 004 000303 50 PUSH ax 7 | 005 000304 B89401 MOV ax, 194h 8 | 006 000307 50 PUSH ax 9 | 007 000308 E84A14 CALL near ptr scanf 10 | 008 00030B 59 POP cx 11 | 009 00030C 59 POP cx 12 | 010 00030D 8D46F8 LEA ax, [bp-8] 13 | 011 000310 50 PUSH ax 14 | 012 000311 B89701 MOV ax, 197h 15 | 013 000314 50 PUSH ax 16 | 014 000315 E83D14 CALL near ptr scanf 17 | 015 000318 59 POP cx 18 | 016 000319 59 POP cx 19 | 017 00031A 8D46FC LEA ax, [bp-4] 20 | 018 00031D 50 PUSH ax 21 | 019 00031E 8D46F8 LEA ax, [bp-8] 22 | 020 000321 50 PUSH ax 23 | 021 000322 B89A01 MOV ax, 19Ah 24 | 022 000325 50 PUSH ax 25 | 023 000326 E82C14 CALL near ptr scanf 26 | 024 000329 83C406 ADD sp, 6 27 | 025 00032C FF76FE PUSH word ptr [bp-2] 28 | 026 00032F FF76FC PUSH word ptr [bp-4] 29 | 027 000332 FF76FA PUSH word ptr [bp-6] 30 | 028 000335 FF76F8 PUSH word ptr [bp-8] 31 | 029 000338 B8A001 MOV ax, 1A0h 32 | 030 00033B 50 PUSH ax 33 | 031 00033C E88D0B CALL near ptr printf 34 | 032 00033F 83C40A ADD sp, 0Ah 35 | 033 000342 8BE5 MOV sp, bp 36 | 034 000344 5D POP bp 37 | 035 000345 C3 RET 38 | 39 | main ENDP 40 | 41 | -------------------------------------------------------------------------------- /tests/prev_base/TESTLONG.EXE.a2: -------------------------------------------------------------------------------- 1 | main PROC NEAR 2 | 000 0002FA 55 PUSH bp 3 | 001 0002FB 8BEC MOV bp, sp 4 | 002 0002FD 83EC08 SUB sp, 8 5 | 003 000300 8D46FC LEA ax, [bp-4] 6 | 004 000303 50 PUSH ax 7 | 005 000304 B89401 MOV ax, 194h 8 | 006 000307 50 PUSH ax 9 | 007 000308 E84A14 CALL near ptr scanf 10 | 008 00030B 59 POP cx 11 | 009 00030C 59 POP cx 12 | 010 00030D 8D46F8 LEA ax, [bp-8] 13 | 011 000310 50 PUSH ax 14 | 012 000311 B89701 MOV ax, 197h 15 | 013 000314 50 PUSH ax 16 | 014 000315 E83D14 CALL near ptr scanf 17 | 015 000318 59 POP cx 18 | 016 000319 59 POP cx 19 | 017 00031A 8D46FC LEA ax, [bp-4] 20 | 018 00031D 50 PUSH ax 21 | 019 00031E 8D46F8 LEA ax, [bp-8] 22 | 020 000321 50 PUSH ax 23 | 021 000322 B89A01 MOV ax, 19Ah 24 | 022 000325 50 PUSH ax 25 | 023 000326 E82C14 CALL near ptr scanf 26 | 024 000329 83C406 ADD sp, 6 27 | 025 00032C FF76FE PUSH word ptr [bp-2] 28 | 026 00032F FF76FC PUSH word ptr [bp-4] 29 | 027 000332 FF76FA PUSH word ptr [bp-6] 30 | 028 000335 FF76F8 PUSH word ptr [bp-8] 31 | 029 000338 B8A001 MOV ax, 1A0h 32 | 030 00033B 50 PUSH ax 33 | 031 00033C E88D0B CALL near ptr printf 34 | 032 00033F 83C40A ADD sp, 0Ah 35 | 033 000342 8BE5 MOV sp, bp 36 | 034 000344 5D POP bp 37 | 035 000345 C3 RET 38 | 39 | main ENDP 40 | 41 | -------------------------------------------------------------------------------- /tests/prev_base/TESTLONG.b: -------------------------------------------------------------------------------- 1 | /* 2 | * Input file : ./tests/inputs/TESTLONG.EXE 3 | * File type : EXE 4 | */ 5 | 6 | #include "dcc.h" 7 | 8 | 9 | void main () 10 | /* Takes no parameters. 11 | * High-level language prologue code. 12 | */ 13 | { 14 | int loc1; 15 | int loc2; 16 | int loc3; 17 | int loc4; 18 | scanf ("%d", &loc1); 19 | scanf ("%d", &loc2); 20 | scanf ("%d %d", &loc2, &loc1); 21 | printf ("%ld %ld", loc2, loc4, loc1, loc3); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(dispsrch) 2 | add_subdirectory(makedsig) 3 | add_subdirectory(readsig) 4 | add_subdirectory(parsehdr) 5 | add_subdirectory(regression_tester) 6 | -------------------------------------------------------------------------------- /tools/dispsrch/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(dispsig dispsig) 2 | target_link_libraries(dispsig dcc_hash Qt5::Core) 3 | 4 | add_executable(srchsig srchsig) 5 | target_link_libraries(srchsig dcc_hash dcc_lib Qt5::Core) 6 | 7 | -------------------------------------------------------------------------------- /tools/dispsrch/dispsig.mak: -------------------------------------------------------------------------------- 1 | CFLAGS = -Zi -c -AL -W3 -D__MSDOS__ 2 | 3 | dispsig.exe: dispsig.obj perfhlib.obj 4 | link /CO dispsig perfhlib; 5 | 6 | dispsig.obj: dispsig.c dcc.h perfhlib.h 7 | cl $(CFLAGS) $*.c 8 | 9 | perfhlib.obj: perfhlib.c dcc.h perfhlib.h 10 | cl $(CFLAGS) $*.c 11 | 12 | -------------------------------------------------------------------------------- /tools/dispsrch/srchsig.mak: -------------------------------------------------------------------------------- 1 | CFLAGS = -Zi -c -AL -W3 -D__MSDOS__ 2 | 3 | srchsig.exe: srchsig.obj perfhlib.obj fixwild.obj 4 | link /CO srchsig perfhlib fixwild; 5 | 6 | srchsig.obj: srchsig.c dcc.h perfhlib.h 7 | cl $(CFLAGS) $*.c 8 | 9 | perfhlib.obj: perfhlib.c dcc.h perfhlib.h 10 | cl $(CFLAGS) $*.c 11 | 12 | fixwild.obj: fixwild.c dcc.h 13 | cl $(CFLAGS) $*.c 14 | 15 | -------------------------------------------------------------------------------- /tools/makedsig/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRC 2 | makedsig 3 | fixwild.cpp 4 | LIB_PatternCollector.cpp 5 | LIB_PatternCollector.h 6 | TPL_PatternCollector.cpp 7 | TPL_PatternCollector.h 8 | ) 9 | add_executable(makedsig ${SRC}) 10 | target_link_libraries(makedsig dcc_hash Qt5::Core) 11 | 12 | -------------------------------------------------------------------------------- /tools/makedsig/LIB_PatternCollector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PatternCollector.h" 4 | 5 | struct LIB_PatternCollector : public PatternCollector 6 | { 7 | protected: 8 | unsigned long offset; 9 | uint8_t lnum = 0; /* Count of LNAMES so far */ 10 | uint8_t segnum = 0; /* Count of SEGDEFs so far */ 11 | uint8_t codeLNAMES; /* Index of the LNAMES for "CODE" class */ 12 | uint8_t codeSEGDEF; /* Index of the first SEGDEF that has class CODE */ 13 | #define NONE 0xFF /* Improbable segment index */ 14 | uint8_t *leData; /* Pointer to 64K of alloc'd data. Some .lib files 15 | have the symbols (PUBDEFs) *after* the data 16 | (LEDATA), so you need to keep the data here */ 17 | uint16_t maxLeData; /* How much data we have in there */ 18 | /* read a length then string to buf[]; make it an asciiz string */ 19 | void readString( FILE *fl); 20 | 21 | public: 22 | /* Read the .lib file, and put the keys into the array *keys[]. Returns the count */ 23 | int readSyms(FILE *fl); 24 | 25 | }; 26 | -------------------------------------------------------------------------------- /tools/makedsig/TPL_PatternCollector.h: -------------------------------------------------------------------------------- 1 | #ifndef TPL_PATTERNCOLLECTOR_H 2 | #define TPL_PATTERNCOLLECTOR_H 3 | #include "PatternCollector.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | struct TPL_PatternCollector : public PatternCollector { 10 | protected: 11 | uint16_t cmap, pmap, csegBase, unitBase; 12 | uint16_t offStCseg, skipPmap; 13 | int count = 0; 14 | int cAllocSym = 0; 15 | int unitNum = 0; 16 | char version, charProc, charFunc; 17 | uint16_t csegoffs[100]; 18 | uint16_t csegIdx; 19 | std::vector positionStack; 20 | 21 | void enterSym(FILE *f,const char *name, uint16_t pmapOffset); 22 | void allocSym(int count); 23 | void readCmapOffsets(FILE *f); 24 | void enterSystemUnit(FILE *f); 25 | void readString(FILE *f); 26 | void unknown(FILE *f,unsigned j, unsigned k); 27 | void nextUnit(FILE *f); 28 | void setVersionSpecifics(void); 29 | void savePos(FILE *f); 30 | void restorePos(FILE *f); 31 | void enterUnitProcs(FILE *f); 32 | public: 33 | /* Read the .tpl file, and put the keys into the array *keys[]. Returns the count */ 34 | int readSyms(FILE *f); 35 | }; 36 | 37 | #endif // TPL_PATTERNCOLLECTOR_H 38 | 39 | -------------------------------------------------------------------------------- /tools/parsehdr/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(parselib parsehdr.cpp) 2 | 3 | target_link_libraries(parselib dcc_hash Qt5::Core) 4 | 5 | -------------------------------------------------------------------------------- /tools/parsehdr/locident.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /*$Log: locident.h,v $ 3 | * Revision 1.6 94/02/22 15:20:23 cifuente 4 | * Code generation is done. 5 | * 6 | * Revision 1.5 93/12/10 09:38:20 cifuente 7 | * New high-level types 8 | * 9 | * Revision 1.4 93/11/10 17:30:51 cifuente 10 | * Procedure header, locals 11 | * 12 | * Revision 1.3 93/11/08 12:06:35 cifuente 13 | * du1 analysis finished. Instantiates procedure arguments for user 14 | * declared procedures. 15 | * 16 | * Revision 1.2 93/10/25 11:01:00 cifuente 17 | * New SYNTHETIC instructions for d/u analysis 18 | * 19 | * Revision 1.1 93/10/11 11:47:39 cifuente 20 | * Initial revision 21 | * 22 | * File: locIdent.h 23 | * Purpose: High-level local identifier definitions 24 | * Date: October 1993 25 | */ 26 | 27 | 28 | /* Type definition */ 29 | typedef struct { 30 | Int csym; /* # symbols used */ 31 | Int alloc; /* # symbols allocated */ 32 | Int *idx; /* Array of integer indexes */ 33 | } IDX_ARRAY; 34 | 35 | /* Type definitions used in the decompiled program */ 36 | typedef enum { 37 | TYPE_UNKNOWN = 0, /* unknown so far */ 38 | TYPE_BYTE_SIGN, /* signed byte (8 bits) */ 39 | TYPE_BYTE_UNSIGN, /* unsigned byte */ 40 | TYPE_WORD_SIGN, /* signed word (16 bits) */ 41 | TYPE_WORD_UNSIGN, /* unsigned word (16 bits) */ 42 | TYPE_LONG_SIGN, /* signed long (32 bits) */ 43 | TYPE_LONG_UNSIGN, /* unsigned long (32 bits) */ 44 | TYPE_RECORD, /* record structure */ 45 | TYPE_PTR, /* pointer (32 bit ptr) */ 46 | TYPE_STR, /* string */ 47 | TYPE_CONST, /* constant (any type) */ 48 | TYPE_FLOAT, /* floating point */ 49 | TYPE_DOUBLE, /* double precision float */ 50 | } hlType; 51 | 52 | static char *hlTypes[13] = {"", "char", "unsigned char", "int", "unsigned int", 53 | "long", "unsigned long", "record", "int *", "char *", 54 | "", "float", "double"}; 55 | 56 | typedef enum { 57 | STK_FRAME, /* For stack vars */ 58 | REG_FRAME, /* For register variables */ 59 | GLB_FRAME, /* For globals */ 60 | } frameType; 61 | 62 | 63 | /* Enumeration to determine whether pIcode points to the high or low part 64 | * of a long number */ 65 | typedef enum { 66 | HIGH_FIRST, /* High value is first */ 67 | LOW_FIRST, /* Low value is first */ 68 | } hlFirst; 69 | 70 | 71 | /* LOCAL_ID */ 72 | typedef struct { 73 | hlType type; /* Probable type */ 74 | boolT illegal;/* Boolean: not a valid field any more */ 75 | IDX_ARRAY idx; /* Index into icode array (REG_FRAME only) */ 76 | frameType loc; /* Frame location */ 77 | boolT hasMacro;/* Identifier requires a macro */ 78 | char macro[10];/* Macro for this identifier */ 79 | char name[20];/* Identifier's name */ 80 | union { /* Different types of identifiers */ 81 | byte regi; /* For TYPE_BYTE(WORD)_(UN)SIGN registers */ 82 | struct { /* For TYPE_BYTE(WORD)_(UN)SIGN on the stack */ 83 | byte regOff; /* register offset (if any) */ 84 | Int off; /* offset from BP */ 85 | } bwId; 86 | struct _bwGlb { /* For TYPE_BYTE(WORD)_(UN)SIGN globals */ 87 | int16 seg; /* segment value */ 88 | int16 off; /* offset */ 89 | byte regi; /* optional indexed register */ 90 | } bwGlb; 91 | struct _longId{ /* For TYPE_LONG_(UN)SIGN registers */ 92 | byte h; /* high register */ 93 | byte l; /* low register */ 94 | } longId; 95 | struct _longStkId { /* For TYPE_LONG_(UN)SIGN on the stack */ 96 | Int offH; /* high offset from BP */ 97 | Int offL; /* low offset from BP */ 98 | } longStkId; 99 | struct { /* For TYPE_LONG_(UN)SIGN globals */ 100 | int16 seg; /* segment value */ 101 | int16 offH; /* offset high */ 102 | int16 offL; /* offset low */ 103 | byte regi; /* optional indexed register */ 104 | } longGlb; 105 | struct { /* For TYPE_LONG_(UN)SIGN constants */ 106 | dword h; /* high word */ 107 | dword l; /* low word */ 108 | } longKte; 109 | } id; 110 | } ID; 111 | 112 | typedef struct { 113 | Int csym; /* No. of symbols in the table */ 114 | Int alloc; /* No. of symbols allocated */ 115 | ID *id; /* Identifier */ 116 | } LOCAL_ID; 117 | 118 | 119 | -------------------------------------------------------------------------------- /tools/parsehdr/parsehdr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Enums.h" 3 | /* 4 | *$Log: parsehdr.h,v $ 5 | */ 6 | /* Header file for parsehdr.c */ 7 | 8 | typedef unsigned long dword; /* 32 bits */ 9 | typedef unsigned char byte; /* 8 bits */ 10 | typedef unsigned short word; /* 16 bits */ 11 | typedef unsigned char boolT; /* 8 bits */ 12 | 13 | #define BUFF_SIZE 8192 /* Holds a declaration */ 14 | #define FBUF_SIZE 32700 /* Holds part of a header file */ 15 | 16 | #define NARGS 15 17 | #define NAMES_L 160 18 | #define TYPES_L 160 19 | #define FUNC_L 160 20 | 21 | #define ERRF stdout 22 | 23 | void phError(char *errmsg); 24 | void phWarning(char *errmsg); 25 | 26 | #define ERR(msg) phError(msg) 27 | #ifdef DEBUG 28 | #define DBG(str) printf(str); 29 | #else 30 | #define DBG(str) ; 31 | #endif 32 | #define WARN(msg) phWarning(msg) 33 | #define OUT(str) fprintf(outfile, str) 34 | 35 | #define PH_PARAMS 32 36 | #define PH_NAMESZ 15 37 | 38 | #define SYMLEN 16 /* Including the null */ 39 | #define Int long /* For locident.h */ 40 | //#include "locident.h" /* For the hlType enum */ 41 | //#define bool unsigned char /* For internal use */ 42 | 43 | typedef 44 | struct ph_func_tag 45 | { 46 | char name[SYMLEN]; /* Name of function or arg */ 47 | hlType typ; /* Return type */ 48 | int numArg; /* Number of args */ 49 | int firstArg; /* Index of first arg in chain */ 50 | int next; /* Index of next function in chain */ 51 | bool bVararg; /* True if variable num args */ 52 | } PH_FUNC_STRUCT; 53 | 54 | typedef 55 | struct ph_arg_tag 56 | { 57 | char name[SYMLEN]; /* Name of function or arg */ 58 | hlType typ; /* Parameter type */ 59 | } PH_ARG_STRUCT; 60 | 61 | #define DELTA_FUNC 32 /* Number to alloc at once */ 62 | 63 | 64 | #define PH_JUNK 0 /* LPSTR buffer, nothing happened */ 65 | #define PH_PROTO 1 /* LPPH_FUNC ret val, func name, args */ 66 | #define PH_FUNCTION 2 /* LPPH_FUNC ret val, func name, args */ 67 | #define PH_TYPEDEF 3 /* LPPH_DEF definer and definee */ 68 | #define PH_DEFINE 4 /* LPPH_DEF definer and definee */ 69 | #define PH_ERROR 5 /* LPSTR error string */ 70 | #define PH_WARNING 6 /* LPSTR warning string */ 71 | #define PH_MPROTO 7 /* ????? multi proto???? */ 72 | #define PH_VAR 8 /* ????? var decl */ 73 | 74 | /* PROTOS */ 75 | 76 | boolT phData(char *buff, int ndata); 77 | boolT phPost(void); 78 | boolT phFree(void); 79 | void checkHeap(char *msg); /* For debugging only */ 80 | 81 | void phBuffToFunc(char *buff); 82 | 83 | void phBuffToDef(char *buff); 84 | 85 | 86 | #define TOK_TYPE 256 /* A type name (e.g. "int") */ 87 | #define TOK_NAME 257 /* A function or parameter name */ 88 | #define TOK_DOTS 258 /* "..." */ 89 | #define TOK_EOL 259 /* End of line */ 90 | 91 | typedef enum 92 | { 93 | BT_INT, BT_CHAR, BT_FLOAT, BT_DOUBLE, BT_STRUCT, BT_VOID, BT_UNKWN 94 | } baseType; 95 | -------------------------------------------------------------------------------- /tools/parsehdr/parselib.mak: -------------------------------------------------------------------------------- 1 | CFLAGS = -Zi -c -AS -W3 -D__MSDOS__ 2 | 3 | parselib.exe: parselib.obj 4 | link /CO parselib; 5 | 6 | parselib.obj: parselib.c 7 | cl $(CFLAGS) $*.c 8 | 9 | -------------------------------------------------------------------------------- /tools/parsehdr/tcfiles.lst: -------------------------------------------------------------------------------- 1 | \tc\include\alloc.h 2 | \tc\include\assert.h 3 | \tc\include\bios.h 4 | \tc\include\conio.h 5 | \tc\include\ctype.h 6 | \tc\include\dir.h 7 | \tc\include\dos.h 8 | \tc\include\errno.h 9 | \tc\include\fcntl.h 10 | \tc\include\float.h 11 | \tc\include\io.h 12 | \tc\include\limits.h 13 | \tc\include\math.h 14 | \tc\include\mem.h 15 | \tc\include\process.h 16 | \tc\include\setjmp.h 17 | \tc\include\share.h 18 | \tc\include\signal.h 19 | \tc\include\stdarg.h 20 | \tc\include\stddef.h 21 | \tc\include\stdio.h 22 | \tc\include\stdlib.h 23 | \tc\include\string.h 24 | \tc\include\time.h 25 | -------------------------------------------------------------------------------- /tools/readsig/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(readsig readsig.cpp) 2 | 3 | target_link_libraries(readsig dcc_hash Qt5::Core) 4 | 5 | -------------------------------------------------------------------------------- /tools/readsig/readsig.mak: -------------------------------------------------------------------------------- 1 | CFLAGS = -Zi -c -AL -W3 -D__MSDOS__ 2 | 3 | readsig.exe: readsig.obj perfhlib.obj 4 | link /CO readsig perfhlib; 5 | 6 | readsig.obj: readsig.c dcc.h perfhlib.h 7 | cl $(CFLAGS) $*.c 8 | 9 | perfhlib.obj: perfhlib.c dcc.h perfhlib.h 10 | cl $(CFLAGS) $*.c 11 | 12 | -------------------------------------------------------------------------------- /tools/readsig/readsig.txt: -------------------------------------------------------------------------------- 1 | READSIG 2 | 3 | 1 What is ReadSig? 4 | 5 | 2 How do I use ReadSig? 6 | 7 | 3 What are duplicate signatures? 8 | 9 | 4 How can I make sense of the signatures? 10 | 11 | 12 | 1 What is ReadSig? 13 | ------------------ 14 | 15 | ReadSig is a quick and dirty program to read signatures from a DCC 16 | signature file. It was originally written as an integrity checker for 17 | signature files, but can now be used to see what's in a signature 18 | file, and which functions have duplicate signatures. 19 | 20 | 2 How do I use ReadSig? 21 | ----------------------- 22 | 23 | Just type 24 | readsig 25 | 26 | or 27 | 28 | readsig -a 29 | 30 | 31 | For example: 32 | readsig -a dcct2p.sig 33 | 34 | Either way, you get a list of duplicate signatures, i.e. functions 35 | whose first 23 bytes, after wildcarding and chopping, (see section 3 36 | for details), that have the same signature. 37 | 38 | With the -a switch, you also (before the above) get a list of all 39 | symbolic names in the signature file, and the signatures themselves 40 | in hex. This could be a dozen or more pages for large signature 41 | files. 42 | 43 | Currently, signatures are 23 bytes long, and the symbolic names are 44 | truncated to 15 characters. 45 | 46 | 47 | 3 What are duplicate signatures? 48 | -------------------------------- 49 | 50 | Duplicate signatures arise for 3 reasons. 1: length of the signature. 51 | 2: wildcards. 3: chopping of the signature. 52 | 53 | 1: Because signatures are only 23 bytes long, there is a chance that 54 | two distinct signatures (first part of the binary image of a 55 | function) are identical in the first 23 bytes, but diverge later. 56 | 57 | 2: Because part of the binary image of a function depends on where it 58 | is loaded, parts of the signature are replaced with wildcards. It is 59 | possible that two functions are distinct only in places that are 60 | replaced by the wildcard byte (F4). 61 | 62 | 3: Signatures are "chopped" (cut short, and the remainder filled with 63 | binary zeroes) after an unconditional branch or subroutine return. 64 | This is to cope with functions shorter than the 23 byte size of 65 | signatures, so unrelated functions are not included at the end of a 66 | signature. (This would cause dcc to fail to recognise these short 67 | signatures if some other function happened to be loaded at the end). 68 | 69 | The effect of duplicate signatures is that only one of the functions 70 | that has the same signature will be recognised. For example, suppose 71 | that sin, cos, and tan were just one wildcarded instruction followed 72 | by a jump to the same piece of code. Then all three would have the 73 | same signature, and calls to sin, cos, or tan would all be reported 74 | by dcc as just one of these, e.g. tan. If you suspect that this is 75 | happening, then at least ReadSig can alert you to this problem. 76 | 77 | In general, the number of duplicate signatures that would actually be 78 | used in dcc is small, but it is possible that the above problem will 79 | occur. 80 | 81 | 82 | 83 | 4 How can I make sense of the signatures? 84 | ----------------------------------------- 85 | 86 | If you're one of those unfortunate individuals that can't decode hex 87 | instructions in your head, you can always use DispSig to copy it to a 88 | binary file, since you now know the name of the function. Then you 89 | can use debug or some other debugger to disassemble the binary file. 90 | Generally, most entries in signature files will be executable code, 91 | so it should disassemble readily. 92 | 93 | Be aware that signatures are wildcarded, so don't pay any attention 94 | to the destination of jmp or call instructions (three or 5 byte 95 | jumps, anyway; 2 byte jumps are not wildcarded), and 16 bit immediate 96 | values. The latter will always be F4F4 (two wildcard bytes), 97 | regardless of what they were in the original function. 98 | -------------------------------------------------------------------------------- /tools/regression_tester/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRC 2 | regression_tester.cpp 3 | ) 4 | add_executable(regression_tester ${SRC}) 5 | target_link_libraries(regression_tester Qt5::Core) 6 | -------------------------------------------------------------------------------- /tools/regression_tester/regression_tester.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static void perform_test(QString exepath,QString filepath, QStringList args) { 9 | const QString tgt_path_base("./tests/outputs/"+QFileInfo(filepath).completeBaseName()); 10 | const QString asm_tgt_path_base("./tests/outputs/"+QFileInfo(filepath).fileName()); 11 | 12 | QProcess p; 13 | p.setProgram(exepath); 14 | QStringList assembly1_args = { QString("-a 1"), QString("-o" + asm_tgt_path_base + ".a1"), filepath }; 15 | p.setArguments(assembly1_args); 16 | p.start(); 17 | if(!p.waitForFinished(30000)) { 18 | qCritical() << "Timeout while calling"<stderr >stdout; diff tests/prev/ tests/outputs/ 7 | -------------------------------------------------------------------------------- /valgrind_tester: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | print("Regression tester 0.0.1\n") 4 | def path_local(from) 5 | 6 | return from #from.gsub('/','//') 7 | from.gsub('/','\\\\') 8 | end 9 | TESTS_DIR="./tests" 10 | def perform_test(exepath,filepath,outname,args) 11 | output_path=path_local(TESTS_DIR+"/outputs/"+outname) 12 | error_path=path_local(TESTS_DIR+"/errors/"+outname) 13 | exepath=path_local(exepath) 14 | output_path=path_local(output_path) 15 | filepath=path_local(filepath) 16 | joined_args = args.join(' ') 17 | printf("calling:" + "#{exepath} #{joined_args} -o#{output_path}.a1 #{filepath}\n") 18 | valgrind_mode="valgrind --track-origins=yes " 19 | #valgrind --tool=callgrind --dump-instr=yes --collect-jumps=yes 20 | result = `#{valgrind_mode} #{exepath} #{joined_args} -a1 -o#{output_path}.b #{filepath} 2>#{error_path}.val` 21 | result = `#{valgrind_mode} #{exepath} #{joined_args} -a2 -o#{output_path}.b #{filepath} 2>>#{error_path}.val` 22 | result = `#{valgrind_mode} #{exepath} #{joined_args} -o#{output_path}.b #{filepath} 2>>#{error_path}.val` 23 | puts result 24 | p $? 25 | end 26 | `rm -rf #{TESTS_DIR}/outputs/*.*` 27 | #exit(1) 28 | if(ARGV.size()==0) 29 | puts("valgrind_tester DCC_EXECUTABLE") 30 | exit(0) 31 | end 32 | Dir.open(TESTS_DIR+"/inputs").each() {|f| 33 | next if f=="." or f==".." 34 | perform_test(".//"+ARGV[0],TESTS_DIR+"/inputs/"+f,f,ARGV[1..-1]) 35 | } 36 | Dir.open(TESTS_DIR+"/inputs").each() {|f| 37 | next if f=="." or f==".." 38 | FileUtils.mv(TESTS_DIR+"/inputs/"+f,TESTS_DIR+"/outputs/"+f) if f.end_with?(".b") 39 | } 40 | "diff -rqbwB" --------------------------------------------------------------------------------