From 62d86331131ff78a75d17ea763453d3274565c4b Mon Sep 17 00:00:00 2001 From: nemerle Date: Tue, 26 Apr 2016 16:18:23 +0200 Subject: [PATCH] Implementation --- CMakeLists.txt | 21 +++-- include/DccFrontend.h | 6 +- include/project.h | 79 ++++++++++++------- include/state.h | 17 ++-- include/symtab.h | 3 + src/Command.cpp | 97 +++++++++++++++++++++++ src/Command.h | 81 +++++++++++++++++++ src/DccFrontend.cpp | 86 ++++++++------------ src/Loaders.cpp | 177 ++++++++++++++++++++++++++++++++++++++++++ src/Loaders.h | 31 ++++++++ src/dcc.cpp | 14 ++-- src/parser.cpp | 10 +-- src/project.cpp | 47 ++++++++++- 13 files changed, 555 insertions(+), 114 deletions(-) create mode 100644 src/Command.cpp create mode 100644 src/Command.h create mode 100644 src/Loaders.cpp create mode 100644 src/Loaders.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cc7e54f..d572804 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,6 @@ PROJECT(dcc_original) cmake_minimum_required(VERSION 2.8.9) -set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_AUTOMOC ON) -find_package(Qt5Core) -OPTION(dcc_build_tests "Enable unit tests." OFF) -#SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS) IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)") ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE -DNOMINMAX) @@ -18,6 +13,13 @@ ENDIF() SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH}) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_AUTOMOC ON) +find_package(Qt5Core) +find_package(Qt5Widgets) + +OPTION(dcc_build_tests "Enable unit tests." OFF) include(cotire) FIND_PACKAGE(Boost) IF(dcc_build_tests) @@ -86,6 +88,11 @@ set(dcc_LIB_SOURCES src/udm.cpp src/BasicBlock.cpp src/dcc_interface.cpp + + src/Command.cpp + src/Command.h + src/Loaders.cpp + src/Loaders.h ) set(dcc_SOURCES src/dcc.cpp @@ -133,10 +140,10 @@ 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_EXECUTABLE(dcc_original ${dcc_SOURCES}) ADD_DEPENDENCIES(dcc_original dcc_lib) TARGET_LINK_LIBRARIES(dcc_original dcc_lib dcc_hash disasm_s ${REQ_LLVM_LIBRARIES} LLVMSupport) -qt5_use_modules(dcc_original Core) +qt5_use_modules(dcc_original Core Widgets) #ADD_SUBDIRECTORY(gui) if(dcc_build_tests) ADD_SUBDIRECTORY(src) diff --git a/include/DccFrontend.h b/include/DccFrontend.h index 39d6c84..4b6501c 100644 --- a/include/DccFrontend.h +++ b/include/DccFrontend.h @@ -1,15 +1,17 @@ #pragma once -#include +#include 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 */ + void initializeMachineState(Project & proj); + + void createEntryProc(Project &proj); signals: diff --git a/include/project.h b/include/project.h index b232c23..05e11d2 100644 --- a/include/project.h +++ b/include/project.h @@ -1,51 +1,59 @@ #pragma once -#include -#include -#include -#include + +#include "symtab.h" +#include "BinaryImage.h" +#include "Procedure.h" +#include "state.h" +#include "src/Command.h" + #include #include #include #include -#include #include -#include "symtab.h" -#include "BinaryImage.h" -#include "Procedure.h" +#include +#include +#include +#include +#include + class QString; class SourceMachine; struct CALL_GRAPH; -class IProject -{ - virtual PROG *binary()=0; - virtual const QString & project_name() const =0; - virtual const QString & binary_path() const =0; -}; -class Project : public IProject -{ - static Project *s_instance; - QString m_fname; - QString m_project_name; - QString m_output_path; -public: +struct DosLoader; +class Project : public QObject +{ + Q_OBJECT +public: typedef llvm::iplist FunctionListType; typedef FunctionListType lFunction; typedef FunctionListType::iterator ilFunction; - SYMTAB symtab; /* Global symbol table */ - FunctionListType pProcList; - CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */ - PROG prog; /* Loaded program image parameters */ - // no copies +public: + DosLoader * m_selected_loader; + uint32_t SynthLab; //!< Last snthetic lab idx + SYMTAB symtab; //!< Global symbol table + FunctionListType pProcList; //!< List of located functions + CALL_GRAPH * callGraph; //!< Pointer to the head of the call graph + STATE m_entry_state; //!< Machine state at program load + + PROG prog; /* Loaded program image parameters */ + CommandStream m_project_command_stream; + bool m_error_state; +public: + // prevent Project instance copying Project(const Project&) = delete; const Project & operator=(const Project & l) =delete; // only moves Project(); // default constructor, -public: void create(const QString &a); - bool load(); + + bool addLoadCommands(); + void processAllCommands(); + void resetCommandsAndErrorState(); + 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;} @@ -68,8 +76,23 @@ public: const FunctionListType &functions() const { return pProcList; } FunctionListType &functions() { return pProcList; } + template + bool addCommand() { + return m_project_command_stream.add(new COMMANDCLASS); + } + void dumpAllErrors(); +public slots: + void onCommandStreamFinished(bool state); protected: void initialize(); void writeGlobSymTable(); + +protected: + static Project * s_instance; + QString m_fname; + QString m_project_name; + QString m_output_path; + CommandContext m_command_ctx; + }; //extern Project g_proj; diff --git a/include/state.h b/include/state.h index 254f267..e229a30 100644 --- a/include/state.h +++ b/include/state.h @@ -3,21 +3,22 @@ * (C) Cristina Cifuentes, Mike van Emmerik ****************************************************************************/ #pragma once -#include -#include #include "machine_x86.h" +#include +#include + /* STATE TABLE */ struct STATE { - uint32_t IP; /* Offset into Image */ - int16_t r[INDEX_BX_SI]; /* Value of segs and AX */ + uint32_t IP; /* Offset into Image */ + int16_t r[INDEX_BX_SI]; /* Register values */ bool f[INDEX_BX_SI]; /* True if r[.] has a value */ struct - { /* For case stmt indexed reg */ - uint8_t regi; /* Last conditional jump */ - int16_t immed; /* Contents of the previous register */ - } JCond; + { /* For case stmt indexed reg */ + uint8_t regi; /* Last conditional jump */ + int16_t immed; /* Contents of the previous register */ + } JCond; void setState(uint16_t reg, int16_t value); void checkStartup(); bool isKnown(eReg v) {return f[v];} diff --git a/include/symtab.h b/include/symtab.h index fad1e8a..2f9f8a4 100644 --- a/include/symtab.h +++ b/include/symtab.h @@ -10,6 +10,9 @@ #include #include #include + +class QTextStream; + struct Expr; struct AstIdent; struct TypeContainer; diff --git a/src/Command.cpp b/src/Command.cpp new file mode 100644 index 0000000..ba7d9c0 --- /dev/null +++ b/src/Command.cpp @@ -0,0 +1,97 @@ +#include "Command.h" + +#include "project.h" +#include "Loaders.h" + +#include + +bool LoaderSelection::execute(CommandContext * ctx, Project *p) +{ + if(p->binary_path().isEmpty()) { + ctx->recordFailure(this,QString("No executable path set in project %1").arg(p->project_name())); + return false; + } + + QFile finfo(p->binary_path()); + /* Open the input file */ + if(not finfo.open(QFile::ReadOnly)) { + ctx->recordFailure(this,QString("Cannot open file %1").arg(p->binary_path())); + return false; + } + /* Read in first 2 bytes to check EXE signature */ + if (finfo.size()<=2) + { + ctx->recordFailure(this,QString("File %1 is too small").arg(p->binary_path())); + } + ComLoader com_loader; + ExeLoader exe_loader; + + if(exe_loader.canLoad(finfo)) { + p->m_selected_loader = new ExeLoader; + return true; + } + if(com_loader.canLoad(finfo)) { + p->m_selected_loader = new ComLoader; + return true; + } + ctx->recordFailure(this,QString("None of the available loaders can load file %1").arg(p->binary_path())); + + return true; +} + +bool LoaderApplication::execute(CommandContext * ctx, Project *p) +{ + if(!p) + return false; + if(!p->m_selected_loader) { + ctx->recordFailure(this,QString("No loader selected for project %1").arg(p->project_name())); + return false; + } + QFile finfo(p->binary_path()); + if(not finfo.open(QFile::ReadOnly)) { + ctx->recordFailure(this,QString("Cannot open file %1").arg(p->binary_path())); + return false; + } + return p->m_selected_loader->load(p->prog,finfo); +} + +bool CommandStream::add(Command * c) { + if(m_commands.size()>=m_maximum_command_count) + return false; + m_commands.push_back(c); + return true; +} + +void CommandStream::setMaximumCommandCount(int maximum_command_count) { + m_maximum_command_count = maximum_command_count; +} + +void CommandStream::processAll(CommandContext *ctx) +{ + while(not m_commands.isEmpty()) { + Command *cmd = m_commands.takeFirst(); + if(false==cmd->execute(ctx,ctx->proj)) { + emit streamCompleted(false); + break; + } + m_recently_executed.push_back(cmd); + } + emit streamCompleted(true); +} + +void CommandStream::clear() +{ + qDeleteAll(m_commands); + qDeleteAll(m_recently_executed); + m_commands.clear(); + m_recently_executed.clear(); +} + + +void CommandContext::reset() +{ + for(int i=0; i +#include +#include + +class Project; +enum CommandLevel { + eProject, + eBinary, + eFunction, + eBasicBlock, + eInstruction +}; +class Command; + +class CommandContext { +public: + void recordFailure(Command *cmd,QString error_message) { + m_failures.push_back({cmd,error_message}); + } + + Project *proj; + QVector> m_failures; + void reset(); +}; + +class Command +{ + QString m_command_name; + CommandLevel m_level; +public: + Command(QString n,CommandLevel level) : m_command_name(n),m_level(level) {} + QString name() const { return m_command_name;} + virtual bool execute(CommandContext *,Project *) { return false; } +}; +class CompoundCommand : public Command { + QVector m_contained; +public: + CompoundCommand(QString n,CommandLevel l) : Command(n,l) { + } + void addCommand(Command *c) { + m_contained.push_back(c); + } + bool execute(CommandContext * ctx,Project *v) { + for(Command * c : m_contained) { + if(!c->execute(ctx,v)) + return false; + } + return true; + } +}; +class CommandStream : public QObject +{ + Q_OBJECT + int m_maximum_command_count; +public: + QVector m_recently_executed; + QVector m_commands; + bool add(Command *c); + void setMaximumCommandCount(int maximum_command_count); + void processAll(CommandContext *ctx); + void clear(); +signals: + void streamCompleted(bool success); +}; + +class LoaderSelection : public Command { +public: + virtual ~LoaderSelection() {} + LoaderSelection() : Command("Select loader",eProject) {} + bool execute(CommandContext * ctx,Project *) override; +}; +class LoaderApplication : public Command { +public: + virtual ~LoaderApplication() {} + LoaderApplication() : Command("Apply loader",eProject) {} + bool execute(CommandContext * ctx,Project *) override; +}; +#endif // COMMAND_H diff --git a/src/DccFrontend.cpp b/src/DccFrontend.cpp index 361e226..d659d78 100644 --- a/src/DccFrontend.cpp +++ b/src/DccFrontend.cpp @@ -11,11 +11,6 @@ #include -class Loader -{ - bool loadIntoProject(IProject *); -}; - struct PSP { /* PSP structure */ uint16_t int20h; /* interrupt 20h */ uint16_t eof; /* segment, end of allocation block */ @@ -325,53 +320,21 @@ struct ExeLoader : public DosLoader { /***************************************************************************** * LoadImage ****************************************************************************/ -bool Project::load() +void DccFrontend::initializeMachineState(Project &proj) { - // addTask(loaderSelection,PreCond(BinaryImage)) - // addTask(applyLoader,PreCond(Loader)) - const char *fname = binary_path().toLocal8Bit().data(); - QFile finfo(binary_path()); - /* Open the input file */ - if(not 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; + const PROG &prog(proj.prog); + proj.m_entry_state.setState(rES, 0); /* PSP segment */ + proj.m_entry_state.setState(rDS, 0); + proj.m_entry_state.setState(rCS, prog.initCS); + proj.m_entry_state.setState(rSS, prog.initSS); + proj.m_entry_state.setState(rSP, prog.initSP); + proj.m_entry_state.IP = ((uint32_t)prog.initCS << 4) + prog.initIP; + proj.SynthLab = SYNTHESIZED_MIN; } -uint32_t SynthLab; -/* Parses the program, builds the call graph, and returns the list of - * procedures found */ -void DccFrontend::parse(Project &proj) + +void DccFrontend::createEntryProc(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(); ilFunction start_proc; /* Make a struct for the initial procedure */ if (prog.offMain != -1) @@ -384,30 +347,43 @@ void DccFrontend::parse(Project &proj) 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; + proj.m_entry_state.setState(rCS, prog.segMain); + proj.m_entry_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; + start_proc->procEntry = (uint32_t)proj.m_entry_state.IP; } - /* The state info is for the first procedure */ - start_proc->state = state; + start_proc->state = proj.m_entry_state; /* Set up call graph initial node */ proj.callGraph = new CALL_GRAPH; proj.callGraph->proc = start_proc; +} + +/* Parses the program, builds the call graph, and returns the list of + * procedures found */ +void DccFrontend::parse(Project &proj) +{ + /* Set initial state */ + initializeMachineState(proj); + + /* Check for special settings of initial state, based on idioms of the + startup code */ + proj.m_entry_state.checkStartup(); + + createEntryProc(proj); /* 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 */ - prog.bSigs = SetupLibCheck(); + proj.prog.bSigs = SetupLibCheck(); //BUG: proj and g_proj are 'live' at this point ! /* Recursively build entire procedure list */ - start_proc->FollowCtrl(proj.callGraph, &state); + proj.callGraph->proc->FollowCtrl(proj.callGraph, &proj.m_entry_state); /* This proc needs to be called to clean things up from SetupLibCheck() */ CleanupLibCheck(); diff --git a/src/Loaders.cpp b/src/Loaders.cpp new file mode 100644 index 0000000..b916550 --- /dev/null +++ b/src/Loaders.cpp @@ -0,0 +1,177 @@ +#include "Loaders.h" + +#include "dcc.h" + +#include + +#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */ + +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; + +void DosLoader::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()); +} + +bool ComLoader::canLoad(QFile & fp) { + fp.seek(0); + char sig[2]; + if(2==fp.read(sig,2)) { + return not (sig[0] == 0x4D and sig[1] == 0x5A); + } + return false; +} + +bool ComLoader::load(PROG & prog, QFile & fp) { + prog.fCOM = true; + fp.seek(0); + /* 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; +} + +bool ExeLoader::canLoad(QFile & fp) { + if(fp.size()> 8); + } + return true; +} diff --git a/src/Loaders.h b/src/Loaders.h new file mode 100644 index 0000000..09e1857 --- /dev/null +++ b/src/Loaders.h @@ -0,0 +1,31 @@ +#ifndef LOADERS_H +#define LOADERS_H + +#include "BinaryImage.h" +#include +#include + +struct DosLoader { +protected: + void prepareImage(PROG &prog,size_t sz,QFile &fp); +public: + virtual bool canLoad(QFile &fp)=0; + virtual QString loaderName() const =0; + virtual bool load(PROG &prog,QFile &fp)=0; +}; +struct ComLoader : public DosLoader { + virtual ~ComLoader() {} + + bool canLoad(QFile &fp) override; + bool load(PROG &prog,QFile &fp) override; + QString loaderName() const override { return "16-bit DOS - COM loader"; } +}; +struct ExeLoader : public DosLoader { + virtual ~ExeLoader() {} + + bool canLoad(QFile &fp) override; + bool load(PROG &prog,QFile &fp) override; + QString loaderName() const override { return "16-bit DOS - EXE loader"; } +}; + +#endif // LOADERS_H diff --git a/src/dcc.cpp b/src/dcc.cpp index 3c2aefb..3554d85 100644 --- a/src/dcc.cpp +++ b/src/dcc.cpp @@ -185,18 +185,22 @@ int main(int argc, char **argv) QCoreApplication::setApplicationVersion("0.1"); setupOptions(app); + Project *proj = Project::get(); /* Front end reads in EXE or COM file, parses it into I-code while * building the call graph and attaching appropriate bits of code for * each procedure. */ - Project::get()->create(option.filename); + proj->create(option.filename); DccFrontend fe(&app); - if(not Project::get()->load()) { + proj->addLoadCommands(); + proj->processAllCommands(); + if(proj->m_error_state) { + proj->dumpAllErrors(); return -1; } if (option.verbose) - Project::get()->prog.displayLoadInfo(); + proj->prog.displayLoadInfo(); if(false==fe.FrontEnd ()) return -1; if(option.asm1) @@ -213,9 +217,9 @@ int main(int argc, char **argv) * analysis, data flow etc. and outputs it to output file ready for * re-compilation. */ - BackEnd(Project::get()->callGraph); + BackEnd(proj->callGraph); - Project::get()->callGraph->write(); + proj->callGraph->write(); if (option.Stats) displayTotalStats(); diff --git a/src/parser.cpp b/src/parser.cpp index d3e40d1..bb5b41c 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -24,8 +24,6 @@ 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); -extern uint32_t SynthLab; - /* Returns the size of the string pointed by sym and delimited by delim. * Size includes delimiter. */ @@ -57,7 +55,7 @@ ICODE * Function::translate_DIV(LLInst *ll, ICODE &_Icode) eIcode.setRegDU( rAX, eUSE); eIcode.setRegDU( rTMP, eDEF); eIcode.ll()->setFlags( SYNTHETIC ); - /* eIcode.ll()->label = SynthLab++; */ + /* eIcode.ll()->label = Project::get()->SynthLab++; */ eIcode.ll()->label = _Icode.ll()->label; Icode.addIcode(&eIcode); @@ -70,7 +68,7 @@ ICODE * Function::translate_DIV(LLInst *ll, ICODE &_Icode) eIcode.ll()->set(iMOD,ll->getFlag() | SYNTHETIC | IM_TMP_DST); eIcode.ll()->replaceSrc(_Icode.ll()->src()); eIcode.du = _Icode.du; - eIcode.ll()->label = SynthLab++; + eIcode.ll()->label = Project::get()->SynthLab++; return Icode.addIcode(&eIcode); } ICODE *Function::translate_XCHG(LLInst *ll,ICODE &_Icode) @@ -108,7 +106,7 @@ ICODE *Function::translate_XCHG(LLInst *ll,ICODE &_Icode) } eIcode.ll()->replaceSrc(rTMP); eIcode.setRegDU( rTMP, eUSE); - eIcode.ll()->label = SynthLab++; + eIcode.ll()->label = Project::get()->SynthLab++; return Icode.addIcode(&eIcode); } @@ -160,7 +158,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate) _Icode.type = LOW_LEVEL; ll->set(iJMP,I | SYNTHETIC | NO_OPS); ll->replaceSrc(LLOperand::CreateImm2(labLoc->ll()->GetLlLabel())); - ll->label = SynthLab++; + ll->label = Project::get()->SynthLab++; } /* Copy Icode to Proc */ diff --git a/src/project.cpp b/src/project.cpp index d60a031..e186569 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1,10 +1,13 @@ -#include -#include -#include #include "dcc.h" #include "CallGraph.h" #include "project.h" #include "Procedure.h" + +#include +#include +#include +#include + using namespace std; //Project g_proj; QString asm1_name, asm2_name; /* Assembler output filenames */ @@ -15,10 +18,13 @@ OPTION option; /* Command line options */ Project *Project::s_instance = nullptr; Project::Project() : callGraph(nullptr) { + m_project_command_stream.setMaximumCommandCount(10); + connect(&m_project_command_stream,SIGNAL(streamCompleted(bool)),SLOT(onCommandStreamFinished(bool))); memset(&prog,0,sizeof(prog)); } void Project::initialize() { + resetCommandsAndErrorState(); delete callGraph; callGraph = nullptr; } @@ -106,3 +112,38 @@ SourceMachine *Project::machine() return nullptr; } +void Project::onCommandStreamFinished(bool state) +{ + if(false==state) { + m_error_state = true; + } +} +void Project::dumpAllErrors() { + for(QPair v : m_command_ctx.m_failures) { + qDebug() << QString("%1 command failed with : %2").arg(v.first->name()).arg(v.second); + } +} +bool Project::addLoadCommands() +{ + if(!addCommand()) + return false; + if(!addCommand()) { + return false; + } + return true; +} + +void Project::processAllCommands() +{ + m_command_ctx.proj = this; + m_project_command_stream.processAll(&m_command_ctx); + +} + +void Project::resetCommandsAndErrorState() +{ + m_error_state = false; + m_command_ctx.reset(); + m_command_ctx.proj = this; + m_project_command_stream.clear(); +}