Move Function closer to LLVM interface ( FunctionType etc. )
A few more places are using Commands.
This commit is contained in:
parent
0684062130
commit
3d5a907b30
@ -4,30 +4,35 @@
|
||||
class QTextStream;
|
||||
|
||||
struct CConv {
|
||||
enum Type {
|
||||
enum CC_Type {
|
||||
UNKNOWN=0,
|
||||
C,
|
||||
PASCAL
|
||||
};
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode)=0;
|
||||
//! given return and argument types fill Function's STKFRAME and return locations
|
||||
virtual void calculateStackLayout(Function *func)=0;
|
||||
virtual void writeComments(QTextStream &)=0;
|
||||
static CConv * create(Type v);
|
||||
static CConv * create(CC_Type v);
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
struct C_CallingConvention : public CConv {
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode);
|
||||
virtual void writeComments(QTextStream &);
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode) override;
|
||||
virtual void writeComments(QTextStream &) override;
|
||||
void calculateStackLayout(Function *func) override;
|
||||
|
||||
private:
|
||||
int processCArg(Function *callee, Function *pProc, ICODE *picode, size_t numArgs);
|
||||
};
|
||||
struct Pascal_CallingConvention : public CConv {
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode);
|
||||
virtual void writeComments(QTextStream &);
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode) override;
|
||||
virtual void writeComments(QTextStream &) override;
|
||||
void calculateStackLayout(Function *func) override;
|
||||
};
|
||||
struct Unknown_CallingConvention : public CConv {
|
||||
void processHLI(Function *func, Expr *_exp, iICODE picode) {}
|
||||
virtual void writeComments(QTextStream &);
|
||||
void processHLI(Function *func, Expr *_exp, iICODE picode) override {}
|
||||
void calculateStackLayout(Function *func) override;
|
||||
virtual void writeComments(QTextStream &) override;
|
||||
};
|
||||
|
||||
@ -263,7 +263,8 @@ enum hlType
|
||||
TYPE_STR, /* string */
|
||||
TYPE_CONST, /* constant (any type) */
|
||||
TYPE_FLOAT, /* floating point */
|
||||
TYPE_DOUBLE /* double precision float */
|
||||
TYPE_DOUBLE, /* double precision float */
|
||||
TYPE_FUNC
|
||||
};
|
||||
|
||||
/* Operand is defined, used or both flag */
|
||||
|
||||
@ -63,7 +63,7 @@ enum PROC_FLAGS
|
||||
GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */
|
||||
SI_REGVAR =0x00200000, /* SI is used as a stack variable */
|
||||
DI_REGVAR =0x00400000, /* DI is used as a stack variable */
|
||||
PROC_IS_FUNC=0x00800000, /* Proc is a function */
|
||||
//PROC_IS_FUNC=0x00800000, /* Proc is a function - determined by return type */
|
||||
REG_ARGS =0x01000000, /* Proc has registers as arguments */
|
||||
// PROC_VARARG =0x02000000, /* Proc has variable arguments */
|
||||
PROC_OUTPUT =0x04000000, /* C for this proc has been output */
|
||||
@ -74,10 +74,43 @@ enum PROC_FLAGS
|
||||
//#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
|
||||
};
|
||||
|
||||
struct FunctionType
|
||||
struct Type {
|
||||
hlType dcc_type;
|
||||
};
|
||||
struct FunctionType : public Type
|
||||
{
|
||||
CConv * m_call_conv;
|
||||
std::vector<Type> ContainedTys;
|
||||
ID retVal; /* Return value - identifier */
|
||||
bool m_vararg=false;
|
||||
unsigned getNumParams() const { return ContainedTys.size(); }
|
||||
bool isVarArg() const {return m_vararg;}
|
||||
void setReturnType(hlType t) {
|
||||
retVal.type = t;
|
||||
}
|
||||
void setReturnLocation(const LONGID_TYPE &v) {
|
||||
retVal.loc = REG_FRAME;
|
||||
retVal.longId() = v;
|
||||
}
|
||||
void setReturnLocation(eReg reg) {
|
||||
retVal.loc = REG_FRAME;
|
||||
retVal.id.regi = reg;
|
||||
}
|
||||
hlType getReturnType() const { return retVal.type; }
|
||||
void addArgument(hlType hl) {
|
||||
ContainedTys.push_back(Type {hl});
|
||||
}
|
||||
void clearArguments() { ContainedTys.clear(); }
|
||||
|
||||
void setCallingConvention(CConv::CC_Type cc);
|
||||
|
||||
static FunctionType *get(Type result,std::vector<Type> params, bool vararg_func) {
|
||||
FunctionType * res = new FunctionType;
|
||||
res->setReturnType(result.dcc_type);
|
||||
std::swap(res->ContainedTys,params);
|
||||
res->m_vararg = vararg_func;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
struct Assignment
|
||||
{
|
||||
@ -121,16 +154,17 @@ struct Function : public llvm::ilist_node<Function>
|
||||
typedef BasicBlockListType::const_iterator const_iterator;
|
||||
protected:
|
||||
BasicBlockListType BasicBlocks; ///< The basic blocks
|
||||
Function(FunctionType */*ty*/) : procEntry(0),depth(0),flg(0),cbParam(0),m_dfsLast(0),numBBs(0),
|
||||
Function(FunctionType *ty) : procEntry(0),depth(0),flg(0),cbParam(0),m_dfsLast(0),numBBs(0),
|
||||
hasCase(false),liveAnal(0)
|
||||
{
|
||||
type = ty;
|
||||
if(!ty) // No type was provided, create it
|
||||
type = new FunctionType;
|
||||
callingConv(CConv::UNKNOWN);
|
||||
}
|
||||
|
||||
public:
|
||||
FunctionType * type;
|
||||
CConv * m_call_conv;
|
||||
uint32_t procEntry; /* label number */
|
||||
QString name; /* Meaningful name for this proc */
|
||||
STATE state; /* Entry state */
|
||||
@ -139,7 +173,6 @@ public:
|
||||
int16_t cbParam; /* Probable no. of bytes of parameters */
|
||||
STKFRAME args; /* Array of arguments */
|
||||
LOCAL_ID localId; /* Local identifiers */
|
||||
ID retVal; /* Return value - identifier */
|
||||
|
||||
/* Icodes and control flow graph */
|
||||
CIcodeRec Icode; /* Object with ICODE records */
|
||||
@ -165,11 +198,14 @@ public:
|
||||
r->name = nm;
|
||||
return r;
|
||||
}
|
||||
hlType getReturnType() const {
|
||||
return getFunctionType()->getReturnType();
|
||||
}
|
||||
FunctionType *getFunctionType() const {
|
||||
return type;
|
||||
}
|
||||
CConv *callingConv() const { return m_call_conv;}
|
||||
void callingConv(CConv::Type v);
|
||||
CConv *callingConv() const { return type->m_call_conv;}
|
||||
void callingConv(CConv::CC_Type v);
|
||||
|
||||
// bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
|
||||
bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
|
||||
|
||||
@ -313,7 +313,7 @@ struct LLOperand
|
||||
{
|
||||
return not (*this == LLOperand());
|
||||
}
|
||||
void addProcInformation(int param_count, CConv::Type call_conv);
|
||||
void addProcInformation(int param_count, CConv::CC_Type call_conv);
|
||||
bool isImmediate() const { return immed;}
|
||||
void setImmediate(bool x) { immed=x;}
|
||||
bool compound() const {return is_compound;} // dx:ax pair
|
||||
|
||||
@ -104,10 +104,7 @@ public:
|
||||
char macro[10]; /* Macro for this identifier */
|
||||
QString name; /* Identifier's name */
|
||||
union ID_UNION { /* Different types of identifiers */
|
||||
friend struct ID;
|
||||
protected:
|
||||
LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
public:
|
||||
eReg regi; /* For TYPE_BYTE(WORD)_(UN)SIGN registers */
|
||||
struct { /* For TYPE_BYTE(WORD)_(UN)SIGN on the stack */
|
||||
uint8_t regOff; /* register offset (if any) */
|
||||
|
||||
@ -21,7 +21,10 @@ class QString;
|
||||
class SourceMachine;
|
||||
struct CALL_GRAPH;
|
||||
struct DosLoader;
|
||||
|
||||
struct SegOffAddr {
|
||||
uint16_t seg;
|
||||
uint32_t addr;
|
||||
};
|
||||
class Project : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -30,8 +33,8 @@ public:
|
||||
typedef FunctionListType lFunction;
|
||||
typedef FunctionListType::iterator ilFunction;
|
||||
|
||||
public:
|
||||
DosLoader * m_selected_loader;
|
||||
public:
|
||||
uint32_t SynthLab; //!< Last snthetic lab idx
|
||||
SYMTAB symtab; //!< Global symbol table
|
||||
FunctionListType pProcList; //!< List of located functions
|
||||
@ -50,10 +53,11 @@ public:
|
||||
|
||||
void create(const QString &a);
|
||||
|
||||
bool addLoadCommands();
|
||||
bool addLoadCommands(QString fname);
|
||||
void processAllCommands();
|
||||
void resetCommandsAndErrorState();
|
||||
|
||||
|
||||
const QString & output_path() const {return m_output_path;}
|
||||
const QString & project_name() const {return m_project_name;}
|
||||
const QString & binary_path() const {return m_fname;}
|
||||
@ -76,13 +80,16 @@ public:
|
||||
|
||||
const FunctionListType &functions() const { return pProcList; }
|
||||
FunctionListType &functions() { return pProcList; }
|
||||
template<class COMMANDCLASS>
|
||||
bool addCommand() {
|
||||
return m_project_command_stream.add(new COMMANDCLASS);
|
||||
}
|
||||
|
||||
bool addCommand(Command *cmd) { return m_project_command_stream.add(cmd); }
|
||||
void dumpAllErrors();
|
||||
void setLoader(DosLoader *ins);
|
||||
public slots:
|
||||
void onCommandStreamFinished(bool state);
|
||||
void onNewFunctionDiscovered(SegOffAddr ip,QString name,FunctionType *ft);
|
||||
signals:
|
||||
void newFunctionCreated(Function &);
|
||||
void loaderSelected();
|
||||
protected:
|
||||
void initialize();
|
||||
void writeGlobSymTable();
|
||||
@ -95,4 +102,3 @@ protected:
|
||||
CommandContext m_command_ctx;
|
||||
|
||||
};
|
||||
//extern Project g_proj;
|
||||
|
||||
@ -105,6 +105,8 @@ struct TypeContainer
|
||||
return 4;
|
||||
case TYPE_FLOAT:
|
||||
return 4;
|
||||
case TYPE_PTR:
|
||||
return 2;
|
||||
default:
|
||||
return ~0;
|
||||
}
|
||||
|
||||
@ -1,9 +1,89 @@
|
||||
#include "CallConvention.h"
|
||||
|
||||
#include "Procedure.h"
|
||||
|
||||
#include <QtCore/QTextStream>
|
||||
#include <ostream>
|
||||
#include <cassert>
|
||||
#include "CallConvention.h"
|
||||
#include <QtCore/QTextStream>
|
||||
static void calculateReturnLocations(Function *func) {
|
||||
switch(func->getReturnType()) {
|
||||
case TYPE_LONG_SIGN:
|
||||
case TYPE_LONG_UNSIGN:
|
||||
func->getFunctionType()->setReturnLocation(LONGID_TYPE(rDX,rAX));
|
||||
break;
|
||||
case TYPE_WORD_SIGN:
|
||||
case TYPE_WORD_UNSIGN:
|
||||
func->getFunctionType()->setReturnLocation(rAX);
|
||||
break;
|
||||
case TYPE_BYTE_SIGN:
|
||||
case TYPE_BYTE_UNSIGN:
|
||||
func->getFunctionType()->setReturnLocation(rAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void calculateArgLocations_allOnStack(Function *func) {
|
||||
FunctionType *type = func->type;
|
||||
int stack_offset=2;
|
||||
if(func->args.size() == type->ContainedTys.size())
|
||||
return;
|
||||
func->args.resize(type->ContainedTys.size());
|
||||
func->args.numArgs=0;
|
||||
for(Type & argtype : type->ContainedTys) {
|
||||
STKSYM &arg(func->args[func->args.numArgs]);
|
||||
arg.label= stack_offset;
|
||||
arg.size = TypeContainer::typeSize(argtype.dcc_type);
|
||||
arg.type = argtype.dcc_type;
|
||||
arg.setArgName(func->args.numArgs);
|
||||
stack_offset+=arg.size;
|
||||
func->args.maxOff=stack_offset;
|
||||
func->args.numArgs++;
|
||||
}
|
||||
func->cbParam = stack_offset;
|
||||
}
|
||||
|
||||
CConv *CConv::create(Type v)
|
||||
static void rebuildArguments_FromStackLayout(Function *func) {
|
||||
|
||||
STKFRAME &stk(func->args);
|
||||
std::map<int,const STKSYM *> arg_locations;
|
||||
FunctionType *f;
|
||||
|
||||
for(const STKSYM & s: stk) {
|
||||
if(s.label>0) {
|
||||
arg_locations[s.label] = &s;
|
||||
}
|
||||
}
|
||||
|
||||
if(arg_locations.empty())
|
||||
return;
|
||||
|
||||
std::vector<Type> argtypes;
|
||||
auto stack_loc_iter = arg_locations.begin();
|
||||
for(int i=stack_loc_iter->first; i<=arg_locations.rbegin()->first; ) {
|
||||
int till_next_loc=stack_loc_iter->first-i;
|
||||
if(till_next_loc==0) {
|
||||
int entry_size=stack_loc_iter->second->size;
|
||||
argtypes.push_back({stack_loc_iter->second->type});
|
||||
i+=entry_size;
|
||||
++stack_loc_iter;
|
||||
} else {
|
||||
if(till_next_loc>=4) {
|
||||
argtypes.push_back({TYPE_LONG_SIGN});
|
||||
i+=4;
|
||||
} else if(till_next_loc>=2) {
|
||||
argtypes.push_back({TYPE_WORD_SIGN});
|
||||
i+=2;
|
||||
} else {
|
||||
argtypes.push_back({TYPE_BYTE_SIGN});
|
||||
i+=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
f = FunctionType::get({func->type->getReturnType()},argtypes,func->type->isVarArg());
|
||||
f->retVal = func->type->retVal;
|
||||
delete func->type;
|
||||
func->type = f;
|
||||
}
|
||||
CConv *CConv::create(CC_Type v)
|
||||
{
|
||||
static C_CallingConvention *c_call = nullptr;
|
||||
static Pascal_CallingConvention *p_call = nullptr;
|
||||
@ -27,11 +107,31 @@ void C_CallingConvention::writeComments(QTextStream & ostr)
|
||||
{
|
||||
ostr << " * C calling convention.\n";
|
||||
}
|
||||
|
||||
void C_CallingConvention::calculateStackLayout(Function *func)
|
||||
{
|
||||
calculateReturnLocations(func);
|
||||
rebuildArguments_FromStackLayout(func);
|
||||
calculateArgLocations_allOnStack(func);
|
||||
}
|
||||
void Pascal_CallingConvention::writeComments(QTextStream & ostr)
|
||||
{
|
||||
ostr << " * Pascal calling convention.\n";
|
||||
}
|
||||
void Pascal_CallingConvention::calculateStackLayout(Function *func)
|
||||
{
|
||||
calculateReturnLocations(func);
|
||||
//TODO: pascal args are passed in reverse order ?
|
||||
rebuildArguments_FromStackLayout(func);
|
||||
calculateArgLocations_allOnStack(func);
|
||||
}
|
||||
void Unknown_CallingConvention::writeComments(QTextStream & ostr)
|
||||
{
|
||||
ostr << " * Unknown calling convention.\n";
|
||||
}
|
||||
void Unknown_CallingConvention::calculateStackLayout(Function *func)
|
||||
{
|
||||
calculateReturnLocations(func);
|
||||
rebuildArguments_FromStackLayout(func);
|
||||
calculateArgLocations_allOnStack(func);
|
||||
}
|
||||
|
||||
@ -1,58 +1,75 @@
|
||||
#include "Command.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
#include "Loaders.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
bool LoaderSelection::execute(CommandContext * ctx, Project *p)
|
||||
bool LoaderSelection::execute(CommandContext * ctx)
|
||||
{
|
||||
if(p->binary_path().isEmpty()) {
|
||||
ctx->recordFailure(this,QString("No executable path set in project %1").arg(p->project_name()));
|
||||
Project *proj=ctx->proj;
|
||||
if(nullptr==proj) {
|
||||
ctx->recordFailure(this,"No active project ");
|
||||
return false;
|
||||
}
|
||||
if(m_filename.isEmpty()) {
|
||||
ctx->recordFailure(this,"No executable path given to loader selector");
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile finfo(p->binary_path());
|
||||
QFile finfo(m_filename);
|
||||
/* Open the input file */
|
||||
if(not finfo.open(QFile::ReadOnly)) {
|
||||
ctx->recordFailure(this,QString("Cannot open file %1").arg(p->binary_path()));
|
||||
ctx->recordFailure(this,QString("Cannot open file %1").arg(m_filename));
|
||||
return false;
|
||||
}
|
||||
/* Read in first 2 bytes to check EXE signature */
|
||||
if (finfo.size()<=2)
|
||||
{
|
||||
ctx->recordFailure(this,QString("File %1 is too small").arg(p->binary_path()));
|
||||
ctx->recordFailure(this,QString("File %1 is too small").arg(m_filename));
|
||||
}
|
||||
ComLoader com_loader;
|
||||
ExeLoader exe_loader;
|
||||
|
||||
if(exe_loader.canLoad(finfo)) {
|
||||
p->m_selected_loader = new ExeLoader;
|
||||
proj->setLoader(new ExeLoader);
|
||||
return true;
|
||||
}
|
||||
if(com_loader.canLoad(finfo)) {
|
||||
p->m_selected_loader = new ComLoader;
|
||||
proj->setLoader(new ExeLoader);
|
||||
return true;
|
||||
}
|
||||
ctx->recordFailure(this,QString("None of the available loaders can load file %1").arg(p->binary_path()));
|
||||
ctx->recordFailure(this,QString("None of the available loaders can load file %1").arg(m_filename));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoaderApplication::execute(CommandContext * ctx, Project *p)
|
||||
bool LoaderApplication::execute(CommandContext * ctx)
|
||||
{
|
||||
if(!p)
|
||||
return false;
|
||||
if(!p->m_selected_loader) {
|
||||
ctx->recordFailure(this,QString("No loader selected for project %1").arg(p->project_name()));
|
||||
Project *proj=ctx->proj;
|
||||
|
||||
if(nullptr==proj) {
|
||||
ctx->recordFailure(this,"No active project ");
|
||||
return false;
|
||||
}
|
||||
QFile finfo(p->binary_path());
|
||||
if(!proj->m_selected_loader) {
|
||||
ctx->recordFailure(this,QString("No loader selected for project %1").arg(proj->project_name()));
|
||||
return false;
|
||||
}
|
||||
QFile finfo(m_filename);
|
||||
if(not finfo.open(QFile::ReadOnly)) {
|
||||
ctx->recordFailure(this,QString("Cannot open file %1").arg(p->binary_path()));
|
||||
ctx->recordFailure(this,QString("Cannot open file %1").arg(m_filename));
|
||||
return false;
|
||||
}
|
||||
return p->m_selected_loader->load(p->prog,finfo);
|
||||
bool load_res = proj->m_selected_loader->load(proj->prog,finfo);
|
||||
if(!load_res) {
|
||||
ctx->recordFailure(this,QString("Failure during load: %1").arg(m_filename));
|
||||
return false;
|
||||
}
|
||||
if (option.verbose)
|
||||
proj->prog.displayLoadInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandStream::add(Command * c) {
|
||||
@ -70,7 +87,7 @@ void CommandStream::processAll(CommandContext *ctx)
|
||||
{
|
||||
while(not m_commands.isEmpty()) {
|
||||
Command *cmd = m_commands.takeFirst();
|
||||
if(false==cmd->execute(ctx,ctx->proj)) {
|
||||
if(false==cmd->execute(ctx)) {
|
||||
emit streamCompleted(false);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ class Command
|
||||
public:
|
||||
Command(QString n,CommandLevel level) : m_command_name(n),m_level(level) {}
|
||||
QString name() const { return m_command_name;}
|
||||
virtual bool execute(CommandContext *,Project *) { return false; }
|
||||
virtual bool execute(CommandContext *) { return false; }
|
||||
};
|
||||
class CompoundCommand : public Command {
|
||||
QVector<Command *> m_contained;
|
||||
@ -43,9 +43,9 @@ public:
|
||||
void addCommand(Command *c) {
|
||||
m_contained.push_back(c);
|
||||
}
|
||||
bool execute(CommandContext * ctx,Project *v) {
|
||||
bool execute(CommandContext * ctx) {
|
||||
for(Command * c : m_contained) {
|
||||
if(!c->execute(ctx,v))
|
||||
if(!c->execute(ctx))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -65,17 +65,21 @@ public:
|
||||
signals:
|
||||
void streamCompleted(bool success);
|
||||
};
|
||||
|
||||
// Effect: loader has been selected and set in current project
|
||||
class LoaderSelection : public Command {
|
||||
QString m_filename;
|
||||
public:
|
||||
virtual ~LoaderSelection() {}
|
||||
LoaderSelection() : Command("Select loader",eProject) {}
|
||||
bool execute(CommandContext * ctx,Project *) override;
|
||||
LoaderSelection(QString f) : Command("Select loader",eProject),m_filename(f) {}
|
||||
bool execute(CommandContext * ctx) override;
|
||||
};
|
||||
// trigger Project->m_selected_loader has changed
|
||||
// Effect: the PROG object is loaded using the current loader
|
||||
class LoaderApplication : public Command {
|
||||
QString m_filename;
|
||||
public:
|
||||
virtual ~LoaderApplication() {}
|
||||
LoaderApplication() : Command("Apply loader",eProject) {}
|
||||
bool execute(CommandContext * ctx,Project *) override;
|
||||
LoaderApplication(QString f) : Command("Apply loader",eProject),m_filename(f) {}
|
||||
bool execute(CommandContext * ctx) override;
|
||||
};
|
||||
#endif // COMMAND_H
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "project.h"
|
||||
#include "disassem.h"
|
||||
#include "CallGraph.h"
|
||||
#include "Command.h"
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QDebug>
|
||||
@ -320,6 +321,71 @@ struct ExeLoader : public DosLoader {
|
||||
/*****************************************************************************
|
||||
* LoadImage
|
||||
****************************************************************************/
|
||||
struct MachineStateInitialization : public Command {
|
||||
|
||||
public:
|
||||
MachineStateInitialization() : Command("Initialize simulated machine state",eProject) {}
|
||||
|
||||
bool execute(CommandContext *ctx) override
|
||||
{
|
||||
assert(ctx && ctx->proj);
|
||||
Project &proj(*ctx->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;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct FindMain : public Command {
|
||||
FindMain() : Command("Locate the main entry point",eProject) {
|
||||
}
|
||||
bool execute(CommandContext *ctx) {
|
||||
Project &proj(*ctx->proj);
|
||||
const PROG &prog(proj.prog);
|
||||
|
||||
if(ctx->proj->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();
|
||||
if (prog.offMain != -1)
|
||||
{
|
||||
FunctionType *main_type = FunctionType::get(Type{TYPE_WORD_SIGN},{ Type{TYPE_WORD_SIGN},Type{TYPE_PTR} },false);
|
||||
main_type->setCallingConvention(CConv::C);
|
||||
proj.onNewFunctionDiscovered( SegOffAddr {prog.segMain,prog.offMain},"main",main_type);
|
||||
//TODO: main arguments and return values should depend on detected compiler/library
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FunctionType *main_type = FunctionType::get(Type{TYPE_UNKNOWN},{ Type{TYPE_UNKNOWN} },false);
|
||||
main_type->setCallingConvention(CConv::UNKNOWN);
|
||||
/* Create initial procedure at program start address */
|
||||
proj.onNewFunctionDiscovered( SegOffAddr {prog.segMain,proj.m_entry_state.IP},"start",main_type);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct AddFunction : public Command {
|
||||
QString m_name;
|
||||
uint16_t m_seg;
|
||||
uint32_t m_addr;
|
||||
FunctionType *m_type;
|
||||
AddFunction(QString name,uint16_t seg,uint32_t address,FunctionType *f) : Command("Create function",eProject),
|
||||
m_name(name),
|
||||
m_seg(seg),
|
||||
m_addr(address)
|
||||
{}
|
||||
bool execute(CommandContext *ctx) override {
|
||||
|
||||
}
|
||||
};
|
||||
void DccFrontend::initializeMachineState(Project &proj)
|
||||
{
|
||||
const PROG &prog(proj.prog);
|
||||
@ -339,10 +405,11 @@ void DccFrontend::createEntryProc(Project &proj)
|
||||
/* Make a struct for the initial procedure */
|
||||
if (prog.offMain != -1)
|
||||
{
|
||||
start_proc = proj.createFunction(0,"main");
|
||||
start_proc->retVal.loc = REG_FRAME;
|
||||
start_proc->retVal.type = TYPE_WORD_SIGN;
|
||||
start_proc->retVal.id.regi = rAX;
|
||||
//TODO: main arguments and return values should depend on detected compiler/library
|
||||
FunctionType *main_type = FunctionType::get(Type{TYPE_WORD_SIGN},{ Type{TYPE_WORD_SIGN},Type{TYPE_PTR} },false);
|
||||
|
||||
start_proc = proj.createFunction(main_type,"main");
|
||||
start_proc->callingConv(CConv::C);
|
||||
/* We know where main() is. Start the flow of control from there */
|
||||
start_proc->procEntry = prog.offMain;
|
||||
/* In medium and large models, the segment of main may (will?) not be
|
||||
@ -369,18 +436,14 @@ void DccFrontend::createEntryProc(Project &proj)
|
||||
void DccFrontend::parse(Project &proj)
|
||||
{
|
||||
/* Set initial state */
|
||||
initializeMachineState(proj);
|
||||
|
||||
/* Check for special settings of initial state, based on idioms of the
|
||||
startup code */
|
||||
proj.m_entry_state.checkStartup();
|
||||
proj.addCommand(new MachineStateInitialization);
|
||||
proj.addCommand(new FindMain);
|
||||
|
||||
createEntryProc(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();
|
||||
//BUG: proj and g_proj are 'live' at this point !
|
||||
|
||||
/* Recursively build entire procedure list */
|
||||
proj.callGraph->proc->FollowCtrl(proj.callGraph, &proj.m_entry_state);
|
||||
|
||||
@ -35,6 +35,13 @@ void JumpTable::pruneEntries(uint16_t cs)
|
||||
}
|
||||
|
||||
|
||||
void Function::callingConv(CConv::Type v) {
|
||||
m_call_conv=CConv::create(v);
|
||||
void Function::callingConv(CConv::CC_Type v) {
|
||||
type->setCallingConvention(v);
|
||||
getFunctionType()->m_call_conv->calculateStackLayout(this);
|
||||
}
|
||||
|
||||
void FunctionType::setCallingConvention(CConv::CC_Type cc)
|
||||
{
|
||||
m_call_conv=CConv::create(cc);
|
||||
assert(m_call_conv);
|
||||
}
|
||||
|
||||
@ -897,10 +897,10 @@ QString FuncNode::walkCondExpr(Function *pProc, int *numLoc) const
|
||||
|
||||
int FuncNode::hlTypeSize(Function *) const
|
||||
{
|
||||
return hlSize[call.proc->retVal.type];
|
||||
return hlSize[call.proc->getReturnType()];
|
||||
}
|
||||
|
||||
hlType FuncNode::expType(Function *) const
|
||||
{
|
||||
return call.proc->retVal.type;
|
||||
return call.proc->getReturnType();
|
||||
}
|
||||
|
||||
@ -226,8 +226,8 @@ void Function::codeGen (QIODevice &fs)
|
||||
|
||||
/* Write procedure/function header */
|
||||
cCode.init();
|
||||
if (flg & PROC_IS_FUNC) /* Function */
|
||||
ostr << QString("\n%1 %2 (").arg(TypeContainer::typeName(retVal.type)).arg(name);
|
||||
if (getReturnType() != TYPE_UNKNOWN) /* Function flg & PROC_IS_FUNC*/
|
||||
ostr << QString("\n%1 %2 (").arg(TypeContainer::typeName(getReturnType())).arg(name);
|
||||
else /* Procedure */
|
||||
ostr << "\nvoid "+name+" (";
|
||||
|
||||
|
||||
@ -480,27 +480,32 @@ bool LibCheck(Function & pProc)
|
||||
pProc.callingConv(CConv::C);
|
||||
if (i != NIL)
|
||||
{
|
||||
PH_FUNC_STRUCT &phfunc(pFunc[i]);
|
||||
/* Allocate space for the arg struct, and copy the hlType to
|
||||
the appropriate field */
|
||||
arg = pFunc[i].firstArg;
|
||||
pProc.args.numArgs = pFunc[i].numArg;
|
||||
pProc.args.resize(pFunc[i].numArg);
|
||||
for (j=0; j < pFunc[i].numArg; j++)
|
||||
arg = phfunc.firstArg;
|
||||
pProc.args.numArgs = phfunc.numArg;
|
||||
pProc.args.resize(phfunc.numArg);
|
||||
pProc.getFunctionType()->clearArguments();
|
||||
for (j=0; j < phfunc.numArg; j++)
|
||||
{
|
||||
pProc.getFunctionType()->addArgument(pArg[arg]);
|
||||
pProc.args[j].type = pArg[arg++];
|
||||
}
|
||||
if (pFunc[i].typ != TYPE_UNKNOWN)
|
||||
if (phfunc.typ != TYPE_UNKNOWN)
|
||||
{
|
||||
pProc.retVal.type = pFunc[i].typ;
|
||||
pProc.flg |= PROC_IS_FUNC;
|
||||
switch (pProc.retVal.type) {
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
pProc.type->setReturnType(phfunc.typ);
|
||||
switch (pProc.getReturnType()) {
|
||||
case TYPE_LONG_SIGN:
|
||||
case TYPE_LONG_UNSIGN:
|
||||
pProc.liveOut.setReg(rDX).addReg(rAX);
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
case TYPE_WORD_SIGN:
|
||||
case TYPE_WORD_UNSIGN:
|
||||
pProc.liveOut.setReg(rAX);
|
||||
break;
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
case TYPE_BYTE_SIGN:
|
||||
case TYPE_BYTE_UNSIGN:
|
||||
pProc.liveOut.setReg(rAL);
|
||||
break;
|
||||
case TYPE_STR:
|
||||
@ -510,10 +515,11 @@ bool LibCheck(Function & pProc)
|
||||
break;
|
||||
default:
|
||||
qCritical() << QString("Unknown retval type %1 for %2 in LibCheck")
|
||||
.arg(pProc.retVal.type).arg(pProc.name);
|
||||
.arg(pProc.getReturnType()).arg(pProc.name);
|
||||
/*** other types are not considered yet ***/
|
||||
}
|
||||
}
|
||||
pProc.getFunctionType()->m_call_conv->calculateStackLayout(&pProc);
|
||||
pProc.getFunctionType()->m_vararg = pFunc[i].bVararg;
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,9 +239,9 @@ void Function::writeProcComments(QTextStream &ostr)
|
||||
if (this->flg & PROC_ASM)
|
||||
{
|
||||
ostr << " * Untranslatable routine. Assembler provided.\n";
|
||||
if (this->flg & PROC_IS_FUNC)
|
||||
switch (this->retVal.type) { // TODO: Functions return value in various regs
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
switch (getReturnType()) { // TODO: Functions return value in various regs
|
||||
case TYPE_BYTE_SIGN:
|
||||
case TYPE_BYTE_UNSIGN:
|
||||
ostr << " * Return value in register al.\n";
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
@ -250,8 +250,11 @@ void Function::writeProcComments(QTextStream &ostr)
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
ostr << " * Return value in registers dx:ax.\n";
|
||||
break;
|
||||
case TYPE_UNKNOWN:
|
||||
// void return type
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Unknown retval type %d",this->retVal.type);
|
||||
fprintf(stderr,"Unknown retval type %d",getReturnType());
|
||||
break;
|
||||
} /* eos */
|
||||
}
|
||||
|
||||
@ -321,12 +321,12 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
|
||||
pbb->liveOut = in_liveOut;
|
||||
|
||||
/* Get return expression of function */
|
||||
if (flg & PROC_IS_FUNC)
|
||||
if (getReturnType()!=TYPE_UNKNOWN)
|
||||
{
|
||||
auto picode = pbb->rbegin(); /* icode of function return */
|
||||
if (picode->hl()->opcode == HLI_RET)
|
||||
{
|
||||
picode->hlU()->expr(AstIdent::idID(&retVal, &localId, (++pbb->rbegin()).base()));
|
||||
picode->hlU()->expr(AstIdent::idID(&type->retVal, &localId, (++pbb->rbegin()).base()));
|
||||
picode->du.use = in_liveOut;
|
||||
}
|
||||
}
|
||||
@ -353,7 +353,7 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
|
||||
}
|
||||
else /* library routine */
|
||||
{
|
||||
if ( (pcallee->flg & PROC_IS_FUNC) and /* returns a value */
|
||||
if ( (pcallee->getReturnType()!=TYPE_UNKNOWN) and /* returns a value */
|
||||
(pcallee->liveOut & pbb->edges[0].BBptr->liveIn).any()
|
||||
)
|
||||
pbb->liveOut = pcallee->liveOut;
|
||||
@ -363,7 +363,7 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
|
||||
|
||||
if ((not (pcallee->flg & PROC_ISLIB)) or ( pbb->liveOut.any() ))
|
||||
{
|
||||
switch (pcallee->retVal.type) {
|
||||
switch (pcallee->getReturnType()) {
|
||||
case TYPE_LONG_SIGN:
|
||||
case TYPE_LONG_UNSIGN:
|
||||
ticode.du1.setDef(rAX).addDef(rDX);
|
||||
@ -461,7 +461,7 @@ bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at)
|
||||
* on optimized code. */
|
||||
void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode)
|
||||
{
|
||||
if (not ((picode.hl()->opcode == HLI_CALL) and (picode.hl()->call.proc->flg & PROC_IS_FUNC)))
|
||||
if (not ((picode.hl()->opcode == HLI_CALL) and (picode.hl()->call.proc->getReturnType()!=TYPE_UNKNOWN)))
|
||||
return;
|
||||
|
||||
BB *tbb = this->edges[0].BBptr;
|
||||
@ -971,7 +971,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
case HLI_CALL:
|
||||
ticode = picode->du1.idx[0].uses.front();
|
||||
ti_hl = ticode->hlU();
|
||||
_retVal = &_icHl.call.proc->retVal;
|
||||
_retVal = &_icHl.call.proc->type->retVal;
|
||||
switch (ti_hl->opcode)
|
||||
{
|
||||
case HLI_ASSIGN:
|
||||
@ -1095,7 +1095,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
|
||||
case HLI_JCOND:
|
||||
_exp = _icHl.call.toAst();
|
||||
_retVal = &picode->hl()->call.proc->retVal;
|
||||
_retVal = &picode->hl()->call.proc->type->retVal;
|
||||
res = Expr::insertSubTreeLongReg (_exp,
|
||||
ticode->hlU()->exp.v,
|
||||
locals.newLongReg ( _retVal->type, _retVal->longId(), picode.base()));
|
||||
@ -1146,7 +1146,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
if ( not _icHl.call.proc->isLibrary() and (not picode->du1.used(0)) and (picode->du1.getNumRegsDef() > 0))
|
||||
{
|
||||
_exp = new FuncNode(_icHl.call.proc, _icHl.call.args);
|
||||
auto lhs = AstIdent::idID (&_icHl.call.proc->retVal, &locals, picode.base());
|
||||
auto lhs = AstIdent::idID (&_icHl.call.proc->type->retVal, &locals, picode.base());
|
||||
picode->setAsgn(lhs, _exp);
|
||||
}
|
||||
}
|
||||
@ -1183,7 +1183,6 @@ void Function::preprocessReturnDU(LivenessSet &_liveOut)
|
||||
if(not _liveOut.any())
|
||||
return;
|
||||
}
|
||||
flg |= PROC_IS_FUNC;
|
||||
isAx = _liveOut.testReg(rAX);
|
||||
isBx = _liveOut.testReg(rBX);
|
||||
isCx = _liveOut.testReg(rCX);
|
||||
@ -1219,53 +1218,55 @@ void Function::preprocessReturnDU(LivenessSet &_liveOut)
|
||||
|
||||
if (isAx and isDx) /* long or pointer */
|
||||
{
|
||||
retVal.type = TYPE_LONG_SIGN;
|
||||
retVal.loc = REG_FRAME;
|
||||
retVal.longId() = LONGID_TYPE(rDX,rAX);
|
||||
type->setReturnType(TYPE_LONG_SIGN);
|
||||
type->m_call_conv->calculateStackLayout(this);
|
||||
/*idx = */localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), Icode.begin());
|
||||
localId.propLongId (rAX, rDX, "");
|
||||
}
|
||||
else if (isAx or isBx or isCx or isDx) /* uint16_t */
|
||||
{
|
||||
retVal.type = TYPE_WORD_SIGN;
|
||||
retVal.loc = REG_FRAME;
|
||||
eReg selected_reg;
|
||||
if (isAx)
|
||||
retVal.id.regi = rAX;
|
||||
selected_reg = rAX;
|
||||
else if (isBx)
|
||||
retVal.id.regi = rBX;
|
||||
selected_reg = rBX;
|
||||
else if (isCx)
|
||||
retVal.id.regi = rCX;
|
||||
selected_reg = rCX;
|
||||
else
|
||||
retVal.id.regi = rDX;
|
||||
/*idx = */localId.newByteWordReg(TYPE_WORD_SIGN,retVal.id.regi);
|
||||
selected_reg = rDX;
|
||||
type->setReturnType(TYPE_WORD_SIGN);
|
||||
type->m_call_conv->calculateStackLayout(this);
|
||||
/*idx = */localId.newByteWordReg(TYPE_WORD_SIGN,selected_reg);
|
||||
}
|
||||
else if(isAL or isBL or isCL or isDL)
|
||||
{
|
||||
retVal.type = TYPE_BYTE_SIGN;
|
||||
retVal.loc = REG_FRAME;
|
||||
eReg selected_reg;
|
||||
if (isAL)
|
||||
retVal.id.regi = rAL;
|
||||
selected_reg = rAL;
|
||||
else if (isBL)
|
||||
retVal.id.regi = rBL;
|
||||
selected_reg = rBL;
|
||||
else if (isCL)
|
||||
retVal.id.regi = rCL;
|
||||
selected_reg = rCL;
|
||||
else
|
||||
retVal.id.regi = rDL;
|
||||
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,retVal.id.regi);
|
||||
selected_reg = rDL;
|
||||
type->setReturnType(TYPE_BYTE_SIGN);
|
||||
type->m_call_conv->calculateStackLayout(this);
|
||||
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,selected_reg);
|
||||
}
|
||||
else if(isAH or isBH or isCH or isDH)
|
||||
{
|
||||
retVal.type = TYPE_BYTE_SIGN;
|
||||
retVal.loc = REG_FRAME;
|
||||
eReg selected_reg;
|
||||
if (isAH)
|
||||
retVal.id.regi = rAH;
|
||||
selected_reg = rAH;
|
||||
else if (isBH)
|
||||
retVal.id.regi = rBH;
|
||||
selected_reg = rBH;
|
||||
else if (isCH)
|
||||
retVal.id.regi = rCH;
|
||||
selected_reg = rCH;
|
||||
else
|
||||
retVal.id.regi = rDH;
|
||||
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,retVal.id.regi);
|
||||
selected_reg = rDH;
|
||||
type->setReturnType(TYPE_BYTE_SIGN);
|
||||
type->m_call_conv->calculateStackLayout(this);
|
||||
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,selected_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ int main(int argc, char **argv)
|
||||
proj->create(option.filename);
|
||||
|
||||
DccFrontend fe(&app);
|
||||
proj->addLoadCommands();
|
||||
proj->addLoadCommands(option.filename);
|
||||
proj->processAllCommands();
|
||||
if(proj->m_error_state) {
|
||||
proj->dumpAllErrors();
|
||||
@ -201,6 +201,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if (option.verbose)
|
||||
proj->prog.displayLoadInfo();
|
||||
|
||||
if(false==fe.FrontEnd ())
|
||||
return -1;
|
||||
if(option.asm1)
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
extern Project g_proj;
|
||||
//static BB * rmJMP(Function * pProc, int marker, BB * pBB);
|
||||
//static void mergeFallThrough(Function * pProc, BB * pBB);
|
||||
//static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last);
|
||||
|
||||
@ -89,7 +89,7 @@ bool LLOperand::isReg() const
|
||||
{
|
||||
return (regi>=rAX) and (regi<=rTMP);
|
||||
}
|
||||
void LLOperand::addProcInformation(int param_count, CConv::Type call_conv)
|
||||
void LLOperand::addProcInformation(int param_count, CConv::CC_Type call_conv)
|
||||
{
|
||||
proc.proc->cbParam = (int16_t)param_count;
|
||||
proc.cb = param_count;
|
||||
|
||||
@ -124,11 +124,10 @@ void Function::findIdioms()
|
||||
/* Check for library functions that return a long register.
|
||||
* Propagate this result */
|
||||
if (pIcode->ll()->src().proc.proc != nullptr)
|
||||
if ((pIcode->ll()->src().proc.proc->flg & PROC_ISLIB) and
|
||||
(pIcode->ll()->src().proc.proc->flg & PROC_IS_FUNC))
|
||||
if ( pIcode->ll()->src().proc.proc->flg & PROC_ISLIB )
|
||||
{
|
||||
if ((pIcode->ll()->src().proc.proc->retVal.type==TYPE_LONG_SIGN)
|
||||
or (pIcode->ll()->src().proc.proc->retVal.type == TYPE_LONG_UNSIGN))
|
||||
if ((pIcode->ll()->src().proc.proc->getReturnType()==TYPE_LONG_SIGN)
|
||||
or (pIcode->ll()->src().proc.proc->getReturnType() == TYPE_LONG_UNSIGN))
|
||||
localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), pIcode/*ip*/);
|
||||
}
|
||||
|
||||
|
||||
@ -1032,8 +1032,9 @@ static void use (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int
|
||||
{
|
||||
if (pm->regi == INDEX_BP) /* indexed on bp */
|
||||
{
|
||||
if (pm->off >= 2)
|
||||
if (pm->off >= 2) {
|
||||
pProc->args.updateFrameOff ( pm->off, size, eDuVal::USE);
|
||||
}
|
||||
else if (pm->off < 0)
|
||||
pProc->localId.newByteWordStk (TYPE_WORD_SIGN, pm->off, 0);
|
||||
}
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
extern Project g_proj;
|
||||
/* Static indentation buffer */
|
||||
static constexpr int indSize=81; /* size of indentation buffer; max 20 */
|
||||
static char indentBuf[indSize] =
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
#include <utility>
|
||||
|
||||
using namespace std;
|
||||
//Project g_proj;
|
||||
QString asm1_name, asm2_name; /* Assembler output filenames */
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
STATS stats; /* cfg statistics */
|
||||
@ -59,11 +58,25 @@ ilFunction Project::findByEntry(uint32_t entry)
|
||||
[entry](const Function &f) { return f.procEntry==entry; });
|
||||
return iter;
|
||||
}
|
||||
void Project::onNewFunctionDiscovered(SegOffAddr ip, QString name, FunctionType *ft) {
|
||||
FIXME;
|
||||
auto proc = createFunction(ft,name);
|
||||
// FIXME: use provided segment addr !
|
||||
proc->procEntry = ip.addr;
|
||||
if(name=="main") {
|
||||
/* In medium and large models, the segment of main may (will?) not be
|
||||
the same as the initial CS segment (of the startup code) */
|
||||
m_entry_state.setState(rCS, prog.segMain);
|
||||
m_entry_state.IP = prog.offMain;
|
||||
}
|
||||
|
||||
}
|
||||
ilFunction Project::createFunction(FunctionType *f,const QString &name)
|
||||
{
|
||||
pProcList.push_back(Function::Create(f,0,name,0));
|
||||
return (++pProcList.rbegin()).base();
|
||||
ilFunction iter = (++pProcList.rbegin()).base();
|
||||
emit newFunctionCreated(*iter);
|
||||
return iter;
|
||||
}
|
||||
|
||||
int Project::getSymIdxByAdd(uint32_t adr)
|
||||
@ -123,11 +136,17 @@ void Project::dumpAllErrors() {
|
||||
qDebug() << QString("%1 command failed with : %2").arg(v.first->name()).arg(v.second);
|
||||
}
|
||||
}
|
||||
bool Project::addLoadCommands()
|
||||
|
||||
void Project::setLoader(DosLoader * ldr)
|
||||
{
|
||||
if(!addCommand<LoaderSelection>())
|
||||
m_selected_loader = ldr;
|
||||
emit loaderSelected();
|
||||
}
|
||||
bool Project::addLoadCommands(QString fname)
|
||||
{
|
||||
if(!addCommand(new LoaderSelection(fname)))
|
||||
return false;
|
||||
if(!addCommand<LoaderApplication>()) {
|
||||
if(!addCommand(new LoaderApplication(fname))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#include <cassert>
|
||||
#include <stdio.h>
|
||||
#include <CallGraph.h>
|
||||
extern Project g_proj;
|
||||
//static void displayCFG(Function * pProc);
|
||||
//static void displayDfs(BB * pBB);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user