Qt5 command options processing

This commit is contained in:
nemerle 2014-03-07 20:01:36 +01:00
parent 50950028e0
commit 3603877f42
11 changed files with 99 additions and 131 deletions

View File

@ -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()

View File

@ -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 */

View File

@ -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];

View File

@ -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 $?

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */
}
}

View File

@ -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 */