GUI work.
This commit is contained in:
parent
2452984864
commit
95acbaa7fa
@ -96,6 +96,22 @@ set(dcc_LIB_SOURCES
|
||||
src/Loaders.cpp
|
||||
src/Loaders.h
|
||||
)
|
||||
set(dcc_UI_SOURCES
|
||||
src/ui/DccMainWindow.ui
|
||||
src/ui/DccMainWindow.h
|
||||
src/ui/DccMainWindow.cpp
|
||||
src/ui/FunctionViewWidget.ui
|
||||
src/ui/FunctionViewWidget.h
|
||||
src/ui/FunctionViewWidget.cpp
|
||||
src/ui/FunctionListDockWidget.ui
|
||||
src/ui/FunctionListDockWidget.cpp
|
||||
src/ui/FunctionListDockWidget.h
|
||||
src/ui/RenderTags.cpp
|
||||
src/ui/RenderTags.h
|
||||
src/ui/CommandQueueView.cpp
|
||||
src/ui/CommandQueueView.h
|
||||
src/ui/CommandQueueView.ui
|
||||
)
|
||||
set(dcc_SOURCES
|
||||
src/dcc.cpp
|
||||
)
|
||||
@ -142,7 +158,7 @@ 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})
|
||||
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_UI_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 Widgets)
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
/** Perfect hashing function library. Contains functions to generate perfect
|
||||
hashing functions */
|
||||
|
||||
@ -14,10 +14,8 @@ struct PROG /* Loaded program image parameters */
|
||||
int cProcs; /* Number of procedures so far */
|
||||
int offMain; /* The offset of the main() proc */
|
||||
uint16_t segMain; /* The segment of the main() proc */
|
||||
bool bSigs; /* True if signatures loaded */
|
||||
int cbImage; /* Length of image in bytes */
|
||||
uint8_t * Imagez; /* Allocated by loader to hold entire program image */
|
||||
int addressingMode;
|
||||
public:
|
||||
const uint8_t *image() const {return Imagez;}
|
||||
void displayLoadInfo();
|
||||
|
||||
@ -9,7 +9,6 @@ class DccFrontend : public QObject
|
||||
public:
|
||||
explicit DccFrontend(QObject *parent = 0);
|
||||
bool FrontEnd(); /* frontend.c */
|
||||
void initializeMachineState(Project & proj);
|
||||
|
||||
signals:
|
||||
|
||||
|
||||
@ -164,6 +164,7 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
int nStep; // decompilation step number for this function
|
||||
FunctionType * type;
|
||||
uint32_t procEntry; /* label number */
|
||||
QString name; /* Meaningful name for this proc */
|
||||
|
||||
@ -88,7 +88,7 @@ void interactDis(Function *, int initIC); /* disassem.c */
|
||||
bool JmpInst(llIcode opcode); /* idioms.c */
|
||||
queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */
|
||||
|
||||
bool SetupLibCheck(void); /* chklib.c */
|
||||
bool SetupLibCheck(QString pattern_file_id); /* chklib.c */
|
||||
void CleanupLibCheck(void); /* chklib.c */
|
||||
bool LibCheck(Function &p); /* chklib.c */
|
||||
|
||||
|
||||
@ -5,18 +5,20 @@
|
||||
#include <QtCore/QDir>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
|
||||
class IXmlTarget;
|
||||
class IStructuredTextTarget;
|
||||
|
||||
struct IDcc {
|
||||
static IDcc *get();
|
||||
virtual void BaseInit()=0;
|
||||
virtual void Init(QObject *tgt)=0;
|
||||
virtual lFunction::iterator GetFirstFuncHandle()=0;
|
||||
virtual lFunction::iterator GetCurFuncHandle()=0;
|
||||
virtual ilFunction GetFirstFuncHandle()=0;
|
||||
virtual ilFunction GetNextFuncHandle(ilFunction iter)=0;
|
||||
virtual ilFunction GetCurFuncHandle()=0;
|
||||
virtual bool isValidFuncHandle(ilFunction) = 0;
|
||||
virtual void analysis_Once()=0;
|
||||
virtual void load(QString name)=0; // load and preprocess -> find entry point
|
||||
virtual void prtout_asm(IXmlTarget *,int level=0)=0;
|
||||
virtual void prtout_cpp(IXmlTarget *,int level=0)=0;
|
||||
virtual bool load(QString name)=0; // load and preprocess -> find entry point
|
||||
virtual void prtout_asm(IStructuredTextTarget *,int level=0)=0;
|
||||
virtual void prtout_cpp(IStructuredTextTarget *,int level=0)=0;
|
||||
virtual size_t getFuncCount()=0;
|
||||
virtual const lFunction &validFunctions() const =0;
|
||||
virtual void SetCurFunc_by_Name(QString )=0;
|
||||
|
||||
@ -25,6 +25,62 @@ struct SegOffAddr {
|
||||
uint16_t seg;
|
||||
uint32_t addr;
|
||||
};
|
||||
enum CompilerVendor {
|
||||
eUnknownVendor=0,
|
||||
eBorland,
|
||||
eMicrosoft,
|
||||
eLogitech,
|
||||
};
|
||||
enum CompilerLanguage {
|
||||
eUnknownLanguage=0,
|
||||
eAnsiCorCPP,
|
||||
ePascal,
|
||||
eModula2
|
||||
};
|
||||
enum CompilerMemoryModel {
|
||||
eUnknownMemoryModel=0,
|
||||
eTiny,
|
||||
eSmall,
|
||||
eCompact,
|
||||
eMedium,
|
||||
eLarge
|
||||
};
|
||||
struct LoaderMetadata {
|
||||
CompilerVendor compiler_vendor;
|
||||
CompilerLanguage compiler_language;
|
||||
CompilerMemoryModel compiler_memory_model;
|
||||
int compiler_version;
|
||||
QString compilerId() const {
|
||||
switch(compiler_vendor) {
|
||||
case eBorland:
|
||||
switch(compiler_language) {
|
||||
case eUnknownLanguage:
|
||||
return QString("bx") + codeModelChar();
|
||||
case eAnsiCorCPP:
|
||||
return QString("b%1%2").arg(compiler_version).arg(codeModelChar());
|
||||
case ePascal:
|
||||
return QString("tp%1").arg(compiler_version);
|
||||
}
|
||||
case eMicrosoft:
|
||||
assert(compiler_language==eAnsiCorCPP);
|
||||
return QString("m%1%2").arg(compiler_version).arg(codeModelChar());
|
||||
case eLogitech:
|
||||
assert(compiler_language==eModula2);
|
||||
return QString("l%1%2").arg(compiler_version).arg(codeModelChar());
|
||||
}
|
||||
return "xxx";
|
||||
}
|
||||
QChar codeModelChar() const {
|
||||
switch(compiler_memory_model) {
|
||||
case eUnknownMemoryModel: return 'x';
|
||||
case eTiny: return 't';
|
||||
case eSmall: return 's';
|
||||
case eCompact: return 'c';
|
||||
case eMedium: return 'm';
|
||||
case eLarge: return 'l';
|
||||
}
|
||||
}
|
||||
};
|
||||
class Project : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -33,8 +89,10 @@ public:
|
||||
typedef FunctionListType lFunction;
|
||||
typedef FunctionListType::iterator ilFunction;
|
||||
|
||||
DosLoader * m_selected_loader;
|
||||
public:
|
||||
DosLoader * m_selected_loader;
|
||||
bool m_metadata_available=false;
|
||||
LoaderMetadata m_loader_data;
|
||||
uint32_t SynthLab; //!< Last snthetic lab idx
|
||||
SYMTAB symtab; //!< Global symbol table
|
||||
FunctionListType pProcList; //!< List of located functions
|
||||
@ -44,6 +102,7 @@ public:
|
||||
PROG prog; /* Loaded program image parameters */
|
||||
CommandStream m_project_command_stream;
|
||||
bool m_error_state;
|
||||
struct PatternLocator *m_pattern_locator;
|
||||
public:
|
||||
// prevent Project instance copying
|
||||
Project(const Project&) = delete;
|
||||
@ -74,6 +133,8 @@ public:
|
||||
const QString & symbolName(size_t idx);
|
||||
const SYM & getSymByIdx(size_t idx) const;
|
||||
|
||||
LoaderMetadata &getLoaderMetadata() { assert(m_metadata_available); return m_loader_data; }
|
||||
void setLoaderMetadata(LoaderMetadata d) { m_loader_data = d; m_metadata_available=true;}
|
||||
static Project * get();
|
||||
PROG * binary() {return &prog;}
|
||||
SourceMachine *machine();
|
||||
@ -81,14 +142,16 @@ public:
|
||||
const FunctionListType &functions() const { return pProcList; }
|
||||
FunctionListType &functions() { return pProcList; }
|
||||
|
||||
bool addCommand(Command *cmd) { return m_project_command_stream.add(cmd); }
|
||||
bool addCommand(Command *cmd) { return m_project_command_stream.add(cmd); emit commandListChanged(); }
|
||||
void dumpAllErrors();
|
||||
void setLoader(DosLoader *ins);
|
||||
void processCommands(int count=1);
|
||||
public slots:
|
||||
void onCommandStreamFinished(bool state);
|
||||
signals:
|
||||
void newFunctionCreated(Function &);
|
||||
void loaderSelected();
|
||||
void commandListChanged();
|
||||
protected:
|
||||
void initialize();
|
||||
void writeGlobSymTable();
|
||||
|
||||
BIN
sigs/dccb3l.sig
Normal file
BIN
sigs/dccb3l.sig
Normal file
Binary file not shown.
BIN
sigs/dccb3s.SIG
Normal file
BIN
sigs/dccb3s.SIG
Normal file
Binary file not shown.
@ -8,7 +8,7 @@
|
||||
|
||||
bool LoaderSelection::execute(CommandContext * ctx)
|
||||
{
|
||||
Project *proj=ctx->proj;
|
||||
Project *proj=ctx->m_project;
|
||||
if(nullptr==proj) {
|
||||
ctx->recordFailure(this,"No active project ");
|
||||
return false;
|
||||
@ -47,7 +47,7 @@ bool LoaderSelection::execute(CommandContext * ctx)
|
||||
|
||||
bool LoaderApplication::execute(CommandContext * ctx)
|
||||
{
|
||||
Project *proj=ctx->proj;
|
||||
Project *proj=ctx->m_project;
|
||||
|
||||
if(nullptr==proj) {
|
||||
ctx->recordFailure(this,"No active project ");
|
||||
@ -96,6 +96,20 @@ void CommandStream::processAll(CommandContext *ctx)
|
||||
emit streamCompleted(true);
|
||||
}
|
||||
|
||||
bool CommandStream::processOne(CommandContext *ctx)
|
||||
{
|
||||
if(not m_commands.isEmpty()) {
|
||||
Command *cmd = m_commands.takeFirst();
|
||||
if(false==cmd->execute(ctx)) {
|
||||
emit streamChanged();
|
||||
return false;
|
||||
}
|
||||
m_recently_executed.push_back(cmd);
|
||||
}
|
||||
emit streamChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommandStream::clear()
|
||||
{
|
||||
qDeleteAll(m_commands);
|
||||
|
||||
@ -21,7 +21,7 @@ public:
|
||||
m_failures.push_back({cmd,error_message});
|
||||
}
|
||||
|
||||
Project *proj;
|
||||
Project *m_project;
|
||||
QVector<QPair<Command *,QString>> m_failures;
|
||||
void reset();
|
||||
};
|
||||
@ -60,10 +60,12 @@ public:
|
||||
QVector<Command *> m_commands;
|
||||
bool add(Command *c);
|
||||
void setMaximumCommandCount(int maximum_command_count);
|
||||
bool processOne(CommandContext *ctx);
|
||||
void processAll(CommandContext *ctx);
|
||||
void clear();
|
||||
signals:
|
||||
void streamCompleted(bool success);
|
||||
void streamChanged();
|
||||
};
|
||||
// Effect: loader has been selected and set in current project
|
||||
class LoaderSelection : public Command {
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "disassem.h"
|
||||
#include "CallGraph.h"
|
||||
#include "Command.h"
|
||||
#include "chklib.h"
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QDebug>
|
||||
@ -157,8 +158,8 @@ public:
|
||||
|
||||
bool execute(CommandContext *ctx) override
|
||||
{
|
||||
assert(ctx && ctx->proj);
|
||||
Project &proj(*ctx->proj);
|
||||
assert(ctx && ctx->m_project);
|
||||
Project &proj(*ctx->m_project);
|
||||
const PROG &prog(proj.prog);
|
||||
proj.m_entry_state.setState(rES, 0); /* PSP segment */
|
||||
proj.m_entry_state.setState(rDS, 0);
|
||||
@ -180,7 +181,7 @@ struct CreateFunction : public Command {
|
||||
m_type(f)
|
||||
{}
|
||||
bool execute(CommandContext *ctx) override {
|
||||
Project &proj(*ctx->proj);
|
||||
Project &proj(*ctx->m_project);
|
||||
const PROG &prog(proj.prog);
|
||||
|
||||
proj.createFunction(m_type,m_name,m_addr);
|
||||
@ -201,15 +202,15 @@ struct FindMain : public Command {
|
||||
FindMain() : Command("Locate the main entry point",eProject) {
|
||||
}
|
||||
bool execute(CommandContext *ctx) {
|
||||
Project &proj(*ctx->proj);
|
||||
Project &proj(*ctx->m_project);
|
||||
const PROG &prog(proj.prog);
|
||||
|
||||
if(ctx->proj->m_entry_state.IP==0) {
|
||||
if(ctx->m_project->m_entry_state.IP==0) {
|
||||
ctx->recordFailure(this,"Cannot search for main func when no entry point was found");
|
||||
return false;
|
||||
}
|
||||
/* Check for special settings of initial state, based on idioms of the startup code */
|
||||
ctx->proj->m_entry_state.checkStartup();
|
||||
checkStartup(ctx->m_project->m_entry_state);
|
||||
Command *cmd;
|
||||
if (prog.offMain != -1)
|
||||
{
|
||||
@ -227,29 +228,15 @@ struct FindMain : public Command {
|
||||
cmd = new CreateFunction("start",SegOffAddr {prog.segMain,proj.m_entry_state.IP},main_type);
|
||||
}
|
||||
proj.addCommand(cmd);
|
||||
proj.addCommand(new LoadPatternLibrary());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
void DccFrontend::initializeMachineState(Project &proj)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* Parses the program, builds the call graph, and returns the list of
|
||||
* procedures found */
|
||||
void DccFrontend::parse(Project &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 */
|
||||
proj.prog.bSigs = SetupLibCheck();
|
||||
|
||||
/* Set initial state */
|
||||
proj.addCommand(new MachineStateInitialization);
|
||||
proj.addCommand(new FindMain);
|
||||
|
||||
@ -226,7 +226,7 @@ void Function::codeGen (QIODevice &fs)
|
||||
|
||||
/* Write procedure/function header */
|
||||
cCode.init();
|
||||
if (getReturnType() != TYPE_UNKNOWN) /* Function flg & PROC_IS_FUNC*/
|
||||
if (getReturnType() != TYPE_UNKNOWN) /* Function */
|
||||
ostr << QString("\n%1 %2 (").arg(TypeContainer::typeName(getReturnType())).arg(name);
|
||||
else /* Procedure */
|
||||
ostr << "\nvoid "+name+" (";
|
||||
|
||||
576
src/chklib.cpp
576
src/chklib.cpp
@ -4,7 +4,9 @@
|
||||
* address of main()
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
#include "chklib.h"
|
||||
|
||||
#include "Enums.h"
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "project.h"
|
||||
@ -18,22 +20,21 @@
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include "Command.h"
|
||||
|
||||
PerfectHash g_pattern_hasher;
|
||||
#define NIL -1 /* Used like NULL, but 0 is valid */
|
||||
|
||||
/* Hash table structure */
|
||||
typedef struct HT_tag
|
||||
struct HT
|
||||
{
|
||||
char htSym[SYMLEN];
|
||||
uint8_t htPat[PATLEN];
|
||||
} HT;
|
||||
};
|
||||
|
||||
/* Structure of the prototypes table. Same as the struct in parsehdr.h,
|
||||
except here we don't need the "next" index (the elements are already
|
||||
sorted by function name) */
|
||||
typedef
|
||||
struct ph_func_tag
|
||||
struct PH_FUNC_STRUCT
|
||||
{
|
||||
char name[SYMLEN]; /* Name of function or arg */
|
||||
hlType typ; /* Return type */
|
||||
@ -41,38 +42,24 @@ struct ph_func_tag
|
||||
int firstArg; /* Index of first arg in chain */
|
||||
// int next; /* Index of next function in chain */
|
||||
bool bVararg; /* True if variable arguements */
|
||||
} PH_FUNC_STRUCT;
|
||||
} ;
|
||||
|
||||
|
||||
#define NUM_PLIST 64 /* Number of entries to increase allocation by */
|
||||
|
||||
/* statics */
|
||||
static char buf[100]; /* A general purpose buffer */
|
||||
int numKeys; /* Number of hash table entries (keys) */
|
||||
int numVert; /* Number of vertices in the graph (also size of g[]) */
|
||||
unsigned PatLen; /* Size of the keys (pattern length) */
|
||||
unsigned SymLen; /* Max size of the symbols, including null */
|
||||
static FILE *g_file; /* File being read */
|
||||
static QString sSigName; /* Full path name of .sig file */
|
||||
|
||||
static uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
static uint16_t *g; /* g[] */
|
||||
static HT *ht; /* The hash table */
|
||||
static PH_FUNC_STRUCT *pFunc; /* Points to the array of func names */
|
||||
static hlType *pArg=nullptr; /* Points to the array of param types */
|
||||
static int numFunc; /* Number of func names actually stored */
|
||||
static int numArg; /* Number of param names actually stored */
|
||||
#define DCCLIBS "dcclibs.dat" /* Name of the prototypes data file */
|
||||
|
||||
/* prototypes */
|
||||
void grab(int n, FILE *_file);
|
||||
uint16_t readFileShort(FILE *_file);
|
||||
void readFileSection(uint16_t* p, int len, FILE *_file);
|
||||
void cleanup(void);
|
||||
void checkStartup(STATE *state);
|
||||
void readProtoFile(void);
|
||||
int searchPList(char *name);
|
||||
void checkHeap(char *msg); /* For debugging */
|
||||
static bool grab(int n, QFile & _file);
|
||||
static uint16_t readFileShort(FILE *_file);
|
||||
static void readFileSection(uint16_t* p, int len, QFile & _file);
|
||||
static void cleanup(void);
|
||||
static void readProtoFile(void);
|
||||
static int searchPList(char *name);
|
||||
static void checkHeap(char *msg); /* For debugging */
|
||||
|
||||
void fixWildCards(uint8_t pat[]); /* In fixwild.c */
|
||||
|
||||
@ -294,148 +281,10 @@ static uint8_t pattMsChkstk[] =
|
||||
0xE9 /* jmp XXXX */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* This procedure is called to initialise the library check code */
|
||||
bool SetupLibCheck(void)
|
||||
{
|
||||
uint16_t w, len;
|
||||
int i;
|
||||
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", qPrintable(fpath));
|
||||
return false;
|
||||
}
|
||||
|
||||
readProtoFile();
|
||||
|
||||
|
||||
/* Read the parameters */
|
||||
grab(4, g_file);
|
||||
if (memcmp("dccs", buf, 4) != 0)
|
||||
{
|
||||
printf("Not a dcc signature file!\n");
|
||||
exit(3);
|
||||
}
|
||||
numKeys = readFileShort(g_file);
|
||||
numVert = readFileShort(g_file);
|
||||
PatLen = readFileShort(g_file);
|
||||
SymLen = readFileShort(g_file);
|
||||
if ((PatLen != PATLEN) or (SymLen != SYMLEN))
|
||||
{
|
||||
printf("Sorry! Compiled for sym and pattern lengths of %d and %d\n", SYMLEN, PATLEN);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialise the perfhlib stuff. Also allocates T1, T2, g, etc */
|
||||
/* Set the parameters for the hash table */
|
||||
g_pattern_hasher.setHashParams(
|
||||
numKeys, /* The number of symbols */
|
||||
PatLen, /* The length of the pattern to be hashed */
|
||||
256, /* The character set of the pattern (0-FF) */
|
||||
0, /* Minimum pattern character value */
|
||||
numVert); /* Specifies c, the sparseness of the graph. See Czech, Havas and Majewski for details */
|
||||
T1base = g_pattern_hasher.readT1();
|
||||
T2base = g_pattern_hasher.readT2();
|
||||
g = g_pattern_hasher.readG();
|
||||
|
||||
/* Read T1 and T2 tables */
|
||||
grab(2, g_file);
|
||||
if (memcmp("T1", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'T1'\n");
|
||||
exit(3);
|
||||
}
|
||||
len = (uint16_t) (PatLen * 256 * sizeof(uint16_t));
|
||||
w = readFileShort(g_file);
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of T1: file %d, calc %d\n", w, len);
|
||||
return false;
|
||||
}
|
||||
readFileSection(T1base, len, g_file);
|
||||
|
||||
grab(2, g_file);
|
||||
if (memcmp("T2", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'T2'\n");
|
||||
return false;
|
||||
}
|
||||
w = readFileShort(g_file);
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of T2: file %d, calc %d\n", w, len);
|
||||
return false;
|
||||
}
|
||||
readFileSection(T2base, len, g_file);
|
||||
|
||||
/* Now read the function g[] */
|
||||
grab(2, g_file);
|
||||
if (memcmp("gg", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'gg'\n");
|
||||
return false;
|
||||
}
|
||||
len = (uint16_t)(numVert * sizeof(uint16_t));
|
||||
w = readFileShort(g_file);
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of g[]: file %d, calc %d\n", w, len);
|
||||
return false;
|
||||
}
|
||||
readFileSection(g, len, g_file);
|
||||
|
||||
|
||||
/* This is now the hash table */
|
||||
/* First allocate space for the table */
|
||||
ht = new HT[numKeys];
|
||||
if ( nullptr == ht)
|
||||
{
|
||||
printf("Could not allocate hash table\n");
|
||||
return false;
|
||||
}
|
||||
grab(2, g_file);
|
||||
if (memcmp("ht", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'ht'\n");
|
||||
return false;
|
||||
}
|
||||
w = readFileShort(g_file);
|
||||
if (w != numKeys * (SymLen + PatLen + sizeof(uint16_t)))
|
||||
{
|
||||
printf("Problem with size of hash table: file %d, calc %d\n", w, len);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
for (i=0; i < numKeys; i++)
|
||||
{
|
||||
if (fread(&ht[i], 1, SymLen + PatLen, g_file) != SymLen + PatLen)
|
||||
{
|
||||
printf("Could not read signature\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fclose(g_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CleanupLibCheck(void)
|
||||
{
|
||||
/* Deallocate all the stuff allocated in SetupLibCheck() */
|
||||
delete [] ht;
|
||||
delete [] pFunc;
|
||||
}
|
||||
|
||||
|
||||
/* Check this function to see if it is a library function. Return true if
|
||||
it is, and copy its name to pProc->name
|
||||
*/
|
||||
bool LibCheck(Function & pProc)
|
||||
bool PatternLocator::LibCheck(Function & pProc)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
long fileOffset;
|
||||
@ -443,13 +292,6 @@ bool LibCheck(Function & pProc)
|
||||
int Idx;
|
||||
uint8_t pat[PATLEN];
|
||||
|
||||
if (prog.bSigs == false)
|
||||
{
|
||||
/* No signatures... can't rely on hash parameters to be initialised
|
||||
so always return false */
|
||||
return false;
|
||||
}
|
||||
|
||||
fileOffset = pProc.procEntry; /* Offset into the image */
|
||||
if (fileOffset == prog.offMain)
|
||||
{
|
||||
@ -545,35 +387,29 @@ bool LibCheck(Function & pProc)
|
||||
|
||||
|
||||
|
||||
void grab(int n, FILE *_file)
|
||||
bool grab(int n, QFile &_file)
|
||||
{
|
||||
if (fread(buf, 1, n, _file) != (unsigned)n)
|
||||
|
||||
if (_file.read(buf,n) != n)
|
||||
{
|
||||
printf("Could not grab\n");
|
||||
exit(11);
|
||||
qCritical() << "File read failed";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
readFileShort(FILE *f)
|
||||
uint16_t readFileShort(QFile &f)
|
||||
{
|
||||
uint8_t b1, b2;
|
||||
|
||||
if (fread(&b1, 1, 1, f) != 1)
|
||||
{
|
||||
printf("Could not read short\n");
|
||||
exit(11);
|
||||
uint16_t tgt;
|
||||
if(sizeof(tgt)!=f.read((char *)&tgt,sizeof(tgt))) {
|
||||
qCritical() << "File read failed";
|
||||
return false;
|
||||
}
|
||||
if (fread(&b2, 1, 1, f) != 1)
|
||||
{
|
||||
printf("Could not read short\n");
|
||||
exit(11);
|
||||
}
|
||||
return (uint16_t)(b2 << 8) + (uint16_t)b1;
|
||||
return tgt;
|
||||
}
|
||||
|
||||
// Read a section of the file, considering endian issues
|
||||
void readFileSection(uint16_t* p, int len, FILE* f)
|
||||
static void readFileSection(uint16_t* p, int len, QFile & f)
|
||||
{
|
||||
for (int i=0; i < len; i += 2)
|
||||
{
|
||||
@ -581,23 +417,11 @@ void readFileSection(uint16_t* p, int len, FILE* f)
|
||||
}
|
||||
}
|
||||
|
||||
/* The following two functions are dummies, since we don't call map() */
|
||||
void getKey(int /*i*/, uint8_t **/*keys*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void dispKey(int /*i*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* Search the source array between limits iMin and iMax for the pattern (length
|
||||
iPatLen). The pattern can contain wild bytes; if you really want to match
|
||||
for the pattern that is used up by the WILD uint8_t, tough - it will match with
|
||||
everything else as well. */
|
||||
static bool locatePattern(const uint8_t *source, int iMin, int iMax, uint8_t *pattern, int iPatLen,
|
||||
int *index)
|
||||
static bool locatePattern(const uint8_t *source, int iMin, int iMax, uint8_t *pattern, int iPatLen, int *index)
|
||||
{
|
||||
int i, j;
|
||||
const uint8_t *pSrc; /* Pointer to start of considered source */
|
||||
@ -633,26 +457,25 @@ static bool locatePattern(const uint8_t *source, int iMin, int iMax, uint8_t *pa
|
||||
}
|
||||
|
||||
|
||||
void STATE::checkStartup()
|
||||
/**
|
||||
* This function checks the startup code for various compilers' way of
|
||||
* loading DS. If found, it sets DS. This may not be needed in the future if
|
||||
* pushing and popping of registers is implemented.
|
||||
* Also sets prog.offMain and prog.segMain if possible
|
||||
*/
|
||||
void checkStartup(STATE &state)
|
||||
{
|
||||
Project & proj(*Project::get());
|
||||
PROG & prog(Project::get()->prog);
|
||||
/* This function checks the startup code for various compilers' way of
|
||||
loading DS. If found, it sets DS. This may not be needed in the future if
|
||||
pushing and popping of registers is implemented.
|
||||
Also sets prog.offMain and prog.segMain if possible */
|
||||
|
||||
|
||||
int startOff; /* Offset into the Image of the initial CS:IP */
|
||||
int i, rel, para, init;
|
||||
char chModel = 'x';
|
||||
char chVendor = 'x';
|
||||
char chVersion = 'x';
|
||||
char temp[4];
|
||||
|
||||
startOff = ((uint32_t)prog.initCS << 4) + prog.initIP;
|
||||
|
||||
/* Check the Turbo Pascal signatures first, since they involve only the
|
||||
first 3 bytes, and false positives may be founf with the others later */
|
||||
first 3 bytes, and false positives may be found with the others later */
|
||||
if (locatePattern(prog.image(), startOff, startOff+5, pattBorl4on,sizeof(pattBorl4on), &i))
|
||||
{
|
||||
/* The first 5 bytes are a far call. Follow that call and
|
||||
@ -660,49 +483,41 @@ void STATE::checkStartup()
|
||||
rel = LH(&prog.image()[startOff+1]); /* This is abs off of init */
|
||||
para= LH(&prog.image()[startOff+3]);/* This is abs seg of init */
|
||||
init = ((uint32_t)para << 4) + rel;
|
||||
if (locatePattern(prog.image(), init, init+26, pattBorl4Init,
|
||||
sizeof(pattBorl4Init), &i))
|
||||
if (locatePattern(prog.image(), init, init+26, pattBorl4Init, sizeof(pattBorl4Init), &i))
|
||||
{
|
||||
|
||||
setState(rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland Pascal v4 detected\n");
|
||||
chVendor = 't'; /* Trubo */
|
||||
chModel = 'p'; /* Pascal */
|
||||
chVersion = '4'; /* Version 4 */
|
||||
state.setState(rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland Turbo Pascal v4 detected\n");
|
||||
proj.setLoaderMetadata({eBorland,ePascal,eUnknownMemoryModel,4});
|
||||
prog.offMain = startOff; /* Code starts immediately */
|
||||
prog.segMain = prog.initCS; /* At the 5 uint8_t jump */
|
||||
goto gotVendor; /* Already have vendor */
|
||||
return; /* Already have vendor */
|
||||
}
|
||||
else if (locatePattern(prog.image(), init, init+26, pattBorl5Init,
|
||||
sizeof(pattBorl5Init), &i))
|
||||
else if (locatePattern(prog.image(), init, init+26, pattBorl5Init, sizeof(pattBorl5Init), &i))
|
||||
{
|
||||
|
||||
setState( rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland Pascal v5.0 detected\n");
|
||||
chVendor = 't'; /* Trubo */
|
||||
chModel = 'p'; /* Pascal */
|
||||
chVersion = '5'; /* Version 5 */
|
||||
state.setState( rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland Turbo Pascal v5.0 detected\n");
|
||||
proj.setLoaderMetadata({eBorland,ePascal,eUnknownMemoryModel,5});
|
||||
prog.offMain = startOff; /* Code starts immediately */
|
||||
prog.segMain = prog.initCS;
|
||||
goto gotVendor; /* Already have vendor */
|
||||
return; /* Already have vendor */
|
||||
}
|
||||
else if (locatePattern(prog.image(), init, init+26, pattBorl7Init,
|
||||
sizeof(pattBorl7Init), &i))
|
||||
{
|
||||
|
||||
setState( rDS, LH(&prog.image()[i+1]));
|
||||
state.setState( rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland Pascal v7 detected\n");
|
||||
chVendor = 't'; /* Trubo */
|
||||
chModel = 'p'; /* Pascal */
|
||||
chVersion = '7'; /* Version 7 */
|
||||
proj.setLoaderMetadata({eBorland,ePascal,eUnknownMemoryModel,7});
|
||||
prog.offMain = startOff; /* Code starts immediately */
|
||||
prog.segMain = prog.initCS;
|
||||
goto gotVendor; /* Already have vendor */
|
||||
return; /* Already have vendor */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
LoaderMetadata metadata;
|
||||
/* Search for the call to main pattern. This is compiler independant,
|
||||
but decides the model required. Note: must do the far data models
|
||||
(large and compact) before the others, since they are the same pattern
|
||||
@ -716,7 +531,7 @@ void STATE::checkStartup()
|
||||
/* Save absolute image offset */
|
||||
prog.offMain = ((uint32_t)para << 4) + rel;
|
||||
prog.segMain = (uint16_t)para;
|
||||
chModel = 'l'; /* Large model */
|
||||
metadata.compiler_memory_model = eLarge;
|
||||
}
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x180, pattMainCompact,
|
||||
sizeof(pattMainCompact), &i))
|
||||
@ -724,7 +539,7 @@ void STATE::checkStartup()
|
||||
rel = LH_SIGNED(&prog.image()[i+OFFMAINCOMPACT]);/* This is the rel addr of main */
|
||||
prog.offMain = i+OFFMAINCOMPACT+2+rel; /* Save absolute image offset */
|
||||
prog.segMain = prog.initCS;
|
||||
chModel = 'c'; /* Compact model */
|
||||
metadata.compiler_memory_model = eCompact;
|
||||
}
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x180, pattMainMedium,
|
||||
sizeof(pattMainMedium), &i))
|
||||
@ -733,7 +548,7 @@ void STATE::checkStartup()
|
||||
para= LH(&prog.image()[i+OFFMAINMEDIUM+2]);/* This is abs seg of main */
|
||||
prog.offMain = ((uint32_t)para << 4) + rel;
|
||||
prog.segMain = (uint16_t)para;
|
||||
chModel = 'm'; /* Medium model */
|
||||
metadata.compiler_memory_model = eMedium;
|
||||
}
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x180, pattMainSmall,
|
||||
sizeof(pattMainSmall), &i))
|
||||
@ -741,7 +556,7 @@ void STATE::checkStartup()
|
||||
rel = LH_SIGNED(&prog.image()[i+OFFMAINSMALL]); /* This is rel addr of main */
|
||||
prog.offMain = i+OFFMAINSMALL+2+rel; /* Save absolute image offset */
|
||||
prog.segMain = prog.initCS;
|
||||
chModel = 's'; /* Small model */
|
||||
metadata.compiler_memory_model = eSmall;
|
||||
}
|
||||
else if (memcmp(&prog.image()[startOff], pattTPasStart, sizeof(pattTPasStart)) == 0)
|
||||
{
|
||||
@ -749,12 +564,10 @@ void STATE::checkStartup()
|
||||
prog.offMain = rel+startOff+3; /* Save absolute image offset */
|
||||
prog.offMain += 0x20; /* These first 32 bytes are setting up */
|
||||
prog.segMain = prog.initCS;
|
||||
chVendor = 't'; /* Turbo.. */
|
||||
chModel = 'p'; /* ...Pascal... (only 1 model) */
|
||||
chVersion = '3'; /* 3.0 */
|
||||
proj.setLoaderMetadata({eBorland,ePascal,eUnknownMemoryModel,3});
|
||||
printf("Turbo Pascal 3.0 detected\n");
|
||||
printf("Main at %04X\n", prog.offMain);
|
||||
goto gotVendor; /* Already have vendor */
|
||||
return; /* Already have vendor */
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -767,28 +580,28 @@ void STATE::checkStartup()
|
||||
printf("Main could not be located!\n");
|
||||
prog.offMain = -1;
|
||||
}
|
||||
|
||||
printf("Model: %c\n", chModel);
|
||||
prog.addressingMode = chModel;
|
||||
//printf("Model: %c\n", chModel);
|
||||
|
||||
/* Now decide the compiler vendor and version number */
|
||||
if (memcmp(&prog.image()[startOff], pattMsC5Start, sizeof(pattMsC5Start)) == 0)
|
||||
{
|
||||
/* Yes, this is Microsoft startup code. The DS is sitting right here
|
||||
in the next 2 bytes */
|
||||
setState( rDS, LH(&prog.image()[startOff+sizeof(pattMsC5Start)]));
|
||||
chVendor = 'm'; /* Microsoft compiler */
|
||||
chVersion = '5'; /* Version 5 */
|
||||
state.setState( rDS, LH(&prog.image()[startOff+sizeof(pattMsC5Start)]));
|
||||
metadata.compiler_vendor = eMicrosoft;
|
||||
metadata.compiler_language = eAnsiCorCPP;
|
||||
metadata.compiler_version = 5;
|
||||
printf("MSC 5 detected\n");
|
||||
}
|
||||
|
||||
/* The C8 startup pattern is different from C5's */
|
||||
else if (memcmp(&prog.image()[startOff], pattMsC8Start, sizeof(pattMsC8Start)) == 0)
|
||||
{
|
||||
setState( rDS, LH(&prog.image()[startOff+sizeof(pattMsC8Start)]));
|
||||
state.setState( rDS, LH(&prog.image()[startOff+sizeof(pattMsC8Start)]));
|
||||
printf("MSC 8 detected\n");
|
||||
chVendor = 'm'; /* Microsoft compiler */
|
||||
chVersion = '8'; /* Version 8 */
|
||||
metadata.compiler_vendor = eMicrosoft;
|
||||
metadata.compiler_language = eAnsiCorCPP;
|
||||
metadata.compiler_version = 8;
|
||||
}
|
||||
|
||||
/* The C8 .com startup pattern is different again! */
|
||||
@ -796,37 +609,35 @@ void STATE::checkStartup()
|
||||
sizeof(pattMsC8ComStart)) == 0)
|
||||
{
|
||||
printf("MSC 8 .com detected\n");
|
||||
chVendor = 'm'; /* Microsoft compiler */
|
||||
chVersion = '8'; /* Version 8 */
|
||||
metadata.compiler_vendor = eMicrosoft;
|
||||
metadata.compiler_language = eAnsiCorCPP;
|
||||
metadata.compiler_version = 8;
|
||||
}
|
||||
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattBorl2Start,
|
||||
sizeof(pattBorl2Start), &i))
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattBorl2Start, sizeof(pattBorl2Start), &i))
|
||||
{
|
||||
/* Borland startup. DS is at the second uint8_t (offset 1) */
|
||||
setState( rDS, LH(&prog.image()[i+1]));
|
||||
state.setState( rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland v2 detected\n");
|
||||
chVendor = 'b'; /* Borland compiler */
|
||||
chVersion = '2'; /* Version 2 */
|
||||
metadata.compiler_vendor = eBorland;
|
||||
metadata.compiler_language = eAnsiCorCPP;
|
||||
metadata.compiler_version = 2;
|
||||
}
|
||||
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattBorl3Start,
|
||||
sizeof(pattBorl3Start), &i))
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattBorl3Start, sizeof(pattBorl3Start), &i))
|
||||
{
|
||||
/* Borland startup. DS is at the second uint8_t (offset 1) */
|
||||
setState( rDS, LH(&prog.image()[i+1]));
|
||||
state.setState( rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland v3 detected\n");
|
||||
chVendor = 'b'; /* Borland compiler */
|
||||
chVersion = '3'; /* Version 3 */
|
||||
metadata.compiler_vendor = eBorland;
|
||||
metadata.compiler_language = eAnsiCorCPP;
|
||||
metadata.compiler_version = 3;
|
||||
}
|
||||
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattLogiStart,
|
||||
sizeof(pattLogiStart), &i))
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattLogiStart, sizeof(pattLogiStart), &i))
|
||||
{
|
||||
/* Logitech modula startup. DS is 0, despite appearances */
|
||||
printf("Logitech modula detected\n");
|
||||
chVendor = 'l'; /* Logitech compiler */
|
||||
chVersion = '1'; /* Version 1 */
|
||||
metadata.compiler_vendor = eLogitech;
|
||||
metadata.compiler_language = eModula2;
|
||||
metadata.compiler_version = 1;
|
||||
}
|
||||
|
||||
/* Other startup idioms would go here */
|
||||
@ -834,16 +645,7 @@ void STATE::checkStartup()
|
||||
{
|
||||
printf("Warning - compiler not recognised\n");
|
||||
}
|
||||
|
||||
gotVendor:
|
||||
|
||||
sSigName = QString("dcc%1%2%3.sig")
|
||||
.arg(QChar(chVendor)) /* Add vendor */
|
||||
.arg(QChar(chVersion)) /* Add version */
|
||||
.arg(QChar(chModel)) /* Add model */
|
||||
;
|
||||
printf("Signature file: %s\n", qPrintable(sSigName));
|
||||
|
||||
proj.setLoaderMetadata(metadata);
|
||||
}
|
||||
|
||||
/* DCCLIBS.DAT is a data file sorted on function name containing names and
|
||||
@ -853,32 +655,31 @@ gotVendor:
|
||||
by dcc, rather than considered as known functions. When a prototype is
|
||||
found (in searchPList()), the parameter info is written to the proc struct.
|
||||
*/
|
||||
void readProtoFile(void)
|
||||
bool PatternLocator::readProtoFile(void)
|
||||
{
|
||||
IDcc *dcc = IDcc::get();
|
||||
QString szProFName = dcc->dataDir("prototypes").absoluteFilePath(DCCLIBS); /* Full name of dclibs.lst */
|
||||
|
||||
FILE *fProto;
|
||||
int i;
|
||||
QFile fProto(szProFName);
|
||||
|
||||
if ((fProto = fopen(qPrintable(szProFName), "rb")) == nullptr)
|
||||
if (not fProto.open(QFile::ReadOnly))
|
||||
{
|
||||
printf("Warning: cannot open library prototype data file %s\n", qPrintable(szProFName));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
grab(4, fProto);
|
||||
if (strncmp(buf, "dccp", 4) != 0)
|
||||
{
|
||||
printf("%s is not a dcc prototype file\n", qPrintable(szProFName));
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
grab(2, fProto);
|
||||
if (strncmp(buf, "FN", 2) != 0)
|
||||
{
|
||||
printf("FN (Function Name) subsection expected in %s\n", qPrintable(szProFName));
|
||||
exit(2);
|
||||
return false;
|
||||
}
|
||||
|
||||
numFunc = readFileShort(fProto); /* Num of entries to allocate */
|
||||
@ -886,51 +687,48 @@ void readProtoFile(void)
|
||||
/* Allocate exactly correct # entries */
|
||||
pFunc = new PH_FUNC_STRUCT[numFunc];
|
||||
|
||||
for (i=0; i < numFunc; i++)
|
||||
for (int i=0; i < numFunc; i++)
|
||||
{
|
||||
size_t read_size=fread(&pFunc[i], 1, SYMLEN, fProto);
|
||||
size_t read_size=fProto.read((char *)&pFunc[i], SYMLEN);
|
||||
assert(read_size==SYMLEN);
|
||||
if(read_size!=SYMLEN)
|
||||
break;
|
||||
pFunc[i].typ = (hlType)readFileShort(fProto);
|
||||
pFunc[i].numArg = readFileShort(fProto);
|
||||
pFunc[i].firstArg = readFileShort(fProto);
|
||||
if(feof(fProto))
|
||||
if(fProto.atEnd())
|
||||
break;
|
||||
int c = fgetc(fProto);
|
||||
pFunc[i].bVararg = (c!=0); //fread(&pFunc[i].bVararg, 1, 1, fProto);
|
||||
char isvararg;
|
||||
fProto.read(&isvararg,1);
|
||||
pFunc[i].bVararg = (isvararg!=0);
|
||||
}
|
||||
|
||||
grab(2, fProto);
|
||||
if (strncmp(buf, "PM", 2) != 0)
|
||||
{
|
||||
printf("PM (Parameter) subsection expected in %s\n", qPrintable(szProFName));
|
||||
exit(2);
|
||||
return false;
|
||||
}
|
||||
|
||||
numArg = readFileShort(fProto); /* Num of entries to allocate */
|
||||
|
||||
/* Allocate exactly correct # entries */
|
||||
delete [] pArg;
|
||||
pArg = new hlType[numArg];
|
||||
pArg.clear();
|
||||
pArg.reserve(numArg);
|
||||
|
||||
for (i=0; i < numArg; i++)
|
||||
for (int i=0; i < numArg; i++)
|
||||
{
|
||||
// fread(&pArg[i], 1, SYMLEN, fProto); /* No names to read as yet */
|
||||
pArg[i] = (hlType) readFileShort(fProto);
|
||||
pArg.push_back((hlType) readFileShort(fProto));
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fProto);
|
||||
|
||||
}
|
||||
|
||||
int searchPList(char *name)
|
||||
int PatternLocator::searchPList(const char *name)
|
||||
{
|
||||
/* Search through the symbol names for the name */
|
||||
/* Use binary search */
|
||||
int mx, mn, i, res;
|
||||
|
||||
|
||||
mx = numFunc;
|
||||
mn = 0;
|
||||
|
||||
@ -939,29 +737,173 @@ int searchPList(char *name)
|
||||
i = (mn + mx) /2;
|
||||
res = strcmp(pFunc[i].name, name);
|
||||
if (res == 0)
|
||||
{
|
||||
return i; /* Found! */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
mn = i+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mx = i-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Still could be the case that mn == mx == required record */
|
||||
res = strcmp(pFunc[mn].name, name);
|
||||
if (res == 0)
|
||||
{
|
||||
return mn; /* Found! */
|
||||
}
|
||||
|
||||
return NIL;
|
||||
}
|
||||
/* This procedure is called to initialise the library check code */
|
||||
bool PatternLocator::load()
|
||||
{
|
||||
uint16_t w, len;
|
||||
int i;
|
||||
IDcc *dcc = IDcc::get();
|
||||
QString fpath = dcc->dataDir("sigs").absoluteFilePath(pattern_id);
|
||||
QFile g_file(fpath);
|
||||
if (not g_file.open(QFile::ReadOnly))
|
||||
{
|
||||
printf("Warning: cannot open signature file %s\n", qPrintable(fpath));
|
||||
return false;
|
||||
}
|
||||
|
||||
readProtoFile();
|
||||
|
||||
|
||||
/* Read the parameters */
|
||||
grab(4, g_file);
|
||||
if (memcmp("dccs", buf, 4) != 0)
|
||||
{
|
||||
printf("Not a dcc signature file!\n");
|
||||
return false;
|
||||
}
|
||||
numKeys = readFileShort(g_file);
|
||||
numVert = readFileShort(g_file);
|
||||
PatLen = readFileShort(g_file);
|
||||
SymLen = readFileShort(g_file);
|
||||
if ((PatLen != PATLEN) or (SymLen != SYMLEN))
|
||||
{
|
||||
printf("Sorry! Compiled for sym and pattern lengths of %d and %d\n", SYMLEN, PATLEN);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialise the perfhlib stuff. Also allocates T1, T2, g, etc */
|
||||
/* Set the parameters for the hash table */
|
||||
g_pattern_hasher.setHashParams(
|
||||
numKeys, /* The number of symbols */
|
||||
PatLen, /* The length of the pattern to be hashed */
|
||||
256, /* The character set of the pattern (0-FF) */
|
||||
0, /* Minimum pattern character value */
|
||||
numVert); /* Specifies c, the sparseness of the graph. See Czech, Havas and Majewski for details */
|
||||
T1base = g_pattern_hasher.readT1();
|
||||
T2base = g_pattern_hasher.readT2();
|
||||
g = g_pattern_hasher.readG();
|
||||
|
||||
/* Read T1 and T2 tables */
|
||||
grab(2, g_file);
|
||||
if (memcmp("T1", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'T1'\n");
|
||||
exit(3);
|
||||
}
|
||||
len = (uint16_t) (PatLen * 256 * sizeof(uint16_t));
|
||||
w = readFileShort(g_file);
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of T1: file %d, calc %d\n", w, len);
|
||||
return false;
|
||||
}
|
||||
readFileSection(T1base, len, g_file);
|
||||
|
||||
grab(2, g_file);
|
||||
if (memcmp("T2", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'T2'\n");
|
||||
return false;
|
||||
}
|
||||
w = readFileShort(g_file);
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of T2: file %d, calc %d\n", w, len);
|
||||
return false;
|
||||
}
|
||||
readFileSection(T2base, len, g_file);
|
||||
|
||||
/* Now read the function g[] */
|
||||
grab(2, g_file);
|
||||
if (memcmp("gg", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'gg'\n");
|
||||
return false;
|
||||
}
|
||||
len = (uint16_t)(numVert * sizeof(uint16_t));
|
||||
w = readFileShort(g_file);
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of g[]: file %d, calc %d\n", w, len);
|
||||
return false;
|
||||
}
|
||||
readFileSection(g, len, g_file);
|
||||
|
||||
|
||||
/* This is now the hash table */
|
||||
/* First allocate space for the table */
|
||||
ht = new HT[numKeys];
|
||||
if ( nullptr == ht)
|
||||
{
|
||||
printf("Could not allocate hash table\n");
|
||||
return false;
|
||||
}
|
||||
grab(2, g_file);
|
||||
if (memcmp("ht", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'ht'\n");
|
||||
return false;
|
||||
}
|
||||
w = readFileShort(g_file);
|
||||
if (w != numKeys * (SymLen + PatLen + sizeof(uint16_t)))
|
||||
{
|
||||
printf("Problem with size of hash table: file %d, calc %d\n", w, len);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
for (i=0; i < numKeys; i++)
|
||||
{
|
||||
if (g_file.read((char *)&ht[i], SymLen + PatLen) != SymLen + PatLen)
|
||||
{
|
||||
printf("Could not read signature\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
PatternLocator::~PatternLocator()
|
||||
{
|
||||
/* Deallocate all the stuff allocated in SetupLibCheck() */
|
||||
delete [] ht;
|
||||
delete [] pFunc;
|
||||
delete [] T1base;
|
||||
delete [] T2base;
|
||||
delete [] g;
|
||||
}
|
||||
|
||||
bool LoadPatternLibrary::execute(CommandContext * ctx)
|
||||
{
|
||||
if(nullptr==ctx->m_project) {
|
||||
ctx->recordFailure(this,"Project was not created yet.");
|
||||
return false;
|
||||
}
|
||||
Project & project( *ctx->m_project) ;
|
||||
if(!project.m_metadata_available) {
|
||||
ctx->recordFailure(this,"Loader metadata was not set. FindMain command should be run before LoadPatternLibrary");
|
||||
return false;
|
||||
}
|
||||
PatternLocator *loc = new PatternLocator(project.getLoaderMetadata().compilerId());
|
||||
if(!loc->load()) {
|
||||
qDebug()<< " No library patterns found for" << project.getLoaderMetadata().compilerId();
|
||||
delete loc;
|
||||
return true; // not an error, just no pattern locator available
|
||||
}
|
||||
project.m_pattern_locator = loc;
|
||||
return true;
|
||||
}
|
||||
|
||||
49
src/chklib.h
Normal file
49
src/chklib.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef CHKLIB_H
|
||||
#define CHKLIB_H
|
||||
|
||||
#include "Command.h"
|
||||
#include "Enums.h"
|
||||
#include "perfhlib.h"
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QString>
|
||||
#include <vector>
|
||||
|
||||
struct Function;
|
||||
|
||||
// This will create a PatternLocator instance load it and pass it to project instance.
|
||||
struct LoadPatternLibrary : public Command {
|
||||
LoadPatternLibrary() : Command("Load patterns for the file",eProject) {}
|
||||
bool execute(CommandContext *ctx) override;
|
||||
};
|
||||
|
||||
class PatternLocator {
|
||||
std::vector<hlType> pArg; /* Points to the array of param types */
|
||||
QString pattern_id;
|
||||
int numFunc; /* Number of func names actually stored */
|
||||
int numArg; /* Number of param names actually stored */
|
||||
public:
|
||||
struct HT *ht; //!< The hash table
|
||||
struct PH_FUNC_STRUCT *pFunc; //!< Points to the array of func names
|
||||
|
||||
|
||||
PatternLocator(QString name) : pattern_id(name) {}
|
||||
~PatternLocator();
|
||||
|
||||
bool load();
|
||||
int searchPList(const char * name);
|
||||
|
||||
bool LibCheck(Function & pProc);
|
||||
private:
|
||||
bool readProtoFile();
|
||||
PerfectHash g_pattern_hasher;
|
||||
int numKeys; /* Number of hash table entries (keys) */
|
||||
int numVert; /* Number of vertices in the graph (also size of g[]) */
|
||||
unsigned PatLen; /* Size of the keys (pattern length) */
|
||||
unsigned SymLen; /* Max size of the symbols, including null */
|
||||
uint16_t * T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
uint16_t * g; /* g[] */
|
||||
|
||||
};
|
||||
extern void checkStartup(struct STATE &state);
|
||||
#endif // CHKLIB_H
|
||||
@ -671,9 +671,7 @@ int C_CallingConvention::processCArg (Function * callee, Function * pProc, ICODE
|
||||
Expr *_exp;
|
||||
bool res;
|
||||
int size_of_arg=0;
|
||||
PROG &prog(Project::get()->prog);
|
||||
|
||||
|
||||
Project &proj(*Project::get());
|
||||
/* if (numArgs == 0)
|
||||
return; */
|
||||
assert(pProc==g_exp_stk.func);
|
||||
@ -693,7 +691,7 @@ int C_CallingConvention::processCArg (Function * callee, Function * pProc, ICODE
|
||||
}
|
||||
else {
|
||||
if(numArgs<callee->args.size()) {
|
||||
if(prog.addressingMode=='l') {
|
||||
if(proj.getLoaderMetadata().compiler_memory_model==eLarge) {
|
||||
if((callee->args[numArgs].type==TYPE_STR) or (callee->args[numArgs].type==TYPE_PTR)) {
|
||||
RegisterNode *rn = dynamic_cast<RegisterNode *>(g_exp_stk.top());
|
||||
AstIdent *idn = dynamic_cast<AstIdent *>(g_exp_stk.top());
|
||||
|
||||
103
src/dcc.cpp
103
src/dcc.cpp
@ -14,26 +14,10 @@
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QCommandLineParser>
|
||||
|
||||
#ifdef LLVM_EXPERIMENTAL
|
||||
#include <llvm/Support/raw_os_ostream.h>
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
#include <llvm/Support/TargetSelect.h>
|
||||
#include <llvm/Support/TargetRegistry.h>
|
||||
#include <llvm/Support/PrettyStackTrace.h>
|
||||
#include <llvm/Support/Signals.h>
|
||||
#include <llvm/Support/Host.h>
|
||||
#include <llvm/Target/TargetMachine.h>
|
||||
#include <llvm/Target/TargetInstrInfo.h>
|
||||
#include <llvm/MC/MCAsmInfo.h>
|
||||
#include <llvm/CodeGen/MachineInstrBuilder.h>
|
||||
#include <llvm/TableGen/Main.h>
|
||||
#include <llvm/TableGen/TableGenBackend.h>
|
||||
#include <llvm/TableGen/Record.h>
|
||||
#endif
|
||||
#include <QtCore/QFile>
|
||||
|
||||
#include "ui/DccMainWindow.h"
|
||||
|
||||
/* Global variables - extern to other modules */
|
||||
extern QString asm1_name, asm2_name; /* Assembler output filenames */
|
||||
@ -46,79 +30,6 @@ static void displayTotalStats(void);
|
||||
/****************************************************************************
|
||||
* main
|
||||
***************************************************************************/
|
||||
#ifdef LLVM_EXPERIMENTAL
|
||||
using namespace llvm;
|
||||
bool TVisitor(raw_ostream &OS, RecordKeeper &Records)
|
||||
{
|
||||
Record *rec = Records.getDef("ADD8i8");
|
||||
if(rec)
|
||||
{
|
||||
if(not rec->getTemplateArgs().empty())
|
||||
std::cout << "Has template args\n";
|
||||
auto classes(rec->getSuperClasses());
|
||||
for(auto val : rec->getSuperClasses())
|
||||
std::cout << "Super "<<val->getName()<<"\n";
|
||||
|
||||
// DagInit * in = rec->getValueAsDag(val.getName());
|
||||
// in->dump();
|
||||
for(const RecordVal &val : rec->getValues())
|
||||
{
|
||||
// val.dump();
|
||||
}
|
||||
rec->dump();
|
||||
|
||||
}
|
||||
// rec = Records.getDef("CCR");
|
||||
// if(rec)
|
||||
// rec->dump();
|
||||
// for(auto val : Records.getDefs())
|
||||
// {
|
||||
// //std::cout<< "Def "<<val.first<<"\n";
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
int testTblGen(int argc, char **argv)
|
||||
{
|
||||
// using namespace llvm;
|
||||
// sys::PrintStackTraceOnErrorSignal();
|
||||
// PrettyStackTraceProgram(argc,argv);
|
||||
// cl::ParseCommandLineOptions(argc,argv);
|
||||
// return llvm::TableGenMain(argv[0],TVisitor);
|
||||
// InitializeNativeTarget();
|
||||
// Triple TheTriple;
|
||||
// std::string def = sys::getDefaultTargetTriple();
|
||||
// std::string MCPU="i386";
|
||||
// std::string MARCH="x86";
|
||||
// InitializeAllTargetInfos();
|
||||
// InitializeAllTargetMCs();
|
||||
// InitializeAllAsmPrinters();
|
||||
// InitializeAllAsmParsers();
|
||||
// InitializeAllDisassemblers();
|
||||
// std::string TargetTriple("i386-pc-linux-gnu");
|
||||
// TheTriple = Triple(Triple::normalize(TargetTriple));
|
||||
// MCOperand op=llvm::MCOperand::CreateImm(11);
|
||||
// MCAsmInfo info;
|
||||
// raw_os_ostream wrap(std::cerr);
|
||||
// op.print(wrap,&info);
|
||||
// wrap.flush();
|
||||
// std::cerr<<"\n";
|
||||
// std::string lookuperr;
|
||||
// TargetRegistry::printRegisteredTargetsForVersion();
|
||||
// const Target *t = TargetRegistry::lookupTarget(MARCH,TheTriple,lookuperr);
|
||||
// TargetOptions opts;
|
||||
// std::string Features;
|
||||
// opts.PrintMachineCode=1;
|
||||
// TargetMachine *tm = t->createTargetMachine(TheTriple.getTriple(),MCPU,Features,opts);
|
||||
// std::cerr<<tm->getInstrInfo()->getName(97)<<"\n";
|
||||
// const MCInstrDesc &ds(tm->getInstrInfo()->get(97));
|
||||
// const MCOperandInfo *op1=ds.OpInfo;
|
||||
// uint16_t impl_def = ds.getImplicitDefs()[0];
|
||||
// std::cerr<<lookuperr<<"\n";
|
||||
|
||||
// exit(0);
|
||||
|
||||
}
|
||||
#endif
|
||||
void setupOptions(QCoreApplication &app) {
|
||||
//[-a1a2cmsi]
|
||||
QCommandLineParser parser;
|
||||
@ -180,9 +91,17 @@ void setupOptions(QCoreApplication &app) {
|
||||
}
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCoreApplication::setApplicationName("dcc");
|
||||
QCoreApplication::setApplicationVersion("0.1");
|
||||
if(argc==1) {
|
||||
QApplication app(argc,argv);
|
||||
DccMainWindow win;
|
||||
win.show();
|
||||
return app.exec();
|
||||
|
||||
}
|
||||
QCoreApplication app(argc,argv);
|
||||
|
||||
QCoreApplication::setApplicationVersion("0.1");
|
||||
setupOptions(app);
|
||||
|
||||
Project *proj = Project::get();
|
||||
|
||||
@ -16,23 +16,43 @@ public:
|
||||
{
|
||||
return Project::get()->functions().begin();
|
||||
}
|
||||
ilFunction GetNextFuncHandle(ilFunction iter)
|
||||
{
|
||||
if(iter!=Project::get()->functions().end())
|
||||
++iter;
|
||||
return iter;
|
||||
}
|
||||
ilFunction GetCurFuncHandle()
|
||||
{
|
||||
return m_current_func;
|
||||
}
|
||||
void analysis_Once()
|
||||
{
|
||||
if(m_current_func==Project::get()->functions().end())
|
||||
return;
|
||||
if(m_current_func->nStep==0) { // unscanned function
|
||||
}
|
||||
void load(QString name)
|
||||
}
|
||||
bool load(QString name)
|
||||
{
|
||||
option.filename = name;
|
||||
Project::get()->create(name);
|
||||
return Project::get()->addLoadCommands(name);
|
||||
}
|
||||
void prtout_asm(IXmlTarget *, int level)
|
||||
void prtout_asm(IStructuredTextTarget *, int level)
|
||||
{
|
||||
// if (m_Cur_Func->m_nStep == 0)
|
||||
// return;
|
||||
|
||||
// XmlOutPro out(iOut);
|
||||
// FuncLL the(m_Cur_Func->ll.m_asmlist);
|
||||
// the.prtout_asm(m_Cur_Func, &m_Cur_Func->m_varll, &out);
|
||||
}
|
||||
void prtout_cpp(IStructuredTextTarget *, int level)
|
||||
{
|
||||
}
|
||||
void prtout_cpp(IXmlTarget *, int level)
|
||||
{
|
||||
bool isValidFuncHandle(ilFunction f) {
|
||||
return f != Project::get()->functions().end();
|
||||
}
|
||||
size_t getFuncCount()
|
||||
{
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "project.h"
|
||||
#include "CallGraph.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "chklib.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
@ -673,6 +674,7 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
||||
|
||||
bool Function::process_CALL(ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *pstate)
|
||||
{
|
||||
Project &project(*Project::get());
|
||||
PROG &prog(Project::get()->prog);
|
||||
ICODE &last_insn(Icode.back());
|
||||
STATE localState; /* Local copy of the machine state */
|
||||
@ -742,7 +744,8 @@ bool Function::process_CALL(ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *psta
|
||||
{
|
||||
iter = Project::get()->createFunction(0,"",{0,pIcode.ll()->src().getImm2()});
|
||||
Function &x(*iter);
|
||||
LibCheck(x);
|
||||
if(project.m_pattern_locator)
|
||||
project.m_pattern_locator->LibCheck(x);
|
||||
|
||||
if (x.flg & PROC_ISLIB)
|
||||
{
|
||||
|
||||
@ -15,7 +15,10 @@ STATS stats; /* cfg statistics */
|
||||
//PROG prog; /* programs fields */
|
||||
OPTION option; /* Command line options */
|
||||
Project *Project::s_instance = nullptr;
|
||||
Project::Project() : callGraph(nullptr)
|
||||
Project::Project() :
|
||||
m_selected_loader(nullptr),
|
||||
callGraph(nullptr),
|
||||
m_pattern_locator(nullptr)
|
||||
{
|
||||
m_project_command_stream.setMaximumCommandCount(10);
|
||||
connect(&m_project_command_stream,SIGNAL(streamCompleted(bool)),SLOT(onCommandStreamFinished(bool)));
|
||||
@ -29,6 +32,7 @@ void Project::initialize()
|
||||
}
|
||||
void Project::create(const QString &a)
|
||||
{
|
||||
// TODO: reset all state.
|
||||
initialize();
|
||||
QFileInfo fi(a);
|
||||
m_fname=a;
|
||||
@ -152,15 +156,23 @@ bool Project::addLoadCommands(QString fname)
|
||||
|
||||
void Project::processAllCommands()
|
||||
{
|
||||
m_command_ctx.proj = this;
|
||||
m_command_ctx.m_project = this;
|
||||
m_project_command_stream.processAll(&m_command_ctx);
|
||||
|
||||
emit commandListChanged();
|
||||
}
|
||||
void Project::processCommands(int count) {
|
||||
m_command_ctx.m_project = this;
|
||||
while(count--) {
|
||||
if(false==m_project_command_stream.processOne(&m_command_ctx)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
emit commandListChanged();
|
||||
}
|
||||
|
||||
void Project::resetCommandsAndErrorState()
|
||||
{
|
||||
m_error_state = false;
|
||||
m_command_ctx.reset();
|
||||
m_command_ctx.proj = this;
|
||||
m_command_ctx.m_project = this;
|
||||
m_project_command_stream.clear();
|
||||
}
|
||||
|
||||
39
src/ui/CommandQueueView.cpp
Normal file
39
src/ui/CommandQueueView.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "CommandQueueView.h"
|
||||
|
||||
#include "project.h"
|
||||
|
||||
#include "ui_CommandQueueView.h"
|
||||
|
||||
CommandQueueView::CommandQueueView(QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::CommandQueueView)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(Project::get(),SIGNAL(commandListChanged()),SLOT(onCommandListChanged()));
|
||||
}
|
||||
|
||||
CommandQueueView::~CommandQueueView()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CommandQueueView::changeEvent(QEvent *e)
|
||||
{
|
||||
QDockWidget::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CommandQueueView::onCommandListChanged() {
|
||||
Project &project(*Project::get());
|
||||
ui->lstQueuedCommands->clear();
|
||||
const CommandStream& cs(project.m_project_command_stream);
|
||||
for(const Command * cmd : cs.m_commands) {
|
||||
ui->lstQueuedCommands->addItem(cmd->name());
|
||||
}
|
||||
}
|
||||
28
src/ui/CommandQueueView.h
Normal file
28
src/ui/CommandQueueView.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef COMMANDQUEUEVIEW_H
|
||||
#define COMMANDQUEUEVIEW_H
|
||||
|
||||
#include <QtWidgets/QDockWidget>
|
||||
|
||||
namespace Ui {
|
||||
class CommandQueueView;
|
||||
}
|
||||
|
||||
class CommandQueueView : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CommandQueueView(QWidget *parent = 0);
|
||||
~CommandQueueView();
|
||||
|
||||
public slots:
|
||||
void onCommandListChanged();
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
|
||||
private:
|
||||
Ui::CommandQueueView *ui;
|
||||
};
|
||||
|
||||
#endif // COMMANDQUEUEVIEW_H
|
||||
33
src/ui/CommandQueueView.ui
Normal file
33
src/ui/CommandQueueView.ui
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CommandQueueView</class>
|
||||
<widget class="QDockWidget" name="CommandQueueView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>222</width>
|
||||
<height>446</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Doc&kWidget</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QListWidget" name="lstQueuedCommands"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Step</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
115
src/ui/DccMainWindow.cpp
Normal file
115
src/ui/DccMainWindow.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
#include "DccMainWindow.h"
|
||||
#include "ui_DccMainWindow.h"
|
||||
//#include "ui_exe2c_gui.h"
|
||||
//#include "exe2c_interface.h"
|
||||
//#include "exe2c.h"
|
||||
#include "FunctionViewWidget.h"
|
||||
#include "FunctionListDockWidget.h"
|
||||
#include "CommandQueueView.h"
|
||||
#include "dcc_interface.h"
|
||||
#include "project.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
#include <QLabel>
|
||||
#include <QFileDialog>
|
||||
IDcc* g_EXE2C = NULL;
|
||||
extern bool exe2c_Init();
|
||||
|
||||
DccMainWindow::DccMainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::DccMainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->statusbar->addPermanentWidget(new QLabel("Test"));
|
||||
|
||||
g_EXE2C = IDcc::get();
|
||||
g_EXE2C->BaseInit();
|
||||
g_EXE2C->Init(this);
|
||||
|
||||
m_last_display = g_EXE2C->GetFirstFuncHandle();
|
||||
m_command_queue = new CommandQueueView(this);
|
||||
m_functionlist_widget = new FunctionListDockWidget(this);
|
||||
m_functionlist_widget->setWindowTitle(QApplication::tr("Function list"));
|
||||
connect(m_functionlist_widget,SIGNAL(displayRequested()), SLOT(displayCurrentFunction()));
|
||||
// we are beeing signalled when display is requested
|
||||
connect(this,SIGNAL(functionListChanged()), m_functionlist_widget->model(),SLOT(updateFunctionList()));
|
||||
this->addDockWidget(Qt::RightDockWidgetArea,m_functionlist_widget);
|
||||
this->addDockWidget(Qt::LeftDockWidgetArea,m_command_queue);
|
||||
m_asm_view = new FunctionViewWidget(this);
|
||||
m_asm_view->setWindowTitle(tr("Assembly listing"));
|
||||
ui->mdiArea->addSubWindow(m_asm_view);
|
||||
//m_internal_view = new FunctionViewWidget;
|
||||
//m_internal_view->setWindowTitle(QApplication::tr("Internal listing"));
|
||||
//ui->mdiArea->addSubWindow(m_internal_view);
|
||||
m_c_view = new FunctionViewWidget;
|
||||
m_c_view->setWindowTitle(tr("Decompiled"));
|
||||
ui->mdiArea->addSubWindow(m_c_view);
|
||||
}
|
||||
|
||||
DccMainWindow::~DccMainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void DccMainWindow::changeEvent(QEvent *e)
|
||||
{
|
||||
QMainWindow::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void DccMainWindow::onOptim()
|
||||
{
|
||||
Project::get()->processCommands();
|
||||
g_EXE2C->analysis_Once();
|
||||
emit functionListChanged();
|
||||
if(m_last_display==g_EXE2C->GetCurFuncHandle())
|
||||
{
|
||||
displayCurrentFunction();
|
||||
}
|
||||
}
|
||||
void DccMainWindow::onOptim10()
|
||||
{
|
||||
for(int i=0; i<10; i++)
|
||||
g_EXE2C->analysis_Once();
|
||||
emit functionListChanged();
|
||||
if(m_last_display==g_EXE2C->GetCurFuncHandle())
|
||||
{
|
||||
displayCurrentFunction();
|
||||
}
|
||||
}
|
||||
void DccMainWindow::onOpenFile_Action()
|
||||
{
|
||||
QFileDialog dlg;
|
||||
QString name=dlg.getOpenFileName(0,
|
||||
tr("Select DOS executable"),
|
||||
".",
|
||||
tr("Executable files (*.exe *.EXE *.com *.COM)"));
|
||||
if(!g_EXE2C->load(name)) {
|
||||
QMessageBox::critical(this,tr("Error"),QString(tr("Cannot open file %1")).arg(name));
|
||||
}
|
||||
//bool m_bSucc = m_xTextBuffer.LoadFromFile(lpszPathName);
|
||||
emit functionListChanged();
|
||||
}
|
||||
|
||||
void DccMainWindow::displayCurrentFunction()
|
||||
{
|
||||
if(m_last_display!=g_EXE2C->GetCurFuncHandle())
|
||||
m_last_display=g_EXE2C->GetCurFuncHandle();
|
||||
g_EXE2C->prtout_asm(m_asm_view);
|
||||
//g_EXE2C->prtout_itn(m_internal_view);
|
||||
g_EXE2C->prtout_cpp(m_c_view);
|
||||
}
|
||||
void DccMainWindow::prt_log(const char *v)
|
||||
{
|
||||
qDebug()<<v;
|
||||
}
|
||||
|
||||
void DccMainWindow::on_actionExit_triggered()
|
||||
{
|
||||
qApp->exit(0);
|
||||
}
|
||||
49
src/ui/DccMainWindow.h
Normal file
49
src/ui/DccMainWindow.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef EXE2C_MAINWINDOW_H
|
||||
#define EXE2C_MAINWINDOW_H
|
||||
|
||||
#include "Procedure.h"
|
||||
#include "DccFrontend.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QAbstractTableModel>
|
||||
#include <QVariant>
|
||||
#include <vector>
|
||||
|
||||
class FunctionViewWidget;
|
||||
class FunctionListDockWidget;
|
||||
class CommandQueueView;
|
||||
|
||||
namespace Ui {
|
||||
class DccMainWindow;
|
||||
}
|
||||
|
||||
class DccMainWindow : public QMainWindow/*,public I_E2COUT*/ {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DccMainWindow(QWidget *parent = 0);
|
||||
~DccMainWindow();
|
||||
void prt_log(const char * str);
|
||||
public slots:
|
||||
void onOptim();
|
||||
void onOptim10();
|
||||
void onOpenFile_Action();
|
||||
void displayCurrentFunction();
|
||||
signals:
|
||||
void functionListChanged();
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
private slots:
|
||||
void on_actionExit_triggered();
|
||||
|
||||
private:
|
||||
|
||||
FunctionViewWidget *m_asm_view;
|
||||
// FunctionViewWidget *m_internal_view;
|
||||
FunctionViewWidget *m_c_view;
|
||||
CommandQueueView *m_command_queue;
|
||||
FunctionListDockWidget *m_functionlist_widget;
|
||||
Ui::DccMainWindow *ui;
|
||||
ilFunction m_last_display;
|
||||
};
|
||||
|
||||
#endif // EXE2C_MAINWINDOW_H
|
||||
372
src/ui/DccMainWindow.ui
Normal file
372
src/ui/DccMainWindow.ui
Normal file
@ -0,0 +1,372 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DccMainWindow</class>
|
||||
<widget class="QMainWindow" name="DccMainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<property name="documentMode">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QMdiArea" name="mdiArea"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionNew"/>
|
||||
<addaction name="actionOpen"/>
|
||||
<addaction name="actionSave"/>
|
||||
<addaction name="actionSave_as"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuUndo">
|
||||
<property name="title">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
<addaction name="actionUndo"/>
|
||||
<addaction name="actionRedo"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionCut"/>
|
||||
<addaction name="actionCopy"/>
|
||||
<addaction name="actionPaste"/>
|
||||
<addaction name="actionDelete"/>
|
||||
<addaction name="actionSelect_All"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionFind"/>
|
||||
<addaction name="actionFind_next"/>
|
||||
<addaction name="actionFind_Previous"/>
|
||||
<addaction name="actionReplace"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionRead_Only"/>
|
||||
<addaction name="separator"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
<string>View</string>
|
||||
</property>
|
||||
<addaction name="actionToolbar"/>
|
||||
<addaction name="actionStatus_Bar"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuWindow">
|
||||
<property name="title">
|
||||
<string>Window</string>
|
||||
</property>
|
||||
<addaction name="actionMdiCascadeWindows"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
<string>Help</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuUndo"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuWindow"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar</string>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="actionOptim"/>
|
||||
<addaction name="actionOptim10"/>
|
||||
</widget>
|
||||
<action name="actionNew">
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen">
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave_as">
|
||||
<property name="text">
|
||||
<string>Save as</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExit">
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionUndo">
|
||||
<property name="text">
|
||||
<string>Undo</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRedo">
|
||||
<property name="text">
|
||||
<string>Redo</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCut">
|
||||
<property name="text">
|
||||
<string>Cut</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCopy">
|
||||
<property name="text">
|
||||
<string>Copy</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPaste">
|
||||
<property name="text">
|
||||
<string>Paste</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDelete">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSelect_All">
|
||||
<property name="text">
|
||||
<string>Select All</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFind">
|
||||
<property name="text">
|
||||
<string>Find</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFind_next">
|
||||
<property name="text">
|
||||
<string>Find Next</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFind_Previous">
|
||||
<property name="text">
|
||||
<string>Find Previous</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionReplace">
|
||||
<property name="text">
|
||||
<string>Replace</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRead_Only">
|
||||
<property name="text">
|
||||
<string>Read Only</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOptim">
|
||||
<property name="text">
|
||||
<string>Optim</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Optimization step</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbar">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Toolbar</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Toggle toolbar visibility</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Alt+T</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStatus_Bar">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Status Bar</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Toggle status bar visibility</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMdiCascadeWindows">
|
||||
<property name="text">
|
||||
<string>Cascade windows</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Will re-arrange the mdi children windows</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMdiTileWindows">
|
||||
<property name="text">
|
||||
<string>Tile windows</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOptim10">
|
||||
<property name="text">
|
||||
<string>Optim10</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>actionStatus_Bar</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>statusbar</receiver>
|
||||
<slot>setVisible(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>588</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>actionToolbar</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>toolBar</receiver>
|
||||
<slot>setVisible(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>37</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>actionMdiCascadeWindows</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>mdiArea</receiver>
|
||||
<slot>cascadeSubWindows()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>347</x>
|
||||
<y>314</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>actionMdiTileWindows</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>mdiArea</receiver>
|
||||
<slot>tileSubWindows()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>347</x>
|
||||
<y>314</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>actionOptim</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>DccMainWindow</receiver>
|
||||
<slot>onOptim()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>299</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>actionNew</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>DccMainWindow</receiver>
|
||||
<slot>onOpenFile_Action()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>299</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>actionOptim10</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>DccMainWindow</receiver>
|
||||
<slot>onOptim10()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>299</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>onOptim()</slot>
|
||||
<slot>onOpenFile_Action()</slot>
|
||||
<slot>displayCurrentFunction(QModelIndex)</slot>
|
||||
<slot>functionSelected(QModelIndex)</slot>
|
||||
<slot>onOptim10()</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
102
src/ui/FunctionListDockWidget.cpp
Normal file
102
src/ui/FunctionListDockWidget.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include "FunctionListDockWidget.h"
|
||||
#include "ui_FunctionListDockWidget.h"
|
||||
#include "dcc.h"
|
||||
#include "dcc_interface.h"
|
||||
#include "Procedure.h"
|
||||
|
||||
#include <QtCore>
|
||||
//#include "exe2c.h"
|
||||
extern IDcc *g_EXE2C;
|
||||
FunctionListDockWidget::FunctionListDockWidget(QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::FunctionListDockWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->m_func_list_view->setModel(&m_list_model);
|
||||
}
|
||||
|
||||
FunctionListDockWidget::~FunctionListDockWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
void FunctionListDockWidget::functionSelected(const QModelIndex &idx)
|
||||
{
|
||||
QVariant v=m_list_model.data(idx,Qt::DisplayRole);
|
||||
qDebug()<<"neb changed function to "<<v;
|
||||
g_EXE2C->SetCurFunc_by_Name(v.toString().toStdString().c_str());
|
||||
}
|
||||
// signalled by m_func_list_view accepted signal
|
||||
void FunctionListDockWidget::displayRequest(const QModelIndex &)
|
||||
{
|
||||
// argument ignored since functionSelected must've been called before us
|
||||
emit displayRequested();
|
||||
}
|
||||
void FunctionListModel::updateFunctionList()
|
||||
{
|
||||
rebuildFunctionList();
|
||||
}
|
||||
void FunctionListModel::rebuildFunctionList()
|
||||
{
|
||||
ilFunction iter = g_EXE2C->GetFirstFuncHandle();
|
||||
clear();
|
||||
beginInsertRows(QModelIndex(),0,g_EXE2C->getFuncCount());
|
||||
|
||||
while (g_EXE2C->isValidFuncHandle(iter))
|
||||
{
|
||||
const Function &info(*iter);
|
||||
//g_EXE2C->GetFuncInfo(iter, &info);
|
||||
iter = g_EXE2C->GetNextFuncHandle(iter);
|
||||
|
||||
if (info.name.isEmpty())
|
||||
continue;
|
||||
// fixme
|
||||
add_function(info.name,info.nStep,info.procEntry,info.procEntry+10,info.cbParam);
|
||||
}
|
||||
endInsertRows();
|
||||
}
|
||||
QVariant FunctionListModel::data(const QModelIndex &idx,int role) const
|
||||
{
|
||||
int row=idx.row();
|
||||
int column=idx.column();
|
||||
const function_info &inf=m_list[row];
|
||||
if(Qt::DisplayRole==role)
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case 0: // name
|
||||
{
|
||||
return QVariant(inf.m_name);
|
||||
}
|
||||
case 1: // step
|
||||
return QVariant(inf.m_decoding_step);
|
||||
case 2: // start offset
|
||||
{
|
||||
QString in_base_16=QString("%1").arg(inf.m_start_off,0,16);
|
||||
return QVariant(in_base_16);
|
||||
}
|
||||
default:
|
||||
return QVariant();
|
||||
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
QVariant FunctionListModel::headerData(int section, Qt::Orientation orientation,int role) const
|
||||
{
|
||||
if(Qt::DisplayRole==role && orientation==Qt::Horizontal)
|
||||
{
|
||||
switch(section)
|
||||
{
|
||||
case 0: // name
|
||||
return QObject::tr("Function name");
|
||||
case 1: // step
|
||||
return QObject::tr("Decoding step");
|
||||
case 2: // start offset
|
||||
return QObject::tr("Start offset");
|
||||
default:
|
||||
return QVariant();
|
||||
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
72
src/ui/FunctionListDockWidget.h
Normal file
72
src/ui/FunctionListDockWidget.h
Normal file
@ -0,0 +1,72 @@
|
||||
#ifndef FUNCTIONLISTDOCKWIDGET_H
|
||||
#define FUNCTIONLISTDOCKWIDGET_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QDockWidget>
|
||||
//#include "exe2c.h"
|
||||
|
||||
class FunctionListModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
struct function_info
|
||||
{
|
||||
QString m_name;
|
||||
int m_decoding_step;
|
||||
int m_start_off, m_end_off, m_stack_purge;
|
||||
};
|
||||
std::vector<function_info> m_list;
|
||||
public:
|
||||
int rowCount(const QModelIndex &/*idx*/) const {return m_list.size();}
|
||||
int columnCount(const QModelIndex &/*idx*/) const {return 3;}
|
||||
QVariant data(const QModelIndex &,int role) const;
|
||||
void clear()
|
||||
{
|
||||
beginResetModel();
|
||||
m_list.clear();
|
||||
endResetModel();
|
||||
}
|
||||
QVariant headerData(int section, Qt::Orientation orientation,int role) const;
|
||||
public slots:
|
||||
void updateFunctionList();
|
||||
|
||||
protected:
|
||||
void add_function(const QString &name,int step,int start_off,int end_off,int stack_purge)
|
||||
{
|
||||
|
||||
function_info info;
|
||||
info.m_name=name;
|
||||
info.m_decoding_step=step;
|
||||
info.m_start_off=start_off;
|
||||
info.m_end_off=end_off;
|
||||
info.m_stack_purge=stack_purge;
|
||||
m_list.push_back(info);
|
||||
}
|
||||
void rebuildFunctionList();
|
||||
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
class FunctionListDockWidget;
|
||||
}
|
||||
|
||||
class FunctionListDockWidget : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FunctionListDockWidget(QWidget *parent = 0);
|
||||
~FunctionListDockWidget();
|
||||
FunctionListModel *model() {return &m_list_model;}
|
||||
public slots:
|
||||
void displayRequest(const QModelIndex &idx);
|
||||
void functionSelected(const QModelIndex &idx);
|
||||
|
||||
signals:
|
||||
void displayRequested();
|
||||
private:
|
||||
Ui::FunctionListDockWidget *ui;
|
||||
FunctionListModel m_list_model;
|
||||
};
|
||||
|
||||
#endif // FUNCTIONLISTDOCKWIDGET_H
|
||||
74
src/ui/FunctionListDockWidget.ui
Normal file
74
src/ui/FunctionListDockWidget.ui
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FunctionListDockWidget</class>
|
||||
<widget class="QDockWidget" name="FunctionListDockWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>DockWidget</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTableView" name="m_func_list_view">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>m_func_list_view</sender>
|
||||
<signal>activated(QModelIndex)</signal>
|
||||
<receiver>FunctionListDockWidget</receiver>
|
||||
<slot>displayRequest(QModelIndex)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>199</x>
|
||||
<y>161</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>149</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>m_func_list_view</sender>
|
||||
<signal>clicked(QModelIndex)</signal>
|
||||
<receiver>FunctionListDockWidget</receiver>
|
||||
<slot>functionSelected(QModelIndex)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>199</x>
|
||||
<y>161</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>149</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<signal>displayRequested()</signal>
|
||||
<slot>displayRequest(QModelIndex)</slot>
|
||||
<slot>functionSelected(QModelIndex)</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
81
src/ui/FunctionViewWidget.cpp
Normal file
81
src/ui/FunctionViewWidget.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include <QDebug>
|
||||
#include <QtCore>
|
||||
#include "FunctionViewWidget.h"
|
||||
#include "ui_FunctionViewWidget.h"
|
||||
#include "RenderTags.h"
|
||||
//#include "XMLTYPE.h"
|
||||
FunctionViewWidget::FunctionViewWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::FunctionViewWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
//ui->label->setTextFormat(Qt::RichText);
|
||||
}
|
||||
|
||||
FunctionViewWidget::~FunctionViewWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void FunctionViewWidget::prtt(const char *s)
|
||||
{
|
||||
collected_text+=s;
|
||||
//collected_text+="<br>";
|
||||
}
|
||||
void FunctionViewWidget::prtt(const std::string &s)
|
||||
{
|
||||
collected_text+=s.c_str();
|
||||
//collected_text+="<br>";
|
||||
}
|
||||
void FunctionViewWidget::TAGbegin(TAG_TYPE tag_type, void *p)
|
||||
{
|
||||
QColor col= RenderTag_2_Color(tag_type);
|
||||
switch(tag_type)
|
||||
{
|
||||
case XT_Function:
|
||||
collected_text+="<body style='color: #FFFFFF; background-color: #000000'>";
|
||||
break;
|
||||
case XT_FuncName:
|
||||
case XT_Symbol:
|
||||
case XT_Keyword:
|
||||
case XT_DataType:
|
||||
case XT_Number:
|
||||
case XT_AsmOffset:
|
||||
case XT_AsmLabel:
|
||||
collected_text+="<font color='"+col.name()+"'>";
|
||||
break;
|
||||
default:
|
||||
qDebug()<<"Tag type:"<<tag_type;
|
||||
}
|
||||
}
|
||||
void FunctionViewWidget::TAGend(TAG_TYPE tag_type)
|
||||
{
|
||||
switch(tag_type)
|
||||
{
|
||||
case XT_Function:
|
||||
{
|
||||
collected_text+="</body>";
|
||||
// TODO: What about attributes with spaces?
|
||||
collected_text.replace(" ", " ");
|
||||
QFile res("result.html");
|
||||
res.open(QFile::WriteOnly);
|
||||
res.write(collected_text.toUtf8());
|
||||
res.close();
|
||||
collected_text.replace(QChar('\n'),"<br>");
|
||||
ui->textEdit->setHtml(collected_text);
|
||||
collected_text.clear();
|
||||
break;
|
||||
}
|
||||
case XT_FuncName:
|
||||
case XT_Symbol:
|
||||
case XT_Keyword:
|
||||
case XT_DataType:
|
||||
case XT_Number:
|
||||
case XT_AsmOffset:
|
||||
case XT_AsmLabel:
|
||||
collected_text+="</font>";
|
||||
break;
|
||||
default:
|
||||
qDebug()<<"Tag end:"<<tag_type;
|
||||
}
|
||||
}
|
||||
27
src/ui/FunctionViewWidget.h
Normal file
27
src/ui/FunctionViewWidget.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef FUNCTIONVIEWWIDGET_H
|
||||
#define FUNCTIONVIEWWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "StructuredTextTarget.h"
|
||||
#include "RenderTags.h"
|
||||
//#include "XmlPrt.h"
|
||||
namespace Ui {
|
||||
class FunctionViewWidget;
|
||||
}
|
||||
class FunctionViewWidget : public QWidget,public IStructuredTextTarget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FunctionViewWidget(QWidget *parent = 0);
|
||||
~FunctionViewWidget();
|
||||
void prtt(const char * s);
|
||||
void prtt(const std::string &s);
|
||||
void TAGbegin(enum TAG_TYPE tag_type, void * p);
|
||||
void TAGend(enum TAG_TYPE tag_type);
|
||||
private:
|
||||
Ui::FunctionViewWidget *ui;
|
||||
QString collected_text;
|
||||
};
|
||||
|
||||
#endif // FUNCTIONVIEWWIDGET_H
|
||||
28
src/ui/FunctionViewWidget.ui
Normal file
28
src/ui/FunctionViewWidget.ui
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FunctionViewWidget</class>
|
||||
<widget class="QWidget" name="FunctionViewWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
23
src/ui/RenderTags.cpp
Normal file
23
src/ui/RenderTags.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "RenderTags.h"
|
||||
|
||||
QColor RenderTag_2_Color(TAG_TYPE tag_type)
|
||||
{
|
||||
switch (tag_type)
|
||||
{
|
||||
case XT_invalid : return QColor(255,255,255);
|
||||
case XT_blank : return QColor(255,255,255);
|
||||
case XT_Symbol : return QColor(57,109,165);
|
||||
case XT_Function : return QColor(255,255,255);
|
||||
case XT_Keyword : return QColor(255,255,0);
|
||||
case XT_Class : return QColor(255,255,0);
|
||||
case XT_K1 : return QColor(163,70,255);
|
||||
case XT_Comment : return QColor(0,245,255);
|
||||
case XT_DataType : return QColor(100,222,192);
|
||||
case XT_Number : return QColor(0,255,0);
|
||||
case XT_AsmStack : return QColor(0,70,255);
|
||||
case XT_AsmOffset: return QColor(70,180,70);
|
||||
case XT_AsmLabel : return QColor(255,180,70);
|
||||
case XT_FuncName : return QColor(255,0,255);
|
||||
}
|
||||
return QColor(255,255,255);
|
||||
}
|
||||
28
src/ui/RenderTags.h
Normal file
28
src/ui/RenderTags.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <qcolor.h>
|
||||
enum TAG_TYPE
|
||||
{
|
||||
XT_invalid = 0,
|
||||
XT_blank,
|
||||
XT_Symbol,
|
||||
XT_Function,
|
||||
XT_Keyword, //Keywords, such as struct, union, for, while
|
||||
XT_Class, //For comound types (struct/class/union)
|
||||
XT_K1, //Braces {} []
|
||||
XT_Comment, //Comments
|
||||
XT_DataType, //
|
||||
XT_Number, //
|
||||
XT_AsmStack, //stack values
|
||||
XT_AsmOffset, //seg:offset
|
||||
XT_AsmLabel, //label name
|
||||
XT_FuncName,
|
||||
};
|
||||
struct tColorPair
|
||||
{
|
||||
QColor color1;
|
||||
QColor color2;
|
||||
};
|
||||
extern tColorPair tbl_color[];
|
||||
|
||||
QColor RenderTag_2_Color(TAG_TYPE tag_type);
|
||||
Loading…
x
Reference in New Issue
Block a user