Qt5 command options processing
This commit is contained in:
parent
50950028e0
commit
3603877f42
@ -1,5 +1,8 @@
|
||||
PROJECT(dcc_original)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
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})
|
||||
@ -9,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++0x")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++11")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} " ) #--coverage
|
||||
ENDIF()
|
||||
|
||||
@ -34,6 +37,7 @@ INCLUDE_DIRECTORIES(
|
||||
${LLVM_INCLUDE_DIRS}
|
||||
)
|
||||
set(dcc_LIB_SOURCES
|
||||
src/CallConvention.cpp
|
||||
src/ast.cpp
|
||||
src/backend.cpp
|
||||
src/bundle.cpp
|
||||
@ -73,7 +77,6 @@ set(dcc_LIB_SOURCES
|
||||
src/symtab.cpp
|
||||
src/udm.cpp
|
||||
src/BasicBlock.cpp
|
||||
src/CallConvention.cpp
|
||||
)
|
||||
set(dcc_SOURCES
|
||||
src/dcc.cpp
|
||||
@ -100,6 +103,7 @@ set(dcc_HEADERS
|
||||
include/idioms/shift_idioms.h
|
||||
include/idioms/xor_idioms.h
|
||||
include/locident.h
|
||||
include/CallConvention.h
|
||||
include/perfhlib.h
|
||||
include/project.h
|
||||
include/scanner.h
|
||||
@ -109,7 +113,6 @@ set(dcc_HEADERS
|
||||
include/Procedure.h
|
||||
include/StackFrame.h
|
||||
include/BasicBlock.h
|
||||
include/CallConvention.h
|
||||
|
||||
)
|
||||
SOURCE_GROUP(Source FILES ${dcc_SOURCES})
|
||||
@ -120,7 +123,8 @@ ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS})
|
||||
|
||||
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
|
||||
ADD_DEPENDENCIES(dcc_original dcc_lib)
|
||||
TARGET_LINK_LIBRARIES(dcc_original LLVMSupport dcc_lib disasm_s ${REQ_LLVM_LIBRARIES} LLVMSupport)
|
||||
TARGET_LINK_LIBRARIES(dcc_original dcc_lib disasm_s ${REQ_LLVM_LIBRARIES} ncurses LLVMSupport)
|
||||
qt5_use_modules(dcc_original Core)
|
||||
if(dcc_build_tests)
|
||||
ADD_SUBDIRECTORY(src)
|
||||
endif()
|
||||
|
||||
@ -26,7 +26,7 @@ extern bundle cCode; /* Output C procedure's declaration and code */
|
||||
|
||||
/**** Global variables ****/
|
||||
|
||||
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
extern std::string asm1_name, asm2_name; /* Assembler output filenames */
|
||||
|
||||
typedef struct { /* Command line option flags */
|
||||
unsigned verbose : 1;
|
||||
@ -37,7 +37,7 @@ typedef struct { /* Command line option flags */
|
||||
unsigned Stats : 1;
|
||||
unsigned Interact : 1; /* Interactive mode */
|
||||
unsigned Calls : 1; /* Follow register indirect calls */
|
||||
char filename[80]; /* The input filename */
|
||||
std::string filename; /* The input filename */
|
||||
} OPTION;
|
||||
|
||||
extern OPTION option; /* Command line options */
|
||||
@ -86,7 +86,7 @@ public:
|
||||
void udm(void); /* udm.c */
|
||||
void freeCFG(BB * cfg); /* graph.c */
|
||||
BB * newBB(BB *, int, int, uint8_t, int, Function *); /* graph.c */
|
||||
void BackEnd(char *filename, CALL_GRAPH *); /* backend.c */
|
||||
void BackEnd(const std::string &filename, 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 */
|
||||
|
||||
@ -36,21 +36,13 @@ struct SYM : public SymbolCommon
|
||||
struct STKSYM : public SymbolCommon
|
||||
{
|
||||
typedef int16_t tLabel;
|
||||
Expr *actual; /* Expression tree of actual parameter */
|
||||
AstIdent *regs; /* For register arguments only */
|
||||
tLabel label; /* Immediate off from BP (+:args, -:params) */
|
||||
uint8_t regOff; /* Offset is a register (e.g. SI, DI) */
|
||||
bool hasMacro; /* This type needs a macro */
|
||||
Expr *actual=0; /* Expression tree of actual parameter */
|
||||
AstIdent *regs=0; /* For register arguments only */
|
||||
tLabel label=0; /* Immediate off from BP (+:args, -:params) */
|
||||
uint8_t regOff=0; /* Offset is a register (e.g. SI, DI) */
|
||||
bool hasMacro=false; /* This type needs a macro */
|
||||
std::string macro; /* Macro name */
|
||||
bool invalid; /* Boolean: invalid entry in formal arg list*/
|
||||
STKSYM()
|
||||
{
|
||||
actual=0;
|
||||
regs=0;
|
||||
label=0;
|
||||
regOff=0;
|
||||
invalid=hasMacro = false;
|
||||
}
|
||||
bool invalid=false; /* Boolean: invalid entry in formal arg list*/
|
||||
void setArgName(int i)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
@ -14,9 +14,9 @@ def perform_test(exepath,filepath,outname,args)
|
||||
filepath=path_local(filepath)
|
||||
joined_args = args.join(' ')
|
||||
printf("calling:" + "#{exepath} -a1 #{joined_args} -o#{output_path}.a1 #{filepath}\n")
|
||||
STDERR << "Errors for : #{filepath}"
|
||||
result = `#{exepath} -a1 -o#{output_path}.a1 #{filepath}`
|
||||
result = `#{exepath} -a2 #{joined_args} -o#{output_path}.a2 #{filepath}`
|
||||
STDERR << "Errors for : #{filepath}\n"
|
||||
result = `#{exepath} -a 1 -o#{output_path}.a1 #{filepath}`
|
||||
result = `#{exepath} -a 2 #{joined_args} -o#{output_path}.a2 #{filepath}`
|
||||
result = `#{exepath} #{joined_args} -o#{output_path} #{filepath}`
|
||||
puts result
|
||||
p $?
|
||||
|
||||
@ -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 */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user