Qt5 command options processing
This commit is contained in:
@@ -167,7 +167,7 @@ void Project::writeGlobSymTable()
|
||||
|
||||
/* Writes the header information and global variables to the output C file
|
||||
* fp. */
|
||||
static void writeHeader (std::ostream &_ios, char *fileName)
|
||||
static void writeHeader (std::ostream &_ios, const char *fileName)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
/* Write header information */
|
||||
@@ -341,7 +341,7 @@ static void backBackEnd (CALL_GRAPH * pcallGraph, std::ostream &_ios)
|
||||
|
||||
|
||||
/* Invokes the necessary routines to produce code one procedure at a time. */
|
||||
void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
|
||||
void BackEnd (const std::string &fileName, CALL_GRAPH * pcallGraph)
|
||||
{
|
||||
std::ofstream fs; /* Output C file */
|
||||
|
||||
@@ -356,7 +356,7 @@ void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
|
||||
printf ("dcc: Writing C beta file %s\n", outNam.c_str());
|
||||
|
||||
/* Header information */
|
||||
writeHeader (fs, option.filename);
|
||||
writeHeader (fs, option.filename.c_str());
|
||||
|
||||
/* Initialize total Icode instructions statistics */
|
||||
stats.totalLL = 0;
|
||||
|
||||
@@ -68,7 +68,6 @@ void readFileSection(uint16_t* p, int len, FILE *_file);
|
||||
void cleanup(void);
|
||||
void checkStartup(STATE *state);
|
||||
void readProtoFile(void);
|
||||
void fixNewline(char *s);
|
||||
int searchPList(char *name);
|
||||
void checkHeap(char *msg); /* For debugging */
|
||||
|
||||
|
||||
150
src/dcc.cpp
150
src/dcc.cpp
@@ -4,13 +4,15 @@
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <cstring>
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
|
||||
#include "CallGraph.h"
|
||||
/* Global variables - extern to other modules */
|
||||
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
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 */
|
||||
@@ -40,6 +42,7 @@ static void displayTotalStats(void);
|
||||
/****************************************************************************
|
||||
* main
|
||||
***************************************************************************/
|
||||
#include <QtCore/QFile>
|
||||
#include <iostream>
|
||||
using namespace llvm;
|
||||
bool TVisitor(raw_ostream &OS, RecordKeeper &Records)
|
||||
@@ -111,11 +114,68 @@ int testTblGen(int argc, char **argv)
|
||||
|
||||
exit(0);
|
||||
|
||||
}
|
||||
void setupOptions(QCoreApplication &app) {
|
||||
//[-a1a2cmsi]
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("dcc");
|
||||
parser.addHelpOption();
|
||||
//parser.addVersionOption();
|
||||
//QCommandLineOption showProgressOption("p", QCoreApplication::translate("main", "Show progress during copy"));
|
||||
QCommandLineOption boolOpts[] {
|
||||
QCommandLineOption {"v", QCoreApplication::translate("main", "verbose")},
|
||||
QCommandLineOption {"V", QCoreApplication::translate("main", "very verbose")},
|
||||
QCommandLineOption {"c", QCoreApplication::translate("main", "Follow register indirect calls")},
|
||||
QCommandLineOption {"m", QCoreApplication::translate("main", "Print memory maps of program")},
|
||||
QCommandLineOption {"s", QCoreApplication::translate("main", "Print stats")}
|
||||
};
|
||||
for(QCommandLineOption &o : boolOpts) {
|
||||
parser.addOption(o);
|
||||
}
|
||||
QCommandLineOption assembly("a", QCoreApplication::translate("main", "Produce assembly"),"assembly_level");
|
||||
// A boolean option with multiple names (-f, --force)
|
||||
//QCommandLineOption forceOption(QStringList() << "f" << "force", "Overwrite existing files.");
|
||||
// An option with a value
|
||||
QCommandLineOption targetFileOption(QStringList() << "o" << "output",
|
||||
QCoreApplication::translate("main", "Place output into <file>."),
|
||||
QCoreApplication::translate("main", "file"));
|
||||
parser.addOption(targetFileOption);
|
||||
parser.addOption(assembly);
|
||||
//parser.addOption(forceOption);
|
||||
// Process the actual command line arguments given by the user
|
||||
parser.addPositionalArgument("source", QCoreApplication::translate("main", "Dos Executable file to decompile."));
|
||||
parser.process(app);
|
||||
|
||||
const QStringList args = parser.positionalArguments();
|
||||
if(args.empty()) {
|
||||
parser.showHelp();
|
||||
}
|
||||
// source is args.at(0), destination is args.at(1)
|
||||
option.verbose = parser.isSet(boolOpts[0]);
|
||||
option.VeryVerbose = parser.isSet(boolOpts[1]);
|
||||
if(parser.isSet(assembly)) {
|
||||
option.asm1 = parser.value(assembly).toInt()==1;
|
||||
option.asm2 = parser.value(assembly).toInt()==2;
|
||||
}
|
||||
option.Map = parser.isSet(boolOpts[3]);
|
||||
option.Stats = parser.isSet(boolOpts[4]);
|
||||
option.Interact = false;
|
||||
option.Calls = parser.isSet(boolOpts[2]);
|
||||
option.filename = args.first().toStdString();
|
||||
if(parser.isSet(targetFileOption))
|
||||
asm1_name = asm2_name = parser.value(targetFileOption).toStdString();
|
||||
else if(option.asm1 || option.asm2) {
|
||||
asm1_name = option.filename+".a1";
|
||||
asm2_name = option.filename+".a2";
|
||||
}
|
||||
|
||||
}
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* Extract switches and filename */
|
||||
strcpy(option.filename, initargs(argc, argv));
|
||||
QCoreApplication app(argc,argv);
|
||||
|
||||
QCoreApplication::setApplicationVersion("0.1");
|
||||
setupOptions(app);
|
||||
|
||||
/* 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
|
||||
@@ -138,98 +198,16 @@ int main(int argc, char **argv)
|
||||
* analysis, data flow etc. and outputs it to output file ready for
|
||||
* re-compilation.
|
||||
*/
|
||||
BackEnd(asm1_name ? asm1_name:option.filename, Project::get()->callGraph);
|
||||
BackEnd(!asm1_name.empty() ? asm1_name:option.filename, Project::get()->callGraph);
|
||||
|
||||
Project::get()->callGraph->write();
|
||||
|
||||
if (option.Stats)
|
||||
displayTotalStats();
|
||||
|
||||
/*
|
||||
freeDataStructures(pProcList);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* initargs - Extract command line arguments
|
||||
***************************************************************************/
|
||||
static char *initargs(int argc, char *argv[])
|
||||
{
|
||||
char *pc;
|
||||
|
||||
while (--argc > 0 && (*++argv)[0] == '-')
|
||||
{
|
||||
for (pc = argv[0]+1; *pc; pc++)
|
||||
switch (*pc)
|
||||
{
|
||||
case 'a': /* Print assembler listing */
|
||||
if (*(pc+1) == '2')
|
||||
option.asm2 = true;
|
||||
else
|
||||
option.asm1 = true;
|
||||
if (*(pc+1) == '1' || *(pc+1) == '2')
|
||||
pc++;
|
||||
break;
|
||||
case 'c':
|
||||
option.Calls = true;
|
||||
break;
|
||||
case 'i':
|
||||
option.Interact = true;
|
||||
break;
|
||||
case 'm': /* Print memory map */
|
||||
option.Map = true;
|
||||
break;
|
||||
case 's': /* Print Stats */
|
||||
option.Stats = true;
|
||||
break;
|
||||
case 'V': /* Very verbose => verbose */
|
||||
option.VeryVerbose = true;
|
||||
case 'v':
|
||||
option.verbose = true; /* Make everything verbose */
|
||||
break;
|
||||
case 'o': /* assembler output file */
|
||||
if (*(pc+1)) {
|
||||
asm1_name = asm2_name = pc+1;
|
||||
goto NextArg;
|
||||
}
|
||||
else if (--argc > 0) {
|
||||
asm1_name = asm2_name = *++argv;
|
||||
goto NextArg;
|
||||
}
|
||||
default:
|
||||
fatalError(INVALID_ARG, *pc);
|
||||
return *argv;
|
||||
}
|
||||
NextArg:;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
if (option.asm1 || option.asm2)
|
||||
{
|
||||
if (! asm1_name)
|
||||
{
|
||||
asm1_name = strcpy((char*)malloc(strlen(*argv)+4), *argv);
|
||||
pc = strrchr(asm1_name, '.');
|
||||
if (pc > strrchr(asm1_name, '/'))
|
||||
{
|
||||
*pc = '\0';
|
||||
}
|
||||
asm2_name = (char*)malloc(strlen(asm1_name)+4) ;
|
||||
strcat(strcpy(asm2_name, asm1_name), ".a2");
|
||||
unlink(asm2_name);
|
||||
strcat(asm1_name, ".a1");
|
||||
}
|
||||
unlink(asm1_name); /* Remove asm output files */
|
||||
}
|
||||
return *argv; /* filename of the program to decompile */
|
||||
}
|
||||
|
||||
fatalError(USAGE);
|
||||
return *argv; // does not reach this.
|
||||
}
|
||||
|
||||
static void
|
||||
displayTotalStats ()
|
||||
/* Displays final statistics for the complete program */
|
||||
|
||||
@@ -153,7 +153,7 @@ void Disassembler::disassem(Function * ppProc)
|
||||
m_fp.open(p,ios_base::app);
|
||||
if (!m_fp.is_open())
|
||||
{
|
||||
fatalError(CANNOT_OPEN, p);
|
||||
fatalError(CANNOT_OPEN, p.c_str());
|
||||
}
|
||||
}
|
||||
/* Create temporary code array */
|
||||
|
||||
@@ -82,7 +82,7 @@ bool DccFrontend::FrontEnd ()
|
||||
|
||||
if (option.asm1)
|
||||
{
|
||||
printf("dcc: writing assembler file %s\n", asm1_name);
|
||||
printf("dcc: writing assembler file %s\n", asm1_name.c_str());
|
||||
}
|
||||
|
||||
/* Search through code looking for impure references and flag them */
|
||||
|
||||
@@ -27,7 +27,6 @@ const char *indentStr(int indLevel) // Indentation according to the depth of the
|
||||
* not exist. */
|
||||
void CALL_GRAPH::insertArc (ilFunction newProc)
|
||||
{
|
||||
CALL_GRAPH *pcg;
|
||||
|
||||
|
||||
/* Check if procedure already exists */
|
||||
@@ -35,7 +34,7 @@ void CALL_GRAPH::insertArc (ilFunction newProc)
|
||||
if(res!=outEdges.end())
|
||||
return;
|
||||
/* Include new arc */
|
||||
pcg = new CALL_GRAPH;
|
||||
CALL_GRAPH *pcg = new CALL_GRAPH;
|
||||
pcg->proc = newProc;
|
||||
outEdges.push_back(pcg);
|
||||
}
|
||||
@@ -49,13 +48,10 @@ bool CALL_GRAPH::insertCallGraph(ilFunction caller, ilFunction callee)
|
||||
insertArc (callee);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (CALL_GRAPH *edg : outEdges)
|
||||
if (edg->insertCallGraph (caller, callee))
|
||||
return true;
|
||||
return (false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CALL_GRAPH::insertCallGraph(Function *caller, ilFunction callee)
|
||||
@@ -333,7 +329,6 @@ void STKFRAME::adjustForArgType(size_t numArg_, hlType actType_)
|
||||
{
|
||||
hlType forType;
|
||||
STKSYM * psym, * nsym;
|
||||
int off;
|
||||
/* If formal argument does not exist, do not create new ones, just
|
||||
* ignore actual argument
|
||||
*/
|
||||
@@ -341,7 +336,7 @@ void STKFRAME::adjustForArgType(size_t numArg_, hlType actType_)
|
||||
return;
|
||||
|
||||
/* Find stack offset for this argument */
|
||||
off = m_minOff;
|
||||
int off = m_minOff;
|
||||
size_t i=0;
|
||||
for(STKSYM &s : *this) // walk formal arguments upto numArg_
|
||||
{
|
||||
@@ -353,7 +348,6 @@ void STKFRAME::adjustForArgType(size_t numArg_, hlType actType_)
|
||||
|
||||
/* Find formal argument */
|
||||
//psym = &at(numArg_);
|
||||
//i = numArg_;
|
||||
//auto iter=std::find_if(sym.begin(),sym.end(),[off](STKSYM &s)->bool {s.off==off;});
|
||||
auto iter=std::find_if(begin()+numArg_,end(),[off](STKSYM &s)->bool {return s.label==off;});
|
||||
if(iter==end()) // symbol not found
|
||||
@@ -361,15 +355,16 @@ void STKFRAME::adjustForArgType(size_t numArg_, hlType actType_)
|
||||
psym = &(*iter);
|
||||
|
||||
forType = psym->type;
|
||||
if (forType != actType_)
|
||||
{
|
||||
if (forType == actType_)
|
||||
return;
|
||||
switch (actType_) {
|
||||
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
|
||||
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
|
||||
case TYPE_WORD_UNSIGN: case TYPE_RECORD:
|
||||
break;
|
||||
|
||||
case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN:
|
||||
case TYPE_LONG_UNSIGN:
|
||||
case TYPE_LONG_SIGN:
|
||||
if ((forType == TYPE_WORD_UNSIGN) ||
|
||||
(forType == TYPE_WORD_SIGN) ||
|
||||
(forType == TYPE_UNKNOWN))
|
||||
@@ -395,6 +390,5 @@ void STKFRAME::adjustForArgType(size_t numArg_, hlType actType_)
|
||||
default:
|
||||
fprintf(stderr,"STKFRAME::adjustForArgType unhandled actType_ %d \n",actType_);
|
||||
} /* eos */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include <utility>
|
||||
#include "dcc.h"
|
||||
#include "CallGraph.h"
|
||||
#include "project.h"
|
||||
#include "Procedure.h"
|
||||
using namespace std;
|
||||
//Project g_proj;
|
||||
char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
string asm1_name, asm2_name; /* Assembler output filenames */
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
STATS stats; /* cfg statistics */
|
||||
//PROG prog; /* programs fields */
|
||||
|
||||
Reference in New Issue
Block a user