Working towards gui integration with exetoc_qt
This commit is contained in:
@@ -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
src/DccFrontend.cpp
Normal file
410
src/DccFrontend.cpp
Normal file
@@ -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();
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,17 +5,16 @@
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
|
||||
#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"
|
||||
#include "dcc_interface.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <string.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)
|
||||
if ((fProto = fopen(qPrintable(szProFName), "rb")) == nullptr)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
52
src/dcc.cpp
52
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
src/dcc_interface.cpp
Normal file
61
src/dcc_interface.cpp
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user