Browse Source

Working towards gui integration with exetoc_qt

nemerle 5 years ago
parent
commit
36b063c183

+ 68 - 0
3rd_party/libdisasm/INTEL_BUGS

@@ -0,0 +1,68 @@
+PMOVMSKB
+Gd, Pq1H
+PMOVMSKB
+(66)
+Gd, Vdq1H
+
+should be 
+
+PMOVMSKB
+Gd, Qq1H
+PMOVMSKB
+(66)
+Gd, Wdq1H
+
+The instruction represented by this opcode expression does not support any 
+operand to be a memory location.
+
+MASKMOVQ
+Pq, Pq1H
+MASKMOVDQU
+(66)
+Vdq, Vdq1H
+
+should be
+
+MASKMOVQ
+Pq, Pq1H
+MASKMOVDQU
+(66)
+Vdq, Wdq1H
+
+MOVMSKPS
+Gd, Vps1H
+MOVMSKPD
+(66)
+Gd, Vpd1H
+
+should be
+
+MOVMSKPS
+Gd, Wps1H
+MOVMSKPD
+(66)
+Gd, Wpd1H
+
+The opcode table entries for LFS, LGS, and LSS
+
+L[FGS]S
+Mp
+
+should be
+
+L[FGS]S
+Gv,Mp
+
+MOVHLPS 
+Vps, Vps
+
+MOVLHPS
+Vps, Vps
+
+should be
+
+MOVHLPS 
+Vps, Wps
+
+MOVLHPS
+Vps, Wps

+ 137 - 0
3rd_party/libdisasm/LICENSE

@@ -0,0 +1,137 @@
+
+
+
+
+			 The "Clarified Artistic License"
+
+				Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+	"Package" refers to the collection of files distributed by the
+	Copyright Holder, and derivatives of that collection of files
+	created through textual modification.
+
+	"Standard Version" refers to such a Package if it has not been
+	modified, or has been modified in accordance with the wishes
+	of the Copyright Holder as specified below.
+
+	"Copyright Holder" is whoever is named in the copyright or
+	copyrights for the package.
+
+	"You" is you, if you're thinking about copying or distributing
+	this Package.
+
+	"Distribution fee" is a fee you charge for providing a copy of this
+	Package to another party.
+
+	"Freely Available" means that no fee is charged for the right to use
+	the item, though there may be fees involved in handling the item.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain, or those made Freely Available, or from
+the Copyright Holder.  A Package modified in such a way shall still be
+considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+    a) place your modifications in the Public Domain or otherwise make them
+    Freely Available, such as by posting said modifications to Usenet or
+    an equivalent medium, or placing the modifications on a major archive
+    site allowing unrestricted access to them, or by allowing the Copyright
+    Holder to include your modifications in the Standard Version of the
+    Package.
+
+    b) use the modified Package only within your corporation or organization.
+
+    c) rename any non-standard executables so the names do not conflict
+    with standard executables, which must also be provided, and provide
+    a separate manual page for each non-standard executable that clearly
+    documents how it differs from the Standard Version.
+
+    d) make other distribution arrangements with the Copyright Holder.
+
+    e) permit and encourge anyone who receives a copy of the modified Package
+    permission to make your modifications Freely Available in some specific
+    way.
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+    a) distribute a Standard Version of the executables and library files,
+    together with instructions (in the manual page or equivalent) on where
+    to get the Standard Version.
+
+    b) accompany the distribution with the machine-readable source of
+    the Package with your modifications.
+
+    c) give non-standard executables non-standard names, and clearly
+    document the differences in manual pages (or equivalent), together
+    with instructions on where to get the Standard Version.
+
+    d) make other distribution arrangements with the Copyright Holder.
+
+    e) offer the machine-readable source of the Package, with your
+    modifications, by mail order.
+
+5. You may charge a distribution fee for any distribution of this Package.
+If you offer support for this Package, you may charge any fee you choose
+for that support.  You may not charge a license fee for the right to use
+this Package itself.  You may distribute this Package in aggregate with
+other (possibly commercial and possibly nonfree) programs as part of a
+larger (possibly commercial and possibly nonfree) software distribution,
+and charge license fees for other parts of that software distribution,
+provided that you do not advertise this Package as a product of your own.
+If the Package includes an interpreter, You may embed this Package's
+interpreter within an executable of yours (by linking); this shall be
+construed as a mere form of aggregation, provided that the complete
+Standard Version of the interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whoever generated
+them, and may be sold commercially, and may be aggregated with this
+Package.  If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of the Standard Version of the Package with a commercial
+distribution is always permitted provided that the use of this Package is
+embedded; that is, when no overt attempt is made to make this Package's
+interfaces visible to the end user of the commercial distribution.
+Such use shall not be construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+				The End

+ 12 - 0
3rd_party/libdisasm/NAMESPACE.TXT

@@ -0,0 +1,12 @@
+
+The rewritten libdisasm code uses the following namespaces:
+
+
+	Prefix		Namespace
+----------------------------------------------------
+	x86_		Global 'libdisasm' namespace
+	ia32_		Internal IA32 ISA namespace
+	ia64_		Internal IA64 ISA namespace
+	ix64_		Internal X86-64 ISA namespace
+
+Note that the 64-bit ISAs are not yet supported/written.

+ 2 - 0
3rd_party/libdisasm/README

@@ -0,0 +1,2 @@
+This is a cut-up version of libdisasm originally from the bastard project http://bastard.sourceforge.net/
+

+ 43 - 0
3rd_party/libdisasm/TODO

@@ -0,0 +1,43 @@
+x86_format.c
+------------
+intel: jmpf -> jmp, callf -> call
+att: jmpf -> ljmp, callf -> lcall
+
+opcode table
+------------
+finish typing instructions
+fix flag clear/set/toggle types
+
+ix64 stuff
+----------
+document output file formats in web page
+features doc: register aliases, implicit operands, stack mods,
+ring0 flags, eflags, cpu model/isa
+
+ia32_handle_* implementation
+
+fix operand 0F C2
+CMPPS
+
+* sysenter, sysexit as CALL types -- preceded by MSR writes
+* SYSENTER/SYSEXIT stack : overwrites SS, ESP
+* stos, cmps, scas, movs, ins, outs, lods -> OP_PTR
+* OP_SIZE in implicit operands
+* use OP_SIZE to choose reg sizes!
+
+DONE?? :
+implicit operands: provide action ?
+e.g. add/inc for stach, write, etc 
+replace table numbers in opcodes.dat with
+#defines for table names
+
+replace 0  with INSN_INVALID   [or maybe FF for imnvalid and 00 for Not Applicable */
+no wait that is only for prefix tables -- n/p
+
+if ( prefx) only use if insn != invalid
+
+these should cover all the wacky disasm exceptions 
+
+for the rep one we can chet, match only a 0x90
+
+todo: privilege | ring

+ 36 - 0
3rd_party/libdisasm/ia32_fixup.cpp

@@ -0,0 +1,36 @@
+#include <stdio.h>
+
+static const char * mem_fixup[256] = {
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 00 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 08 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 10 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 18 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 20 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 28 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 30 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 38 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 40 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 48 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 50 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 58 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 60 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 68 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 70 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 78 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 80 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 88 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 90 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 98 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* A0 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* A8 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* B0 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* B8 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* C0 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* C8 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* D0 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* D8 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* E0 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* E8 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* F0 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* F8 */
+};

File diff suppressed because it is too large
+ 3206 - 0
3rd_party/libdisasm/ia32_opcode.dat


+ 49 - 0
3rd_party/libdisasm/libdisasm.def

@@ -0,0 +1,49 @@
+;libdisasm.def : Declares the module parameters
+
+LIBRARY "libdisasm.dll"
+DESCRIPTION "libdisasm exported functions"
+EXPORTS
+	 x86_addr_size  		@1
+	 x86_cleanup		@2
+	 x86_disasm		@3
+	 x86_disasm_forward	@4
+	 x86_disasm_range		@5	
+	 x86_endian		@6
+	 x86_format_header		@7
+	 x86_format_insn		@8
+	 x86_format_mnemonic	@9
+	 x86_format_operand	@10
+	 x86_fp_reg		@11
+	 x86_get_branch_target	@12
+	 x86_get_imm		@13
+	 x86_get_options		@14
+	 x86_get_raw_imm		@15
+	 x86_get_rel_offset		@16
+	 x86_imm_signsized		@17
+	 x86_imm_sized		@18
+	 x86_init			@19
+	 x86_insn_is_tagged		@20
+	 x86_insn_is_valid		@21
+	 x86_invariant_disasm	@22	
+	 x86_ip_reg		@23
+	 x86_max_insn_size		@24
+	 x86_op_size		@25
+	 x86_operand_1st		@26
+	 x86_operand_2nd		@27
+	 x86_operand_3rd		@28
+	 x86_operand_count	@29
+	 x86_operand_foreach	@30
+	 x86_operand_new		@31
+	 x86_operand_size		@32
+	 x86_oplist_free		@33
+	 x86_reg_from_id		@34
+	 x86_report_error		@35
+	 x86_set_insn_addr		@36
+	 x86_set_insn_block	@37
+	 x86_set_insn_function	@38
+	 x86_set_insn_offset	@39
+	 x86_set_options		@40
+	 x86_set_reporter		@41
+	 x86_size_disasm		@42
+	 x86_sp_reg		@43
+	 x86_tag_insn		@44

+ 7 - 2
CMakeLists.txt

@@ -12,7 +12,7 @@ IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
     ADD_DEFINITIONS(/W4)
 ELSE()
 #-D_GLIBCXX_DEBUG
-    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++11")
+    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
     SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} "  ) #--coverage
 ENDIF()
 
@@ -46,9 +46,9 @@ set(dcc_LIB_SOURCES
     src/control.cpp
     src/dataflow.cpp
     src/disassem.cpp
+    src/DccFrontend.cpp
     src/error.cpp
     src/fixwild.cpp
-    src/frontend.cpp
     src/graph.cpp
     src/hlicode.cpp
     src/hltype.cpp
@@ -77,6 +77,7 @@ set(dcc_LIB_SOURCES
     src/symtab.cpp
     src/udm.cpp
     src/BasicBlock.cpp
+    src/dcc_interface.cpp
 )
 set(dcc_SOURCES
     src/dcc.cpp
@@ -85,6 +86,7 @@ set(dcc_HEADERS
     include/ast.h
     include/bundle.h
     include/BinaryImage.h
+    include/DccFrontend.h
     include/dcc.h
     include/disassem.h
     include/dosdcc.h
@@ -113,18 +115,21 @@ set(dcc_HEADERS
     include/Procedure.h
     include/StackFrame.h
     include/BasicBlock.h
+    include/dcc_interface.h
 
 )
 SOURCE_GROUP(Source FILES ${dcc_SOURCES})
 SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
 
 ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS})
+qt5_use_modules(dcc_lib Core)
 #cotire(dcc_lib)
 
 ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
 ADD_DEPENDENCIES(dcc_original dcc_lib)
 TARGET_LINK_LIBRARIES(dcc_original dcc_lib disasm_s ${REQ_LLVM_LIBRARIES} ncurses LLVMSupport)
 qt5_use_modules(dcc_original Core)
+#ADD_SUBDIRECTORY(gui)
 if(dcc_build_tests)
 ADD_SUBDIRECTORY(src)
 endif()

File diff suppressed because it is too large
+ 942 - 312
CMakeScripts/cotire.cmake


+ 5 - 2
include/BinaryImage.h

@@ -1,5 +1,6 @@
 #pragma once
 #include <stdint.h>
+#include <vector>
 struct PROG /* Loaded program image parameters  */
 {
     int16_t     initCS;
@@ -8,15 +9,17 @@ struct PROG /* Loaded program image parameters  */
     uint16_t    initSP;
     bool        fCOM;       /* Flag set if COM program (else EXE)*/
     int         cReloc;     /* No. of relocation table entries  */
-    uint32_t *  relocTable; /* Ptr. to relocation table         */
+    std::vector<uint32_t> relocTable; /* Ptr. to relocation table         */
     uint8_t *   map;        /* Memory bitmap ptr                */
     int         cProcs;     /* Number of procedures so far      */
     int         offMain;    /* The offset  of the main() proc   */
     uint16_t    segMain;    /* The segment of the main() proc   */
     bool        bSigs;		/* True if signatures loaded		*/
     int         cbImage;    /* Length of image in bytes         */
-    const uint8_t *image() const {return Imagez;}
     uint8_t *   Imagez;      /* Allocated by loader to hold entire program image */
     int         addressingMode;
+public:
+    const uint8_t *image() const {return Imagez;}
+    void displayLoadInfo();
 };
 

+ 19 - 0
include/CallGraph.h

@@ -0,0 +1,19 @@
+#pragma once
+#include "Procedure.h"
+/* CALL GRAPH NODE */
+struct CALL_GRAPH
+{
+        ilFunction proc;               /* Pointer to procedure in pProcList	*/
+        std::vector<CALL_GRAPH *> outEdges; /* array of out edges                   */
+public:
+        void write();
+        CALL_GRAPH()
+        {
+        }
+public:
+        void writeNodeCallGraph(int indIdx);
+        bool insertCallGraph(ilFunction caller, ilFunction callee);
+        bool insertCallGraph(Function *caller, ilFunction callee);
+        void insertArc(ilFunction newProc);
+};
+//extern CALL_GRAPH * callGraph;	/* Pointer to the head of the call graph     */

+ 17 - 0
include/DccFrontend.h

@@ -0,0 +1,17 @@
+#pragma once
+#include <QObject>
+class Project;
+class DccFrontend : public QObject
+{
+    Q_OBJECT
+    void    LoadImage();
+    void    parse(Project &proj);
+    std::string m_fname;
+public:
+    explicit DccFrontend(QObject *parent = 0);
+    bool FrontEnd();            /* frontend.c   */
+
+signals:
+
+public slots:
+};

+ 4 - 14
include/dcc.h

@@ -9,6 +9,7 @@
 #include <utility>
 #include <algorithm>
 #include <bitset>
+#include <QtCore/QString>
 
 #include "Enums.h"
 #include "types.h"
@@ -26,7 +27,7 @@ extern bundle cCode;			/* Output C procedure's declaration and code */
 
 /**** Global variables ****/
 
-extern std::string asm1_name, asm2_name; /* Assembler output filenames 		*/
+extern QString asm1_name, asm2_name; /* Assembler output filenames 		*/
 
 typedef struct {            /* Command line option flags */
     unsigned verbose        : 1;
@@ -37,7 +38,7 @@ typedef struct {            /* Command line option flags */
     unsigned Stats          : 1;
     unsigned Interact       : 1;    /* Interactive mode */
     unsigned Calls          : 1;    /* Follow register indirect calls */
-    std::string	filename;			/* The input filename */
+    QString	filename;			/* The input filename */
 } OPTION;
 
 extern OPTION option;       /* Command line options             */
@@ -71,22 +72,11 @@ extern STATS stats; /* Icode statistics */
 
 
 /**** Global function prototypes ****/
-class DccFrontend
-{
-    void    LoadImage(Project &proj);
-    void    parse(Project &proj);
-    std::string m_fname;
-public:
-    DccFrontend(const std::string &fname) : m_fname(fname)
-    {
-    }
-    bool FrontEnd();            /* frontend.c   */
-};
 
 void    udm(void);                                          /* udm.c        */
 void    freeCFG(BB * cfg);                                  /* graph.c      */
 BB *    newBB(BB *, int, int, uint8_t, int, Function *);    /* graph.c      */
-void    BackEnd(const std::string &filename, CALL_GRAPH *);              /* backend.c    */
+void    BackEnd(CALL_GRAPH *);              /* backend.c    */
 extern char   *cChar(uint8_t c);                            /* backend.c    */
 eErrorId scan(uint32_t ip, ICODE &p);                       /* scanner.c    */
 void    parse (CALL_GRAPH * *);                             /* parser.c     */

+ 25 - 0
include/dcc_interface.h

@@ -0,0 +1,25 @@
+#pragma once
+#include "Procedure.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QDir>
+#include <llvm/ADT/ilist.h>
+
+class IXmlTarget;
+
+struct IDcc {
+    static IDcc *get();
+    virtual void BaseInit()=0;
+    virtual void Init(QObject *tgt)=0;
+    virtual lFunction::iterator GetFirstFuncHandle()=0;
+    virtual lFunction::iterator GetCurFuncHandle()=0;
+    virtual void analysis_Once()=0;
+    virtual void load(QString name)=0; // load and preprocess -> find entry point
+    virtual void prtout_asm(IXmlTarget *,int level=0)=0;
+    virtual void prtout_cpp(IXmlTarget *,int level=0)=0;
+    virtual size_t getFuncCount()=0;
+    virtual const lFunction &validFunctions() const =0;
+    virtual void SetCurFunc_by_Name(QString )=0;
+    virtual QDir installDir()=0;
+    virtual QDir dataDir(QString kind)=0;
+};

+ 14 - 7
include/project.h

@@ -8,22 +8,25 @@
 #include <boost/icl/interval_map.hpp>
 #include <boost/icl/split_interval_map.hpp>
 #include <unordered_set>
+#include <QtCore/QString>
 #include "symtab.h"
 #include "BinaryImage.h"
 #include "Procedure.h"
+class QString;
 class SourceMachine;
 struct CALL_GRAPH;
 class IProject
 {
     virtual PROG *binary()=0;
-    virtual const std::string & project_name() const =0;
-    virtual const std::string & binary_path() const =0;
+    virtual const QString & project_name() const =0;
+    virtual const QString & binary_path() const =0;
 };
 class Project : public IProject
 {
     static Project *s_instance;
-    std::string m_fname;
-    std::string m_project_name;
+    QString m_fname;
+    QString m_project_name;
+    QString m_output_path;
 public:
 
 typedef llvm::iplist<Function> FunctionListType;
@@ -41,9 +44,12 @@ typedef FunctionListType lFunction;
     Project(); // default constructor,
 
 public:
-    void create(const std::string & a);
-    const std::string &project_name() const {return m_project_name;}
-    const std::string &binary_path() const {return m_fname;}
+    void create(const QString &a);
+    bool load();
+    const QString &output_path() const {return m_output_path;}
+    const QString &project_name() const {return m_project_name;}
+    const QString &binary_path() const {return m_fname;}
+    QString output_name(const char *ext);
     ilFunction funcIter(Function *to_find);
     ilFunction findByEntry(uint32_t entry);
     ilFunction createFunction(FunctionType *f,const std::string &name);
@@ -60,6 +66,7 @@ public:
     PROG * binary() {return &prog;}
     SourceMachine *machine();
 
+    const FunctionListType &functions() const { return pProcList; }
 protected:
     void initialize();
     void writeGlobSymTable();

BIN
prototypes/dcclibs.dat


BIN
sigs/dccb2s.sig


+ 14 - 14
src/BasicBlock.cpp

@@ -28,11 +28,11 @@ BB *BB::Create(const rCODE &r,eBBKind _nodeType, Function *parent)
     pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
     pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
     pnewBB->instructions = r;
-    int addr = pnewBB->begin()->loc_ip;
     /* Mark the basic block to which the icodes belong to, but only for
      * real code basic blocks (ie. not interval bbs) */
     if(parent)
     {
+        int addr = pnewBB->begin()->loc_ip;
         //setInBB should automatically handle if our range is empty
         parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
 
@@ -40,10 +40,10 @@ BB *BB::Create(const rCODE &r,eBBKind _nodeType, Function *parent)
         parent->m_ip_to_bb[addr] = pnewBB;
         parent->m_actual_cfg.push_back(pnewBB);
         pnewBB->Parent = parent;
-    }
 
     if ( r.begin() != parent->Icode.end() )		/* Only for code BB's */
         stats.numBBbef++;
+    }
     return pnewBB;
 
 }
@@ -90,7 +90,7 @@ void BB::displayDfs()
            dfsFirstNum, dfsLastNum,
            immedDom == MAX ? -1 : immedDom);
     printf("loopType = %s, loopHead = %d, latchNode = %d, follow = %d\n",
-           s_loopType[loopType],
+           s_loopType[(int)loopType],
            loopHead == MAX ? -1 : loopHead,
            latchNode == MAX ? -1 : latchNode,
            loopFollow == MAX ? -1 : loopFollow);
@@ -136,12 +136,14 @@ void BB::displayDfs()
 */
 ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, bool &repCond)
 {
+    if(loopType == eNodeHeaderType::NO_TYPE)
+        return nullptr;
     latch = pProc->m_dfsLast[this->latchNode];
     std::ostringstream ostr;
     ICODE* picode;
     switch (loopType)
     {
-        case WHILE_TYPE:
+    case eNodeHeaderType::WHILE_TYPE:
             picode = &this->back();
 
             /* Check for error in while condition */
@@ -169,15 +171,16 @@ ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&lat
             picode->invalidate();
             break;
 
-        case REPEAT_TYPE:
+    case eNodeHeaderType::REPEAT_TYPE:
             ostr << "\n"<<indentStr(indLevel)<<"do {\n";
             picode = &latch->back();
             picode->invalidate();
             break;
 
-        case ENDLESS_TYPE:
+    case eNodeHeaderType::ENDLESS_TYPE:
             ostr << "\n"<<indentStr(indLevel)<<"for (;;) {\n";
             picode = &latch->back();
+        break;
     }
     cCode.appendCode(ostr.str());
     stats.numHLIcode += 1;
@@ -209,10 +212,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
     /* Check for start of loop */
     repCond = false;
     latch = nullptr;
-    if (loopType)
-    {
        picode=writeLoopHeader(indLevel, pProc, numLoc, latch, repCond);
-    }
 
     /* Write the code for this basic block */
     if (repCond == false)
@@ -227,12 +227,12 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
         return;
 
     /* Check type of loop/node and process code */
-    if ( loopType )	/* there is a loop */
+    if ( loopType!=eNodeHeaderType::NO_TYPE )	/* there is a loop */
     {
         assert(latch);
         if (this != latch)		/* loop is over several bbs */
         {
-            if (loopType == WHILE_TYPE)
+            if (loopType == eNodeHeaderType::WHILE_TYPE)
             {
                 succ = edges[THEN].BBptr;
                 if (succ->dfsLastNum == loopFollow)
@@ -248,7 +248,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
 
         /* Loop epilogue: generate the loop trailer */
         indLevel--;
-        if (loopType == WHILE_TYPE)
+        if (loopType == eNodeHeaderType::WHILE_TYPE)
         {
             std::ostringstream ostr;
             /* Check if there is need to repeat other statements involved
@@ -260,9 +260,9 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
             ostr <<indentStr(indLevel)<< "}	/* end of while */\n";
             cCode.appendCode(ostr.str());
         }
-        else if (loopType == ENDLESS_TYPE)
+        else if (loopType == eNodeHeaderType::ENDLESS_TYPE)
             cCode.appendCode( "%s}	/* end of loop */\n",indentStr(indLevel));
-        else if (loopType == REPEAT_TYPE)
+        else if (loopType == eNodeHeaderType::REPEAT_TYPE)
         {
             string e = "//*failed*//";
             if (picode->hl()->opcode != HLI_JCOND)

+ 410 - 0
src/DccFrontend.cpp

@@ -0,0 +1,410 @@
+#include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
+#include <cstdio>
+#include "dcc.h"
+#include "DccFrontend.h"
+#include "project.h"
+#include "disassem.h"
+#include "CallGraph.h"
+
+
+class Loader
+{
+    bool loadIntoProject(IProject *);
+};
+
+struct PSP {			/*        PSP structure					*/
+    uint16_t int20h;			/* interrupt 20h						*/
+    uint16_t eof;				/* segment, end of allocation block		*/
+    uint8_t res1;				/* reserved                         	*/
+    uint8_t dosDisp[5];		/* far call to DOS function dispatcher	*/
+    uint8_t int22h[4];			/* vector for terminate routine			*/
+    uint8_t int23h[4];			/* vector for ctrl+break routine		*/
+    uint8_t int24h[4];			/* vector for error routine				*/
+    uint8_t res2[22];			/* reserved								*/
+    uint16_t segEnv;			/* segment address of environment block	*/
+    uint8_t res3[34];			/* reserved								*/
+    uint8_t int21h[6];			/* opcode for int21h and far return		*/
+    uint8_t res4[6];			/* reserved								*/
+    uint8_t fcb1[16];			/* default file control block 1			*/
+    uint8_t fcb2[16];      	/* default file control block 2			*/
+    uint8_t res5[4];			/* reserved								*/
+    uint8_t cmdTail[0x80];		/* command tail and disk transfer area	*/
+};
+
+static struct MZHeader {				/*      EXE file header		 	 */
+    uint8_t     sigLo;			/* .EXE signature: 0x4D 0x5A	 */
+    uint8_t     sigHi;
+    uint16_t	lastPageSize;	/* Size of the last page		 */
+    uint16_t	numPages;		/* Number of pages in the file	 */
+    uint16_t	numReloc;		/* Number of relocation items	 */
+    uint16_t	numParaHeader;	/* # of paragraphs in the header */
+    uint16_t	minAlloc;		/* Minimum number of paragraphs	 */
+    uint16_t	maxAlloc;		/* Maximum number of paragraphs	 */
+    uint16_t	initSS;			/* Segment displacement of stack */
+    uint16_t	initSP;			/* Contents of SP at entry       */
+    uint16_t	checkSum;		/* Complemented checksum         */
+    uint16_t	initIP;			/* Contents of IP at entry       */
+    uint16_t	initCS;			/* Segment displacement of code  */
+    uint16_t	relocTabOffset;	/* Relocation table offset       */
+    uint16_t	overlayNum;		/* Overlay number                */
+} header;
+
+#define EXE_RELOCATION  0x10		/* EXE images rellocated to above PSP */
+
+//static void LoadImage(char *filename);
+static void displayMemMap(void);
+/****************************************************************************
+* displayLoadInfo - Displays low level loader type info.
+***************************************************************************/
+void PROG::displayLoadInfo(void)
+{
+    int	i;
+
+    printf("File type is %s\n", (fCOM)?"COM":"EXE");
+    if (! fCOM) {
+        printf("Signature            = %02X%02X\n", header.sigLo, header.sigHi);
+        printf("File size %% 512     = %04X\n", LH(&header.lastPageSize));
+        printf("File size / 512      = %04X pages\n", LH(&header.numPages));
+        printf("# relocation items   = %04X\n", LH(&header.numReloc));
+        printf("Offset to load image = %04X paras\n", LH(&header.numParaHeader));
+        printf("Minimum allocation   = %04X paras\n", LH(&header.minAlloc));
+        printf("Maximum allocation   = %04X paras\n", LH(&header.maxAlloc));
+    }
+    printf("Load image size      = %04" PRIiPTR "\n", cbImage - sizeof(PSP));
+    printf("Initial SS:SP        = %04X:%04X\n", initSS, initSP);
+    printf("Initial CS:IP        = %04X:%04X\n", initCS, initIP);
+
+    if (option.VeryVerbose && cReloc)
+    {
+        printf("\nRelocation Table\n");
+        for (i = 0; i < cReloc; i++)
+        {
+            printf("%06X -> [%04X]\n", relocTable[i],LH(image() + relocTable[i]));
+        }
+    }
+    printf("\n");
+}
+
+/*****************************************************************************
+* fill - Fills line for displayMemMap()
+****************************************************************************/
+static void fill(int ip, char *bf)
+{
+    PROG &prog(Project::get()->prog);
+    static uint8_t type[4] = {'.', 'd', 'c', 'x'};
+    uint8_t	i;
+
+    for (i = 0; i < 16; i++, ip++)
+    {
+        *bf++ = ' ';
+        *bf++ = (ip < prog.cbImage)? type[(prog.map[ip >> 2] >> ((ip & 3) * 2)) & 3]: ' ';
+    }
+    *bf = '\0';
+}
+
+
+/*****************************************************************************
+* displayMemMap - Displays the memory bitmap
+****************************************************************************/
+static void displayMemMap(void)
+{
+    PROG &prog(Project::get()->prog);
+
+    char	c, b1[33], b2[33], b3[33];
+    uint8_t i;
+    int ip = 0;
+
+    printf("\nMemory Map\n");
+    while (ip < prog.cbImage)
+    {
+        fill(ip, b1);
+        printf("%06X %s\n", ip, b1);
+        ip += 16;
+        for (i = 3, c = b1[1]; i < 32 && c == b1[i]; i += 2)
+            ;		/* Check if all same */
+        if (i > 32)
+        {
+            fill(ip, b2);	/* Skip until next two are not same */
+            fill(ip+16, b3);
+            if (! (strcmp(b1, b2) || strcmp(b1, b3)))
+            {
+                printf("                   :\n");
+                do
+                {
+                    ip += 16;
+                    fill(ip+16, b1);
+                } while (! strcmp(b1, b2));
+            }
+        }
+    }
+    printf("\n");
+}
+DccFrontend::DccFrontend(QObject *parent) :
+    QObject(parent)
+{
+}
+
+/*****************************************************************************
+* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
+* rewritter, and displays any useful information.
+****************************************************************************/
+bool DccFrontend::FrontEnd ()
+{
+
+    /* Do depth first flow analysis building call graph and procedure list,
+     * and attaching the I-code to each procedure          */
+    parse (*Project::get());
+
+    if (option.asm1)
+    {
+        std::cout << "dcc: writing assembler file "<<asm1_name.toStdString()<<'\n';
+    }
+
+    /* Search through code looking for impure references and flag them */
+    Disassembler ds(1);
+    for(Function &f : Project::get()->pProcList)
+    {
+        f.markImpure();
+        if (option.asm1)
+        {
+            ds.disassem(&f);
+        }
+    }
+    if (option.Interact)
+    {
+        interactDis(&Project::get()->pProcList.front(), 0);     /* Interactive disassembler */
+    }
+
+    /* Converts jump target addresses to icode offsets */
+    for(Function &f : Project::get()->pProcList)
+    {
+        f.bindIcodeOff();
+    }
+    /* Print memory bitmap */
+    if (option.Map)
+        displayMemMap();
+    return(true); // we no longer own proj !
+}
+struct DosLoader {
+protected:
+    void prepareImage(PROG &prog,size_t sz,QFile &fp) {
+        /* Allocate a block of memory for the program. */
+        prog.cbImage  = sz + sizeof(PSP);
+        prog.Imagez    = new uint8_t [prog.cbImage];
+        prog.Imagez[0] = 0xCD;		/* Fill in PSP int 20h location */
+        prog.Imagez[1] = 0x20;		/* for termination checking     */
+        /* Read in the image past where a PSP would go */
+        if (sz != fp.read((char *)prog.Imagez + sizeof(PSP),sz))
+            fatalError(CANNOT_READ, fp.fileName().toLocal8Bit().data());
+    }
+};
+struct ComLoader : public DosLoader {
+    bool canLoad(QFile &fp) {
+        fp.seek(0);
+        char sig[2];
+        if(2==fp.read(sig,2)) {
+            return not (sig[0] == 0x4D && sig[1] == 0x5A);
+        }
+        return false;
+    }
+    bool load(PROG &prog,QFile &fp) {
+        /* COM file
+         * In this case the load module size is just the file length
+         */
+        auto cb = fp.size();
+
+        /* COM programs start off with an ORG 100H (to leave room for a PSP)
+         * This is also the implied start address so if we load the image
+         * at offset 100H addresses should all line up properly again.
+         */
+        prog.initCS = 0;
+        prog.initIP = 0x100;
+        prog.initSS = 0;
+        prog.initSP = 0xFFFE;
+        prog.cReloc = 0;
+
+        prepareImage(prog,cb,fp);
+
+
+        /* Set up memory map */
+        cb = (prog.cbImage + 3) / 4;
+        prog.map = (uint8_t *)malloc(cb);
+        memset(prog.map, BM_UNKNOWN, (size_t)cb);
+        return true;
+    }
+};
+struct ExeLoader : public DosLoader {
+    bool canLoad(QFile &fp) {
+        if(fp.size()<sizeof(header))
+            return false;
+        MZHeader tmp_header;
+        fp.seek(0);
+        fp.read((char *)&tmp_header, sizeof(header));
+        if(not (tmp_header.sigLo == 0x4D && tmp_header.sigHi == 0x5A))
+            return false;
+
+        /* This is a typical DOS kludge! */
+        if (LH(&header.relocTabOffset) == 0x40)
+        {
+            qDebug() << "Don't understand new EXE format";
+            return false;
+        }
+        return true;
+    }
+    bool load(PROG &prog,QFile &fp) {
+        /* Read rest of header */
+        fp.seek(0);
+        if (fp.read((char *)&header, sizeof(header)) != sizeof(header))
+            return false;
+
+        /* Calculate the load module size.
+        * This is the number of pages in the file
+        * less the length of the header and reloc table
+        * less the number of bytes unused on last page
+        */
+        uint32_t cb = (uint32_t)LH(&header.numPages) * 512 - (uint32_t)LH(&header.numParaHeader) * 16;
+        if (header.lastPageSize)
+        {
+            cb -= 512 - LH(&header.lastPageSize);
+        }
+
+        /* We quietly ignore minAlloc and maxAlloc since for our
+        * purposes it doesn't really matter where in real memory
+        * the program would end up.  EXE programs can't really rely on
+        * their load location so setting the PSP segment to 0 is fine.
+        * Certainly programs that prod around in DOS or BIOS are going
+        * to have to load DS from a constant so it'll be pretty
+        * obvious.
+        */
+        prog.initCS = (int16_t)LH(&header.initCS) + EXE_RELOCATION;
+        prog.initIP = (int16_t)LH(&header.initIP);
+        prog.initSS = (int16_t)LH(&header.initSS) + EXE_RELOCATION;
+        prog.initSP = (int16_t)LH(&header.initSP);
+        prog.cReloc = (int16_t)LH(&header.numReloc);
+
+        /* Allocate the relocation table */
+        if (prog.cReloc)
+        {
+            prog.relocTable.resize(prog.cReloc);
+            fp.seek(LH(&header.relocTabOffset));
+
+            /* Read in seg:offset pairs and convert to Image ptrs */
+            uint8_t	buf[4];
+            for (int i = 0; i < prog.cReloc; i++)
+            {
+                fp.read((char *)buf,4);
+                prog.relocTable[i] = LH(buf) + (((int)LH(buf+2) + EXE_RELOCATION)<<4);
+            }
+        }
+        /* Seek to start of image */
+        uint32_t start_of_image= LH(&header.numParaHeader) * 16;
+        fp.seek(start_of_image);
+        /* Allocate a block of memory for the program. */
+        prepareImage(prog,cb,fp);
+
+        /* Set up memory map */
+        cb = (prog.cbImage + 3) / 4;
+        prog.map = (uint8_t *)malloc(cb);
+        memset(prog.map, BM_UNKNOWN, (size_t)cb);
+
+        /* Relocate segment constants */
+        for(uint32_t v : prog.relocTable) {
+            uint8_t *p = &prog.Imagez[v];
+            uint16_t  w = (uint16_t)LH(p) + EXE_RELOCATION;
+            *p++    = (uint8_t)(w & 0x00FF);
+            *p      = (uint8_t)((w & 0xFF00) >> 8);
+        }
+        return true;
+    }
+};
+/*****************************************************************************
+* LoadImage
+****************************************************************************/
+bool Project::load()
+{
+    // addTask(loaderSelection,PreCond(BinaryImage))
+    // addTask(applyLoader,PreCond(Loader))
+    const char *fname = binary_path().toLocal8Bit().data();
+    QFile finfo(binary_path());
+    /* Open the input file */
+    if(!finfo.open(QFile::ReadOnly)) {
+        fatalError(CANNOT_OPEN, fname);
+    }
+    /* Read in first 2 bytes to check EXE signature */
+    if (finfo.size()<=2)
+    {
+        fatalError(CANNOT_READ, fname);
+    }
+    ComLoader com_loader;
+    ExeLoader exe_loader;
+    if(exe_loader.canLoad(finfo)) {
+        prog.fCOM = false;
+        return exe_loader.load(prog,finfo);
+    }
+    if(com_loader.canLoad(finfo)) {
+        prog.fCOM = true;
+        return com_loader.load(prog,finfo);
+    }
+    return false;
+}
+uint32_t SynthLab;
+/* Parses the program, builds the call graph, and returns the list of
+ * procedures found     */
+void DccFrontend::parse(Project &proj)
+{
+    PROG &prog(proj.prog);
+    STATE state;
+
+    /* Set initial state */
+    state.setState(rES, 0);   /* PSP segment */
+    state.setState(rDS, 0);
+    state.setState(rCS, prog.initCS);
+    state.setState(rSS, prog.initSS);
+    state.setState(rSP, prog.initSP);
+    state.IP = ((uint32_t)prog.initCS << 4) + prog.initIP;
+    SynthLab = SYNTHESIZED_MIN;
+
+    /* Check for special settings of initial state, based on idioms of the
+          startup code */
+    state.checkStartup();
+    Function *start_proc;
+    /* Make a struct for the initial procedure */
+    if (prog.offMain != -1)
+    {
+        start_proc = proj.createFunction(0,"main");
+        start_proc->retVal.loc = REG_FRAME;
+        start_proc->retVal.type = TYPE_WORD_SIGN;
+        start_proc->retVal.id.regi = rAX;
+        /* We know where main() is. Start the flow of control from there */
+        start_proc->procEntry = prog.offMain;
+        /* In medium and large models, the segment of main may (will?) not be
+            the same as the initial CS segment (of the startup code) */
+        state.setState(rCS, prog.segMain);
+        state.IP = prog.offMain;
+    }
+    else
+    {
+        start_proc = proj.createFunction(0,"start");
+        /* Create initial procedure at program start address */
+        start_proc->procEntry = (uint32_t)state.IP;
+    }
+
+    /* The state info is for the first procedure */
+    start_proc->state = state;
+
+    /* Set up call graph initial node */
+    proj.callGraph = new CALL_GRAPH;
+    proj.callGraph->proc = start_proc;
+
+    /* This proc needs to be called to set things up for LibCheck(), which
+       checks a proc to see if it is a know C (etc) library */
+    SetupLibCheck();
+    //BUG:  proj and g_proj are 'live' at this point !
+
+    /* Recursively build entire procedure list */
+    start_proc->FollowCtrl(proj.callGraph, &state);
+
+    /* This proc needs to be called to clean things up from SetupLibCheck() */
+    CleanupLibCheck();
+}

+ 11 - 10
src/backend.cpp

@@ -4,6 +4,8 @@
  * Purpose:	Back-end module.  Generates C code for each procedure.
  * (C) Cristina Cifuentes
  ****************************************************************************/
+#include <QDir>
+#include <QFile>
 #include <cassert>
 #include <string>
 #include <boost/range.hpp>
@@ -167,13 +169,13 @@ void Project::writeGlobSymTable()
 
 /* Writes the header information and global variables to the output C file
  * fp. */
-static void writeHeader (std::ostream &_ios, const char *fileName)
+static void writeHeader (std::ostream &_ios, const std::string &fileName)
 {
     PROG &prog(Project::get()->prog);
     /* Write header information */
     cCode.init();
     cCode.appendDecl( "/*\n");
-    cCode.appendDecl( " * Input file\t: %s\n", fileName);
+    cCode.appendDecl( " * Input file\t: %s\n", fileName.c_str());
     cCode.appendDecl( " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
     cCode.appendDecl( " */\n\n#include \"dcc.h\"\n\n");
 
@@ -341,22 +343,21 @@ static void backBackEnd (CALL_GRAPH * pcallGraph, std::ostream &_ios)
 
 
 /* Invokes the necessary routines to produce code one procedure at a time. */
-void BackEnd (const std::string &fileName, CALL_GRAPH * pcallGraph)
+void BackEnd(CALL_GRAPH * pcallGraph)
 {
     std::ofstream fs; /* Output C file 	*/
 
     /* Get output file name */
-    std::string outNam(fileName);
-    outNam = outNam.substr(0,outNam.rfind("."))+".b"; /* b for beta */
+    QString outNam(Project::get()->output_name("b")); /* b for beta */
 
     /* Open output file */
-    fs.open(outNam);
+    fs.open(outNam.toStdString());
     if(!fs.is_open())
-        fatalError (CANNOT_OPEN, outNam.c_str());
-    printf ("dcc: Writing C beta file %s\n", outNam.c_str());
+        fatalError (CANNOT_OPEN, outNam.toStdString().c_str());
+    std::cout<<"dcc: Writing C beta file "<<outNam.toStdString()<<"\n";
 
     /* Header information */
-    writeHeader (fs, option.filename.c_str());
+    writeHeader (fs, option.filename.toStdString());
 
     /* Initialize total Icode instructions statistics */
     stats.totalLL = 0;
@@ -367,7 +368,7 @@ void BackEnd (const std::string &fileName, CALL_GRAPH * pcallGraph)
 
     /* Close output file */
     fs.close();
-    printf ("dcc: Finished writing C beta file\n");
+    std::cout << "dcc: Finished writing C beta file\n";
 }
 
 

+ 18 - 49
src/chklib.cpp

@@ -5,17 +5,16 @@
  * (C) Mike van Emmerik
 */
 
+#include "dcc.h"
+#include "project.h"
+#include "perfhlib.h"
+#include "dcc_interface.h"
+
+#include <QDir>
 #include <stdio.h>
 #include <stdlib.h>
-#ifdef __BORLAND__
-#include <mem.h>
-#else
 #include <memory.h>
-#endif
 #include <string.h>
-#include "dcc.h"
-#include "project.h"
-#include "perfhlib.h"
 
 #define  NIL   -1                   /* Used like NULL, but 0 is valid */
 
@@ -300,10 +299,11 @@ void SetupLibCheck(void)
     PROG &prog(Project::get()->prog);
     uint16_t w, len;
     int i;
-
-    if ((g_file = fopen(sSigName, "rb")) == nullptr)
+    IDcc *dcc = IDcc::get();
+    QString fpath = dcc->dataDir("sigs").absoluteFilePath(sSigName);
+    if ((g_file = fopen(qPrintable(fpath), "rb")) == nullptr)
     {
-        printf("Warning: cannot open signature file %s\n", sSigName);
+        printf("Warning: cannot open signature file %s\n", qPrintable(fpath));
         return;
     }
 
@@ -638,7 +638,6 @@ void STATE::checkStartup()
     char chModel = 'x';
     char chVendor = 'x';
     char chVersion = 'x';
-    char *pPath;
     char temp[4];
 
     startOff = ((uint32_t)prog.initCS << 4) + prog.initIP;
@@ -829,21 +828,6 @@ void STATE::checkStartup()
 
 gotVendor:
 
-    /* Use the DCC environment variable to set where the .sig files will
-        be found. Otherwise, assume current directory */
-    pPath = getenv("DCC");
-    if (pPath)
-    {
-        strcpy(sSigName, pPath);            /* Use path given */
-        if (sSigName[strlen(sSigName)-1] != '/')
-        {
-            strcat(sSigName, "/");          /* Append a slash if necessary */
-        }
-    }
-    else
-    {
-        strcpy(sSigName, "./");             /* Current directory */
-    }
     strcat(sSigName, "dcc");
     temp[1] = '\0';
     temp[0] = chVendor;
@@ -866,45 +850,30 @@ gotVendor:
 */
 void readProtoFile(void)
 {
+    IDcc *dcc = IDcc::get();
+    QString szProFName = dcc->dataDir("prototypes").absoluteFilePath(DCCLIBS); /* Full name of dclibs.lst */
+
     FILE *fProto;
     char *pPath;                /* Point to the environment string */
-    char szProFName[81];        /* Full name of dclibs.lst */
     int  i;
 
-    /* Use the DCC environment variable to set where the dcclibs.lst file will
-        be found. Otherwise, assume current directory */
-    pPath = getenv("DCC");
-    if (pPath)
-    {
-        strcpy(szProFName, pPath);           /* Use path given */
-        if (szProFName[strlen(szProFName)-1] != '/')
-        {
-            strcat(szProFName, "/");         /* Append a slash if necessary */
-        }
-    }
-    else
-    {
-        strcpy(szProFName, "./");            /* Current directory */
-    }
-    strcat(szProFName, DCCLIBS);
-
-    if ((fProto = fopen(szProFName, "rb")) == nullptr)
+    if ((fProto = fopen(qPrintable(szProFName), "rb")) == nullptr)
     {
-        printf("Warning: cannot open library prototype data file %s\n", szProFName);
+        printf("Warning: cannot open library prototype data file %s\n", qPrintable(szProFName));
         return;
     }
 
     grab(4, fProto);
     if (strncmp(buf, "dccp", 4) != 0)
     {
-        printf("%s is not a dcc prototype file\n", szProFName);
+        printf("%s is not a dcc prototype file\n", qPrintable(szProFName));
         exit(1);
     }
 
     grab(2, fProto);
     if (strncmp(buf, "FN", 2) != 0)
     {
-        printf("FN (Function Name) subsection expected in %s\n", szProFName);
+        printf("FN (Function Name) subsection expected in %s\n", qPrintable(szProFName));
         exit(2);
     }
 
@@ -931,7 +900,7 @@ void readProtoFile(void)
     grab(2, fProto);
     if (strncmp(buf, "PM", 2) != 0)
     {
-        printf("PM (Parameter) subsection expected in %s\n", szProFName);
+        printf("PM (Parameter) subsection expected in %s\n", qPrintable(szProFName));
         exit(2);
     }
 

+ 7 - 7
src/control.cpp

@@ -168,7 +168,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
                 (inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum) &&
                  inList (loopNodes, head->edges[ELSE].BBptr->dfsLastNum)))
             {
-                head->loopType = REPEAT_TYPE;
+                head->loopType = eNodeHeaderType::REPEAT_TYPE;
                 if (latchNode->edges[0].BBptr == head)
                     head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
                 else
@@ -177,7 +177,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
             }
             else
             {
-                head->loopType = WHILE_TYPE;
+                head->loopType = eNodeHeaderType::WHILE_TYPE;
                 if (inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum))
                     head->loopFollow = head->edges[ELSE].BBptr->dfsLastNum;
                 else
@@ -186,7 +186,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
             }
         else /* head = anything besides 2-way, latch = 2-way */
         {
-            head->loopType = REPEAT_TYPE;
+            head->loopType = eNodeHeaderType::REPEAT_TYPE;
             if (latchNode->edges[THEN].BBptr == head)
                 head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
             else
@@ -196,12 +196,12 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
     else	/* latch = 1-way */
         if (latchNode->nodeType == LOOP_NODE)
         {
-            head->loopType = REPEAT_TYPE;
+            head->loopType = eNodeHeaderType::REPEAT_TYPE;
             head->loopFollow = latchNode->edges[0].BBptr->dfsLastNum;
         }
         else if (intNodeType == TWO_BRANCH)
         {
-            head->loopType = WHILE_TYPE;
+            head->loopType = eNodeHeaderType::WHILE_TYPE;
             pbb = latchNode;
             thenDfs = head->edges[THEN].BBptr->dfsLastNum;
             elseDfs = head->edges[ELSE].BBptr->dfsLastNum;
@@ -222,7 +222,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
                                  * loop, so it is safer to consider it an endless loop */
                 if (pbb->dfsLastNum <= head->dfsLastNum)
                 {
-                    head->loopType = ENDLESS_TYPE;
+                    head->loopType = eNodeHeaderType::ENDLESS_TYPE;
                     findEndlessFollow (pProc, loopNodes, head);
                     break;
                 }
@@ -234,7 +234,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
         }
         else
         {
-            head->loopType = ENDLESS_TYPE;
+            head->loopType = eNodeHeaderType::ENDLESS_TYPE;
             findEndlessFollow (pProc, loopNodes, head);
         }
 

+ 0 - 2
src/dataflow.cpp

@@ -143,7 +143,6 @@ void Function::elimCondCodes ()
         //auto reversed_instructions = pBB->range() | reversed;
         for (useAt = pBB->rbegin(); useAt != pBB->rend(); useAt++)
         {
-            ICODE &useIcode(*useAt);
             llIcode useAtOp = llIcode(useAt->ll()->getOpcode());
             use = useAt->ll()->flagDU.u;
             if ((useAt->type != LOW_LEVEL) || ( ! useAt->valid() ) || ( 0 == use ))
@@ -159,7 +158,6 @@ void Function::elimCondCodes ()
                     continue;
                 notSup = false;
                 LLOperand *dest_ll = defIcode.ll()->get(DST);
-                LLOperand *src_ll = defIcode.ll()->get(SRC);
                 if ((useAtOp >= iJB) && (useAtOp <= iJNS))
                 {
                     iICODE befDefAt = (++riICODE(defAt)).base();

+ 28 - 24
src/dcc.cpp

@@ -4,26 +4,10 @@
  * (C) Cristina Cifuentes
  ****************************************************************************/
 
+#include <cstring>
+#include <iostream>
 #include <QtCore/QCoreApplication>
 #include <QCommandLineParser>
-#include <cstring>
-#include "dcc.h"
-#include "project.h"
-
-#include "CallGraph.h"
-/* Global variables - extern to other modules */
-extern std::string asm1_name, asm2_name;     /* Assembler output filenames     */
-extern SYMTAB  symtab;             /* Global symbol table      			  */
-extern STATS   stats;              /* cfg statistics       				  */
-//PROG    prog;               /* programs fields      				  */
-extern OPTION  option;             /* Command line options     			  */
-//Function *   pProcList;			/* List of procedures, topologically sort */
-//Function *	pLastProc;			/* Pointer to last node in procedure list */
-//FunctionListType pProcList;
-//CALL_GRAPH	*callGraph;		/* Call graph of the program			  */
-
-static char *initargs(int argc, char *argv[]);
-static void displayTotalStats(void);
 #include <llvm/Support/raw_os_ostream.h>
 #include <llvm/Support/CommandLine.h>
 #include <llvm/Support/TargetSelect.h>
@@ -39,11 +23,24 @@ static void displayTotalStats(void);
 #include <llvm/TableGen/Main.h>
 #include <llvm/TableGen/TableGenBackend.h>
 #include <llvm/TableGen/Record.h>
+#include <QtCore/QFile>
+
+#include "dcc.h"
+#include "project.h"
+#include "CallGraph.h"
+#include "DccFrontend.h"
+
+/* Global variables - extern to other modules */
+extern QString asm1_name, asm2_name;     /* Assembler output filenames     */
+extern SYMTAB  symtab;             /* Global symbol table      			  */
+extern STATS   stats;              /* cfg statistics       				  */
+extern OPTION  option;             /* Command line options     			  */
+
+static char *initargs(int argc, char *argv[]);
+static void displayTotalStats(void);
 /****************************************************************************
  * main
  ***************************************************************************/
-#include <QtCore/QFile>
-#include <iostream>
 using namespace llvm;
 bool TVisitor(raw_ostream &OS, RecordKeeper &Records)
 {
@@ -161,9 +158,9 @@ void setupOptions(QCoreApplication &app) {
     option.Stats = parser.isSet(boolOpts[4]);
     option.Interact = false;
     option.Calls = parser.isSet(boolOpts[2]);
-    option.filename = args.first().toStdString();
+    option.filename = args.first();
     if(parser.isSet(targetFileOption))
-        asm1_name = asm2_name = parser.value(targetFileOption).toStdString();
+        asm1_name = asm2_name = parser.value(targetFileOption);
     else if(option.asm1 || option.asm2) {
         asm1_name = option.filename+".a1";
         asm2_name = option.filename+".a2";
@@ -181,7 +178,14 @@ int main(int argc, char **argv)
      * building the call graph and attaching appropriate bits of code for
      * each procedure.
     */
-    DccFrontend fe(option.filename);
+    Project::get()->create(option.filename);
+
+    DccFrontend fe(&app);
+    if(!Project::get()->load()) {
+        return -1;
+    }
+    if (option.verbose)
+        Project::get()->prog.displayLoadInfo();
     if(false==fe.FrontEnd ())
         return -1;
     if(option.asm1)
@@ -198,7 +202,7 @@ int main(int argc, char **argv)
      * analysis, data flow etc. and outputs it to output file ready for
      * re-compilation.
     */
-    BackEnd(!asm1_name.empty() ? asm1_name:option.filename, Project::get()->callGraph);
+    BackEnd(Project::get()->callGraph);
 
     Project::get()->callGraph->write();
 

+ 61 - 0
src/dcc_interface.cpp

@@ -0,0 +1,61 @@
+#include "dcc_interface.h"
+#include "dcc.h"
+#include "project.h"
+struct DccImpl : public IDcc{
+
+
+    // IDcc interface
+public:
+    void BaseInit()
+    {
+    }
+    void Init(QObject *tgt)
+    {
+    }
+    ilFunction GetFirstFuncHandle()
+    {
+    }
+    ilFunction GetCurFuncHandle()
+    {
+    }
+    void analysis_Once()
+    {
+    }
+    void load(QString name)
+    {
+        option.filename = name;
+        Project::get()->create(name);
+    }
+    void prtout_asm(IXmlTarget *, int level)
+    {
+    }
+    void prtout_cpp(IXmlTarget *, int level)
+    {
+    }
+    size_t getFuncCount()
+    {
+    }
+    const lFunction &validFunctions() const
+    {
+        return Project::get()->functions();
+    }
+    void SetCurFunc_by_Name(QString)
+    {
+    }
+    QDir installDir() {
+        return QDir(".");
+    }
+    QDir dataDir(QString kind) { // return directory containing decompilation helper data -> signatures/includes/etc.
+        QDir res(installDir());
+        res.cd(kind);
+        return res;
+    }
+};
+
+IDcc* IDcc::get() {
+    static IDcc *v=0;
+    if(!v)
+        v = new DccImpl;
+
+    return v;
+}

+ 2 - 2
src/disassem.cpp

@@ -150,10 +150,10 @@ void Disassembler::disassem(Function * ppProc)
     if (pass != 3)
     {
         auto p = (pass == 1)? asm1_name: asm2_name;
-        m_fp.open(p,ios_base::app);
+        m_fp.open(p.toStdString(),ios_base::app);
         if (!m_fp.is_open())
         {
-            fatalError(CANNOT_OPEN, p.c_str());
+            fatalError(CANNOT_OPEN, p.toStdString().c_str());
         }
     }
     /* Create temporary code array */

+ 5 - 0
src/idioms.cpp

@@ -3,7 +3,12 @@
  * (C) Cristina Cifuentes
  ****************************************************************************/
 
+#include <llvm/Config/llvm-config.h>
+#if( (LLVM_VERSION_MAJOR==3 ) && (LLVM_VERSION_MINOR>3) )
+#include <llvm/IR/PatternMatch.h>
+#else
 #include <llvm/Support/PatternMatch.h>
+#endif
 #include <boost/iterator/filter_iterator.hpp>
 #include <cstring>
 #include <deque>

+ 9 - 12
src/idioms/mov_idioms.cpp

@@ -27,16 +27,16 @@ bool Idiom14::match(iICODE pIcode)
         return false;
     m_icodes[0]=pIcode++;
     m_icodes[1]=pIcode++;
-    LLInst * matched [] = {m_icodes[0]->ll(),m_icodes[1]->ll()};
+    LLInst * matched [] {m_icodes[0]->ll(),m_icodes[1]->ll()};
     /* Check for regL */
-    m_regL = m_icodes[0]->ll()->m_dst.regi;
-    if (not m_icodes[0]->ll()->testFlags(I) && ((m_regL == rAX) || (m_regL ==rBX)))
+    m_regL = matched[0]->m_dst.regi;
+    if (not matched[0]->testFlags(I) && ((m_regL == rAX) || (m_regL ==rBX)))
     {
         /* Check for XOR regH, regH */
-        if (m_icodes[1]->ll()->match(iXOR) && not m_icodes[1]->ll()->testFlags(I))
+        if (matched[1]->match(iXOR) && not matched[1]->testFlags(I))
         {
-            m_regH = m_icodes[1]->ll()->m_dst.regi;
-            if (m_regH == m_icodes[1]->ll()->src().getReg2())
+            m_regH = matched[1]->m_dst.regi;
+            if (m_regH == matched[1]->src().getReg2())
             {
                 if ((m_regL == rAX) && (m_regH == rDX))
                     return true;
@@ -49,14 +49,11 @@ bool Idiom14::match(iICODE pIcode)
 }
 int Idiom14::action()
 {
-    int idx;
-    AstIdent *lhs;
-    Expr *rhs;
 
-    idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(m_regH,m_regL), m_icodes[0]);
-    lhs = AstIdent::LongIdx (idx);
+    int idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(m_regH,m_regL), m_icodes[0]);
+    AstIdent *lhs = AstIdent::LongIdx (idx);
     m_icodes[0]->setRegDU( m_regH, eDEF);
-    rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
+    Expr *rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
     m_icodes[0]->setAsgn(lhs, rhs);
     m_icodes[1]->invalidate();
     return 2;

+ 1 - 63
src/parser.cpp

@@ -20,70 +20,8 @@ static void     setBits(int16_t type, uint32_t start, uint32_t len);
 static void     process_MOV(LLInst &ll, STATE * pstate);
 static SYM *     lookupAddr (LLOperand *pm, STATE * pstate, int size, uint16_t duFlag);
 void    interactDis(Function * initProc, int ic);
-static uint32_t    SynthLab;
+extern uint32_t    SynthLab;
 
-/* Parses the program, builds the call graph, and returns the list of
- * procedures found     */
-void DccFrontend::parse(Project &proj)
-{
-    PROG &prog(proj.prog);
-    STATE state;
-
-    /* Set initial state */
-    state.setState(rES, 0);   /* PSP segment */
-    state.setState(rDS, 0);
-    state.setState(rCS, prog.initCS);
-    state.setState(rSS, prog.initSS);
-    state.setState(rSP, prog.initSP);
-    state.IP = ((uint32_t)prog.initCS << 4) + prog.initIP;
-    SynthLab = SYNTHESIZED_MIN;
-
-    // default-construct a Function object !
-    /*auto func = */;
-
-    /* Check for special settings of initial state, based on idioms of the
-          startup code */
-    state.checkStartup();
-    Function *start_proc;
-    /* Make a struct for the initial procedure */
-    if (prog.offMain != -1)
-    {
-        start_proc = proj.createFunction(0,"main");
-        start_proc->retVal.loc = REG_FRAME;
-        start_proc->retVal.type = TYPE_WORD_SIGN;
-        start_proc->retVal.id.regi = rAX;
-        /* We know where main() is. Start the flow of control from there */
-        start_proc->procEntry = prog.offMain;
-        /* In medium and large models, the segment of main may (will?) not be
-            the same as the initial CS segment (of the startup code) */
-        state.setState(rCS, prog.segMain);
-        state.IP = prog.offMain;
-    }
-    else
-    {
-        start_proc = proj.createFunction(0,"start");
-        /* Create initial procedure at program start address */
-        start_proc->procEntry = (uint32_t)state.IP;
-    }
-
-    /* The state info is for the first procedure */
-    start_proc->state = state;
-
-    /* Set up call graph initial node */
-    proj.callGraph = new CALL_GRAPH;
-    proj.callGraph->proc = start_proc;
-
-    /* This proc needs to be called to set things up for LibCheck(), which
-       checks a proc to see if it is a know C (etc) library */
-    SetupLibCheck();
-    //BUG:  proj and g_proj are 'live' at this point !
-
-    /* Recursively build entire procedure list */
-    start_proc->FollowCtrl(proj.callGraph, &state);
-
-    /* This proc needs to be called to clean things up from SetupLibCheck() */
-    CleanupLibCheck();
-}
 
 /* Returns the size of the string pointed by sym and delimited by delim.
  * Size includes delimiter.     */

+ 17 - 8
src/project.cpp

@@ -1,3 +1,5 @@
+#include <QtCore/QString>
+#include <QtCore/QDir>
 #include <utility>
 #include "dcc.h"
 #include "CallGraph.h"
@@ -5,7 +7,7 @@
 #include "Procedure.h"
 using namespace std;
 //Project g_proj;
-string asm1_name, asm2_name;     /* Assembler output filenames     */
+QString asm1_name, asm2_name;     /* Assembler output filenames     */
 SYMTAB  symtab;             /* Global symbol table      			  */
 STATS   stats;              /* cfg statistics       				  */
 //PROG    prog;               /* programs fields      				  */
@@ -20,19 +22,26 @@ void Project::initialize()
     delete callGraph;
     callGraph = nullptr;
 }
-void Project::create(const string &a)
+void Project::create(const QString &a)
 {
+    initialize();
     m_fname=a;
-    string::size_type ext_loc=a.find_last_of('.');
-    string::size_type slash_loc=a.find_last_of('/',ext_loc);
-    if(slash_loc==string::npos)
+    auto ext_loc=a.lastIndexOf('.');
+    auto slash_loc=a.lastIndexOf('/',ext_loc);
+    if(slash_loc==-1)
         slash_loc=0;
     else
         slash_loc++;
-    if(ext_loc!=string::npos)
-        m_project_name = a.substr(slash_loc,(ext_loc-slash_loc));
+    if(ext_loc!=-1) {
+        m_project_name = a.mid(slash_loc,ext_loc-slash_loc);
+    }
     else
-        m_project_name = a.substr(slash_loc);
+        m_project_name = a.mid(slash_loc);
+    m_output_path = a.left(slash_loc);
+}
+
+QString Project::output_name(const char *ext) {
+    return m_output_path+QDir::separator()+m_project_name+"."+ext;
 }
 bool Project::valid(ilFunction iter)
 {