Extend responsibilities of FunctionViewWidget
Reduced IDcc interface functionality. Fix a few bugs/warnings discovered by coverity. Emit functionUpdate signal from project when function object internal fields change.
This commit is contained in:
parent
292e4041e1
commit
152625d67d
2
3rd_party/libdisasm/libdis.h
vendored
2
3rd_party/libdisasm/libdis.h
vendored
@ -626,7 +626,7 @@ public:
|
|||||||
/* the instruction proper */
|
/* the instruction proper */
|
||||||
enum x86_insn_prefix prefix; /* prefixes ORed together */
|
enum x86_insn_prefix prefix; /* prefixes ORed together */
|
||||||
char prefix_string[MAX_PREFIX_STR]; /* prefixes [might be truncated] */
|
char prefix_string[MAX_PREFIX_STR]; /* prefixes [might be truncated] */
|
||||||
char mnemonic[MAX_MNEM_STR];
|
char mnemonic[MAX_MNEM_STR+1];
|
||||||
x86_oplist_t *operands; /* list of explicit/implicit operands */
|
x86_oplist_t *operands; /* list of explicit/implicit operands */
|
||||||
size_t operand_count; /* total number of operands */
|
size_t operand_count; /* total number of operands */
|
||||||
size_t explicit_count; /* number of explicit operands */
|
size_t explicit_count; /* number of explicit operands */
|
||||||
|
|||||||
@ -10,12 +10,7 @@ class IStructuredTextTarget;
|
|||||||
struct IDcc {
|
struct IDcc {
|
||||||
static IDcc *get();
|
static IDcc *get();
|
||||||
virtual void BaseInit()=0;
|
virtual void BaseInit()=0;
|
||||||
virtual void Init(QObject *tgt)=0;
|
|
||||||
virtual void analysis_Once()=0;
|
|
||||||
virtual bool load(QString name)=0; // load and preprocess -> find entry point
|
virtual bool load(QString name)=0; // load and preprocess -> find entry point
|
||||||
virtual void prtout_asm(PtrFunction f,IStructuredTextTarget *,int level=0)=0;
|
|
||||||
virtual void prtout_cpp(PtrFunction f,IStructuredTextTarget *,int level=0)=0;
|
|
||||||
virtual size_t getFuncCount()=0;
|
|
||||||
virtual const lFunction &validFunctions() const =0;
|
virtual const lFunction &validFunctions() const =0;
|
||||||
virtual QDir installDir()=0;
|
virtual QDir installDir()=0;
|
||||||
virtual QDir dataDir(QString kind)=0;
|
virtual QDir dataDir(QString kind)=0;
|
||||||
|
|||||||
@ -175,7 +175,7 @@ struct AssignType : public HlTypeSupport
|
|||||||
protected:
|
protected:
|
||||||
public:
|
public:
|
||||||
Expr *m_lhs;
|
Expr *m_lhs;
|
||||||
Expr *rhs;
|
Expr *m_rhs;
|
||||||
AssignType() {}
|
AssignType() {}
|
||||||
Expr *lhs() const {return m_lhs;}
|
Expr *lhs() const {return m_lhs;}
|
||||||
void lhs(Expr *l);
|
void lhs(Expr *l);
|
||||||
@ -262,7 +262,7 @@ struct LLOperand
|
|||||||
bool is_offset; // set by jumps
|
bool is_offset; // set by jumps
|
||||||
bool is_compound;
|
bool is_compound;
|
||||||
size_t width;
|
size_t width;
|
||||||
//union {/* Source operand if (flg & I) */
|
/* Source operand if (flg & I) */
|
||||||
struct { /* Call & # actual arg bytes */
|
struct { /* Call & # actual arg bytes */
|
||||||
Function *proc; /* pointer to target proc (for CALL(F))*/
|
Function *proc; /* pointer to target proc (for CALL(F))*/
|
||||||
int cb; /* # actual arg bytes */
|
int cb; /* # actual arg bytes */
|
||||||
@ -339,20 +339,12 @@ public:
|
|||||||
}
|
}
|
||||||
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
|
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
|
||||||
void setFlags(uint32_t flag) {flg |= flag;}
|
void setFlags(uint32_t flag) {flg |= flag;}
|
||||||
void clrFlags(uint32_t flag)
|
void clrFlags(uint32_t flag);
|
||||||
{
|
|
||||||
if(getOpcode()==iMOD)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
flg &= ~flag;
|
|
||||||
}
|
|
||||||
uint32_t getFlag() const {return flg;}
|
uint32_t getFlag() const {return flg;}
|
||||||
uint32_t GetLlLabel() const { return label;}
|
uint32_t GetLlLabel() const { return label;}
|
||||||
|
|
||||||
void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);}
|
void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);}
|
||||||
|
|
||||||
|
|
||||||
bool match(llIcode op)
|
bool match(llIcode op)
|
||||||
{
|
{
|
||||||
return (getOpcode()==op);
|
return (getOpcode()==op);
|
||||||
@ -363,19 +355,19 @@ public:
|
|||||||
}
|
}
|
||||||
bool match(llIcode op,eReg dest)
|
bool match(llIcode op,eReg dest)
|
||||||
{
|
{
|
||||||
return (getOpcode()==op)&&m_dst.regi==dest;
|
return (getOpcode()==op) and match(dest);
|
||||||
}
|
}
|
||||||
bool match(llIcode op,eReg dest,uint32_t flgs)
|
bool match(llIcode op,eReg dest,uint32_t flgs)
|
||||||
{
|
{
|
||||||
return (getOpcode()==op) and (m_dst.regi==dest) and testFlags(flgs);
|
return match(op) and match(dest) and testFlags(flgs);
|
||||||
}
|
}
|
||||||
bool match(llIcode op,eReg dest,eReg src_reg)
|
bool match(llIcode op,eReg dest,eReg src_reg)
|
||||||
{
|
{
|
||||||
return (getOpcode()==op) and (m_dst.regi==dest) and (m_src.regi==src_reg);
|
return match(op) and match(dest) and (m_src.regi==src_reg);
|
||||||
}
|
}
|
||||||
bool match(eReg dest,eReg src_reg)
|
bool match(eReg dest,eReg src_reg)
|
||||||
{
|
{
|
||||||
return (m_dst.regi==dest) and (m_src.regi==src_reg);
|
return match(dest) and (m_src.regi==src_reg);
|
||||||
}
|
}
|
||||||
bool match(eReg dest)
|
bool match(eReg dest)
|
||||||
{
|
{
|
||||||
@ -383,7 +375,7 @@ public:
|
|||||||
}
|
}
|
||||||
bool match(llIcode op,uint32_t flgs)
|
bool match(llIcode op,uint32_t flgs)
|
||||||
{
|
{
|
||||||
return (getOpcode()==op) and testFlags(flgs);
|
return match(op) and testFlags(flgs);
|
||||||
}
|
}
|
||||||
void set(llIcode op,uint32_t flags)
|
void set(llIcode op,uint32_t flags)
|
||||||
{
|
{
|
||||||
@ -418,30 +410,15 @@ public:
|
|||||||
}
|
}
|
||||||
const LLOperand & src() const { return m_src; }
|
const LLOperand & src() const { return m_src; }
|
||||||
LLOperand & src() { return m_src; }
|
LLOperand & src() { return m_src; }
|
||||||
void replaceSrc(const LLOperand &with)
|
void replaceSrc(const LLOperand &with) { m_src = with; }
|
||||||
{
|
void replaceSrc(eReg r) { m_src = LLOperand::CreateReg2(r); }
|
||||||
m_src = with;
|
void replaceSrc(int64_t r) { m_src = LLOperand::CreateImm2(r); }
|
||||||
}
|
void replaceDst(const LLOperand &with) { m_dst = with; }
|
||||||
void replaceSrc(eReg r)
|
|
||||||
{
|
|
||||||
m_src = LLOperand::CreateReg2(r);
|
|
||||||
}
|
|
||||||
void replaceSrc(int64_t r)
|
|
||||||
{
|
|
||||||
m_src = LLOperand::CreateImm2(r);
|
|
||||||
}
|
|
||||||
void replaceDst(const LLOperand &with)
|
|
||||||
{
|
|
||||||
m_dst = with;
|
|
||||||
}
|
|
||||||
// void replaceDst(eReg r)
|
|
||||||
// {
|
|
||||||
// dst = LLOperand::CreateReg2(r);
|
|
||||||
// }
|
|
||||||
ICODE *m_link;
|
|
||||||
condId idType(opLoc sd) const;
|
condId idType(opLoc sd) const;
|
||||||
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &m_dst; }
|
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &m_dst; }
|
||||||
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &m_dst; }
|
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &m_dst; }
|
||||||
|
|
||||||
|
ICODE * m_link;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */
|
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */
|
||||||
|
|||||||
@ -158,6 +158,7 @@ public slots:
|
|||||||
void onCommandStreamFinished(bool state);
|
void onCommandStreamFinished(bool state);
|
||||||
signals:
|
signals:
|
||||||
void newFunctionCreated(PtrFunction);
|
void newFunctionCreated(PtrFunction);
|
||||||
|
void functionUpdate(const PtrFunction &);
|
||||||
void loaderSelected();
|
void loaderSelected();
|
||||||
void commandListChanged();
|
void commandListChanged();
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@ -578,7 +578,7 @@ void LOCAL_ID::forwardSubs (Expr *lhs, Expr *rhs, iICODE picode, iICODE ticode,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Insert on rhs of ticode, if possible */
|
/* Insert on rhs of ticode, if possible */
|
||||||
res = Expr::insertSubTreeReg (ticode->hlU()->asgn.rhs,rhs, id_arr[lhs_reg->regiIdx].id.regi, this);
|
res = Expr::insertSubTreeReg (ticode->hlU()->asgn.m_rhs,rhs, id_arr[lhs_reg->regiIdx].id.regi, this);
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
picode->invalidate();
|
picode->invalidate();
|
||||||
@ -617,7 +617,7 @@ static void forwardSubsLong (int longIdx, Expr *_exp, iICODE picode, iICODE tico
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Insert on rhs of ticode, if possible */
|
/* Insert on rhs of ticode, if possible */
|
||||||
res = Expr::insertSubTreeLongReg (_exp, ticode->hlU()->asgn.rhs, longIdx);
|
res = Expr::insertSubTreeLongReg (_exp, ticode->hlU()->asgn.m_rhs, longIdx);
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
picode->invalidate();
|
picode->invalidate();
|
||||||
@ -758,11 +758,11 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
|
|||||||
if(isLong)
|
if(isLong)
|
||||||
{
|
{
|
||||||
forwardSubsLong (lhs_ident->ident.idNode.longIdx,
|
forwardSubsLong (lhs_ident->ident.idNode.longIdx,
|
||||||
p_hl.asgn.rhs, picode,ticode,
|
p_hl.asgn.m_rhs, picode,ticode,
|
||||||
&numHlIcodes);
|
&numHlIcodes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
this->forwardSubs (lhs_ident, p_hl.asgn.rhs, picode, ticode, numHlIcodes);
|
this->forwardSubs (lhs_ident, p_hl.asgn.m_rhs, picode, ticode, numHlIcodes);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HLI_JCOND: case HLI_PUSH: case HLI_RET:
|
case HLI_JCOND: case HLI_PUSH: case HLI_RET:
|
||||||
@ -770,7 +770,7 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
|
|||||||
{
|
{
|
||||||
assert(lhs_ident);
|
assert(lhs_ident);
|
||||||
res = Expr::insertSubTreeLongReg (
|
res = Expr::insertSubTreeLongReg (
|
||||||
p_hl.asgn.rhs,
|
p_hl.asgn.m_rhs,
|
||||||
t_hl.exp.v,
|
t_hl.exp.v,
|
||||||
lhs_ident->ident.idNode.longIdx);
|
lhs_ident->ident.idNode.longIdx);
|
||||||
}
|
}
|
||||||
@ -780,7 +780,7 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
|
|||||||
assert(lhs_reg);
|
assert(lhs_reg);
|
||||||
res = Expr::insertSubTreeReg (
|
res = Expr::insertSubTreeReg (
|
||||||
t_hl.exp.v,
|
t_hl.exp.v,
|
||||||
p_hl.asgn.rhs,
|
p_hl.asgn.m_rhs,
|
||||||
id_arr[lhs_reg->regiIdx].id.regi,
|
id_arr[lhs_reg->regiIdx].id.regi,
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
@ -914,7 +914,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
|||||||
(ticode->hl()->opcode != HLI_RET)))
|
(ticode->hl()->opcode != HLI_RET)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (_icHl.asgn.rhs->xClear (make_iterator_range(picode.base(),picode->du1.idx[0].uses[0]),
|
if (_icHl.asgn.m_rhs->xClear (make_iterator_range(picode.base(),picode->du1.idx[0].uses[0]),
|
||||||
end(), locals))
|
end(), locals))
|
||||||
{
|
{
|
||||||
locals.processTargetIcode(picode.base(), numHlIcodes, ticode,false);
|
locals.processTargetIcode(picode.base(), numHlIcodes, ticode,false);
|
||||||
@ -973,9 +973,9 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
|||||||
switch (ti_hl->opcode)
|
switch (ti_hl->opcode)
|
||||||
{
|
{
|
||||||
case HLI_ASSIGN:
|
case HLI_ASSIGN:
|
||||||
assert(ti_hl->asgn.rhs);
|
assert(ti_hl->asgn.m_rhs);
|
||||||
_exp = _icHl.call.toAst();
|
_exp = _icHl.call.toAst();
|
||||||
res = Expr::insertSubTreeReg (ti_hl->asgn.rhs,_exp, _retVal->id.regi, &locals);
|
res = Expr::insertSubTreeReg (ti_hl->asgn.m_rhs,_exp, _retVal->id.regi, &locals);
|
||||||
if (not res)
|
if (not res)
|
||||||
Expr::insertSubTreeReg (ti_hl->asgn.m_lhs, _exp,_retVal->id.regi, &locals);
|
Expr::insertSubTreeReg (ti_hl->asgn.m_lhs, _exp,_retVal->id.regi, &locals);
|
||||||
//TODO: HERE missing: 2 regs
|
//TODO: HERE missing: 2 regs
|
||||||
@ -1023,8 +1023,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
|||||||
switch (_icHl.opcode)
|
switch (_icHl.opcode)
|
||||||
{
|
{
|
||||||
case HLI_ASSIGN:
|
case HLI_ASSIGN:
|
||||||
/* Replace rhs of current icode into target
|
/* Replace rhs of current icode into target icode expression */
|
||||||
* icode expression */
|
|
||||||
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
|
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
|
||||||
{
|
{
|
||||||
ticode = picode->du1.idx[0].uses.front();
|
ticode = picode->du1.idx[0].uses.front();
|
||||||
@ -1048,10 +1047,11 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
|||||||
_exp = g_exp_stk.pop(); /* pop last exp pushed */
|
_exp = g_exp_stk.pop(); /* pop last exp pushed */
|
||||||
switch (ticode->hl()->opcode) {
|
switch (ticode->hl()->opcode) {
|
||||||
case HLI_ASSIGN:
|
case HLI_ASSIGN:
|
||||||
forwardSubsLong (dynamic_cast<AstIdent *>(_icHl.expr())->ident.idNode.longIdx,
|
forwardSubsLong (static_cast<AstIdent *>(_icHl.expr())->ident.idNode.longIdx,
|
||||||
_exp, picode.base(), ticode, &numHlIcodes);
|
_exp, picode.base(), ticode, &numHlIcodes);
|
||||||
break;
|
break;
|
||||||
case HLI_JCOND: case HLI_PUSH:
|
case HLI_JCOND:
|
||||||
|
case HLI_PUSH:
|
||||||
res = Expr::insertSubTreeLongReg (_exp,
|
res = Expr::insertSubTreeLongReg (_exp,
|
||||||
ticode->hlU()->exp.v,
|
ticode->hlU()->exp.v,
|
||||||
dynamic_cast<AstIdent *>(_icHl.asgn.lhs())->ident.idNode.longIdx);
|
dynamic_cast<AstIdent *>(_icHl.asgn.lhs())->ident.idNode.longIdx);
|
||||||
@ -1079,7 +1079,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
|||||||
AstIdent::Long(&locals, DST,
|
AstIdent::Long(&locals, DST,
|
||||||
ticode,HIGH_FIRST, picode.base(),
|
ticode,HIGH_FIRST, picode.base(),
|
||||||
eDEF, *(++iICODE(ticode))->ll()));
|
eDEF, *(++iICODE(ticode))->ll()));
|
||||||
ticode->hlU()->asgn.rhs = _exp;
|
ticode->hlU()->asgn.m_rhs = _exp;
|
||||||
picode->invalidate();
|
picode->invalidate();
|
||||||
numHlIcodes--;
|
numHlIcodes--;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -5,53 +5,12 @@ struct DccImpl : public IDcc {
|
|||||||
PtrFunction m_current_func;
|
PtrFunction m_current_func;
|
||||||
// IDcc interface
|
// IDcc interface
|
||||||
public:
|
public:
|
||||||
void BaseInit()
|
|
||||||
{
|
|
||||||
m_current_func = nullptr;
|
|
||||||
}
|
|
||||||
void Init(QObject *tgt)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
PtrFunction GetCurFuncHandle() {
|
|
||||||
return m_current_func;
|
|
||||||
}
|
|
||||||
void analysis_Once()
|
|
||||||
{
|
|
||||||
if(m_current_func==nullptr)
|
|
||||||
return;
|
|
||||||
if(m_current_func->nStep==0) { // unscanned function
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool load(QString name)
|
bool load(QString name)
|
||||||
{
|
{
|
||||||
option.filename = name;
|
option.filename = name;
|
||||||
Project::get()->create(name);
|
Project::get()->create(name);
|
||||||
return Project::get()->addLoadCommands(name);
|
return Project::get()->addLoadCommands(name);
|
||||||
}
|
}
|
||||||
void prtout_asm(PtrFunction f,IStructuredTextTarget *tgt, int level) override
|
|
||||||
{
|
|
||||||
// if (m_current_func->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);
|
|
||||||
f->toStructuredText(tgt,level);
|
|
||||||
}
|
|
||||||
void prtout_cpp(PtrFunction f,IStructuredTextTarget *, int level) override
|
|
||||||
{
|
|
||||||
}
|
|
||||||
bool isValidFuncHandle(ilFunction f) {
|
|
||||||
return f != Project::get()->functions().end();
|
|
||||||
}
|
|
||||||
size_t getFuncCount()
|
|
||||||
{
|
|
||||||
return Project::get()->functions().size();
|
|
||||||
}
|
|
||||||
const lFunction &validFunctions() const
|
|
||||||
{
|
|
||||||
return Project::get()->functions();
|
|
||||||
}
|
|
||||||
void SetCurFunc_by_Name(QString v)
|
void SetCurFunc_by_Name(QString v)
|
||||||
{
|
{
|
||||||
PtrFunction p(Project::get()->findByName(v));
|
PtrFunction p(Project::get()->findByName(v));
|
||||||
|
|||||||
@ -828,7 +828,7 @@ void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
|
|||||||
const LLInst &inst(*insn);
|
const LLInst &inst(*insn);
|
||||||
QString opcode = Machine_X86::opcodeName(insn->getOpcode());
|
QString opcode = Machine_X86::opcodeName(insn->getOpcode());
|
||||||
out->addSpace(4);
|
out->addSpace(4);
|
||||||
out->addTaggedString(XT_Number,strHex(insn->label));
|
out->addTaggedString(XT_Number,QString("%1").arg(insn->label,8,16,QChar('0').toUpper()));
|
||||||
out->addSpace(4);
|
out->addSpace(4);
|
||||||
out->addTaggedString(XT_Keyword,Machine_X86::opcodeName(insn->getOpcode()),insn);
|
out->addTaggedString(XT_Keyword,Machine_X86::opcodeName(insn->getOpcode()),insn);
|
||||||
out->addSpace(2);
|
out->addSpace(2);
|
||||||
@ -905,17 +905,12 @@ void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
|
|||||||
}
|
}
|
||||||
else if (inst.testFlags(I) )
|
else if (inst.testFlags(I) )
|
||||||
{
|
{
|
||||||
out->addTaggedString(XT_AsmLabel,strHex(inst.src().getImm2()));
|
int64_t tgt_addr = inst.src().getImm2();
|
||||||
// j = inst.src().getImm2();
|
if (inst.getOpcode() == iJMPF)
|
||||||
// if (pl.count(j)==0) /* Forward jump */
|
{
|
||||||
// {
|
out->addTaggedString(XT_Keyword," far ptr ");
|
||||||
// pl[j] = ++g_lab;
|
}
|
||||||
// }
|
out->addTaggedString(XT_AsmLabel,QString("L_%1").arg(strHex(tgt_addr)));
|
||||||
// if (inst.getOpcode() == iJMPF)
|
|
||||||
// {
|
|
||||||
// operands_s<<" far ptr ";
|
|
||||||
// }
|
|
||||||
// operands_s<<"L"<<pl[j];
|
|
||||||
}
|
}
|
||||||
else if (inst.getOpcode() == iJMPF)
|
else if (inst.getOpcode() == iJMPF)
|
||||||
{
|
{
|
||||||
@ -928,6 +923,36 @@ void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
case iCALL: case iCALLF:
|
||||||
|
if (inst.testFlags(I))
|
||||||
|
{
|
||||||
|
out->addTaggedString(XT_Keyword,QString("%1 ptr ").arg((inst.getOpcode() == iCALL) ? "near" : "far"));
|
||||||
|
out->addTaggedString(XT_AsmLabel,(inst.src().proc.proc)->name);
|
||||||
|
}
|
||||||
|
else if (inst.getOpcode() == iCALLF)
|
||||||
|
{
|
||||||
|
out->addTaggedString(XT_Keyword,"dword ptr ");
|
||||||
|
strSrc(out,insn,true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strDst(out,I,inst.src());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case iENTER:
|
||||||
|
out->addTaggedString(XT_AsmOffset,strHex(inst.m_dst.off));
|
||||||
|
out->prtt(", ");
|
||||||
|
out->addTaggedString(XT_AsmOffset,strHex(inst.src().getImm2()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case iRET:
|
||||||
|
case iRETF:
|
||||||
|
case iINT:
|
||||||
|
if (inst.testFlags(I))
|
||||||
|
{
|
||||||
|
out->addTaggedString(XT_Number,strHex(inst.src().getImm2()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
out->addEOL();
|
out->addEOL();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -399,7 +399,8 @@ void Function::highLevelGen()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iMOV: pIcode->setAsgn(lhs, rhs);
|
case iMOV:
|
||||||
|
pIcode->setAsgn(lhs, rhs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iMUL:
|
case iMUL:
|
||||||
@ -432,7 +433,8 @@ void Function::highLevelGen()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case iRET:
|
case iRET:
|
||||||
case iRETF: pIcode->setUnary(HLI_RET, nullptr);
|
case iRETF:
|
||||||
|
pIcode->setUnary(HLI_RET, nullptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iSHL:
|
case iSHL:
|
||||||
@ -461,6 +463,8 @@ void Function::highLevelGen()
|
|||||||
rhs = new BinaryOperator(XOR,lhs, rhs);
|
rhs = new BinaryOperator(XOR,lhs, rhs);
|
||||||
pIcode->setAsgn(lhs, rhs);
|
pIcode->setAsgn(lhs, rhs);
|
||||||
break;
|
break;
|
||||||
|
//TODO: default: // mostly to silence static analyzer warnings ?
|
||||||
|
// delete rhs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,7 +536,7 @@ QString AssignType::writeOut(Function *pProc, int *numLoc) const
|
|||||||
{
|
{
|
||||||
return QString("%1 = %2;\n")
|
return QString("%1 = %2;\n")
|
||||||
.arg(m_lhs->walkCondExpr (pProc, numLoc))
|
.arg(m_lhs->walkCondExpr (pProc, numLoc))
|
||||||
.arg(rhs->walkCondExpr (pProc, numLoc));
|
.arg(m_rhs->walkCondExpr (pProc, numLoc));
|
||||||
}
|
}
|
||||||
QString CallType::writeOut(Function *pProc, int *numLoc) const
|
QString CallType::writeOut(Function *pProc, int *numLoc) const
|
||||||
{
|
{
|
||||||
@ -553,7 +557,7 @@ void HLTYPE::set(Expr *l, Expr *r)
|
|||||||
//assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
|
//assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
|
||||||
assert(dynamic_cast<UnaryOperator *>(l));
|
assert(dynamic_cast<UnaryOperator *>(l));
|
||||||
asgn.m_lhs=l;
|
asgn.m_lhs=l;
|
||||||
asgn.rhs=r;
|
asgn.m_rhs=r;
|
||||||
}
|
}
|
||||||
/* Returns a string with the contents of the current high-level icode.
|
/* Returns a string with the contents of the current high-level icode.
|
||||||
* Note: this routine does not output the contens of HLI_JCOND icodes. This is
|
* Note: this routine does not output the contens of HLI_JCOND icodes. This is
|
||||||
|
|||||||
@ -67,6 +67,15 @@ extern bundle cCode;
|
|||||||
* is created and a goto is also emitted.
|
* is created and a goto is also emitted.
|
||||||
* Note: this procedure is to be used when the label is to be backpatched
|
* Note: this procedure is to be used when the label is to be backpatched
|
||||||
* onto code in cCode.code */
|
* onto code in cCode.code */
|
||||||
|
void LLInst::clrFlags(uint32_t flag)
|
||||||
|
{
|
||||||
|
if(getOpcode()==iMOD)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
flg &= ~flag;
|
||||||
|
}
|
||||||
|
|
||||||
void LLInst::emitGotoLabel (int indLevel)
|
void LLInst::emitGotoLabel (int indLevel)
|
||||||
{
|
{
|
||||||
if ( not testFlags(HLL_LABEL) ) /* node hasn't got a lab */
|
if ( not testFlags(HLL_LABEL) ) /* node hasn't got a lab */
|
||||||
|
|||||||
@ -198,7 +198,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
|||||||
pstate->JCond.immed++;
|
pstate->JCond.immed++;
|
||||||
if (ll->getOpcode() == iJAE or ll->getOpcode() == iJA)
|
if (ll->getOpcode() == iJAE or ll->getOpcode() == iJA)
|
||||||
pstate->JCond.regi = prev.ll()->m_dst.regi;
|
pstate->JCond.regi = prev.ll()->m_dst.regi;
|
||||||
fBranch = (bool) (ll->getOpcode() == iJB or ll->getOpcode() == iJBE);
|
fBranch = (ll->getOpcode() == iJB or ll->getOpcode() == iJBE);
|
||||||
}
|
}
|
||||||
StCopy = *pstate;
|
StCopy = *pstate;
|
||||||
|
|
||||||
@ -212,8 +212,10 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
|||||||
/* Next icode. Note: not the same as GetLastIcode() because of the call
|
/* Next icode. Note: not the same as GetLastIcode() because of the call
|
||||||
to FollowCtrl() */
|
to FollowCtrl() */
|
||||||
pIcode = Icode.GetIcode(ip);
|
pIcode = Icode.GetIcode(ip);
|
||||||
} /* Fall through to do the jump path */
|
/* do the jump path */
|
||||||
|
done = process_JMP (*pIcode, pstate, pcallGraph);
|
||||||
|
break;
|
||||||
|
}
|
||||||
/*** Jumps ***/
|
/*** Jumps ***/
|
||||||
case iJMP:
|
case iJMP:
|
||||||
case iJMPF: /* Returns true if we've run into a loop */
|
case iJMPF: /* Returns true if we've run into a loop */
|
||||||
@ -232,7 +234,9 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
|||||||
case iRET:
|
case iRET:
|
||||||
case iRETF:
|
case iRETF:
|
||||||
this->flg |= (ll->getOpcode() == iRET)? PROC_NEAR:PROC_FAR;
|
this->flg |= (ll->getOpcode() == iRET)? PROC_NEAR:PROC_FAR;
|
||||||
/* Fall through */
|
this->flg &= ~TERMINATES;
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
case iIRET:
|
case iIRET:
|
||||||
this->flg &= ~TERMINATES;
|
this->flg &= ~TERMINATES;
|
||||||
done = true;
|
done = true;
|
||||||
@ -868,7 +872,7 @@ static void process_MOV(LLInst & ll, STATE * pstate)
|
|||||||
pstate->setMemoryByte(psym->label,(uint8_t)pstate->r[srcReg]);
|
pstate->setMemoryByte(psym->label,(uint8_t)pstate->r[srcReg]);
|
||||||
if(psym->size>1)
|
if(psym->size>1)
|
||||||
{
|
{
|
||||||
pstate->setMemoryByte(psym->label,(uint8_t)pstate->r[srcReg]>>8);
|
pstate->setMemoryByte(psym->label,uint8_t(pstate->r[srcReg]>>8));
|
||||||
//prog.image()[psym->label+1] = (uint8_t)(pstate->r[srcReg] >> 8);
|
//prog.image()[psym->label+1] = (uint8_t)(pstate->r[srcReg] >> 8);
|
||||||
}
|
}
|
||||||
psym->duVal.setFlags(eDuVal::DEF);
|
psym->duVal.setFlags(eDuVal::DEF);
|
||||||
@ -1276,7 +1280,9 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
|
|||||||
use(SRC, pIcode, this, pstate, cb);
|
use(SRC, pIcode, this, pstate, cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iLOOP: case iLOOPE: case iLOOPNE:
|
case iLOOP:
|
||||||
|
case iLOOPE:
|
||||||
|
case iLOOPNE:
|
||||||
pIcode.du.def.addReg(rCX);
|
pIcode.du.def.addReg(rCX);
|
||||||
pIcode.du1.addDef(rCX);
|
pIcode.du1.addDef(rCX);
|
||||||
case iJCXZ:
|
case iJCXZ:
|
||||||
@ -1331,7 +1337,8 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
|
|||||||
pIcode.du.use.addReg(rDX).addReg(sseg);
|
pIcode.du.use.addReg(rDX).addReg(sseg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iIN: case iOUT:
|
case iIN:
|
||||||
|
case iOUT:
|
||||||
def(DST, pIcode, this, pstate, cb);
|
def(DST, pIcode, this, pstate, cb);
|
||||||
if (not Imm)
|
if (not Imm)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -187,7 +187,7 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
|
|||||||
/* Do ps (actual arguments) */
|
/* Do ps (actual arguments) */
|
||||||
STKSYM newsym;
|
STKSYM newsym;
|
||||||
newsym.setArgName(call_args_stackframe->size());
|
newsym.setArgName(call_args_stackframe->size());
|
||||||
newsym.actual = picode->hl()->asgn.rhs;
|
newsym.actual = picode->hl()->asgn.m_rhs;
|
||||||
newsym.regs = lhs;
|
newsym.regs = lhs;
|
||||||
/* Mask off high and low register(s) in picode */
|
/* Mask off high and low register(s) in picode */
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|||||||
@ -228,6 +228,7 @@ void Project::processFunctionCommands(const PtrFunction &func,int count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit commandListChanged();
|
emit commandListChanged();
|
||||||
|
emit functionUpdate(func);
|
||||||
}
|
}
|
||||||
void Project::resetCommandsAndErrorState()
|
void Project::resetCommandsAndErrorState()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -630,7 +630,7 @@ static int signex(uint8_t b)
|
|||||||
static void setAddress(int i, bool fdst, uint16_t seg, int16_t reg, uint16_t off)
|
static void setAddress(int i, bool fdst, uint16_t seg, int16_t reg, uint16_t off)
|
||||||
{
|
{
|
||||||
/* If not to register (i.e. to r/m), and talking about r/m, then this is dest */
|
/* If not to register (i.e. to r/m), and talking about r/m, then this is dest */
|
||||||
LLOperand *pm = (! (stateTable[i].flg & TO_REG) == fdst) ? &pIcode->ll()->m_dst : &pIcode->ll()->src();
|
LLOperand *pm = (! bool(stateTable[i].flg & TO_REG) == fdst) ? &pIcode->ll()->m_dst : &pIcode->ll()->src();
|
||||||
|
|
||||||
/* Set segment. A later procedure (lookupAddr in proclist.c) will
|
/* Set segment. A later procedure (lookupAddr in proclist.c) will
|
||||||
* provide the value of this segment in the field segValue.
|
* provide the value of this segment in the field segValue.
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
#include <QtWidgets>
|
#include <QtWidgets>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
IDcc* g_EXE2C = NULL;
|
IDcc* g_IDCC = NULL;
|
||||||
extern bool exe2c_Init();
|
extern bool exe2c_Init();
|
||||||
|
|
||||||
DccMainWindow::DccMainWindow(QWidget *parent) :
|
DccMainWindow::DccMainWindow(QWidget *parent) :
|
||||||
@ -22,9 +22,9 @@ DccMainWindow::DccMainWindow(QWidget *parent) :
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->statusbar->addPermanentWidget(new QLabel("Test"));
|
ui->statusbar->addPermanentWidget(new QLabel("Test"));
|
||||||
|
|
||||||
g_EXE2C = IDcc::get();
|
g_IDCC = IDcc::get();
|
||||||
g_EXE2C->BaseInit();
|
g_IDCC->BaseInit();
|
||||||
g_EXE2C->Init(this);
|
g_IDCC->Init(this);
|
||||||
|
|
||||||
m_last_display = nullptr;
|
m_last_display = nullptr;
|
||||||
m_command_queue = new CommandQueueView(this);
|
m_command_queue = new CommandQueueView(this);
|
||||||
@ -36,20 +36,12 @@ DccMainWindow::DccMainWindow(QWidget *parent) :
|
|||||||
// we are beeing signalled when display is requested
|
// we are beeing signalled when display is requested
|
||||||
connect(this,SIGNAL(functionListChanged()), m_functionlist_widget->model(),SLOT(updateFunctionList()));
|
connect(this,SIGNAL(functionListChanged()), m_functionlist_widget->model(),SLOT(updateFunctionList()));
|
||||||
connect(Project::get(),SIGNAL(newFunctionCreated(PtrFunction)),SLOT(onNewFunction(PtrFunction)));
|
connect(Project::get(),SIGNAL(newFunctionCreated(PtrFunction)),SLOT(onNewFunction(PtrFunction)));
|
||||||
|
connect(Project::get(),SIGNAL(functionUpdate(const PtrFunction &)),SLOT(onFunctionUpdated(const PtrFunction &)));
|
||||||
|
|
||||||
this->addDockWidget(Qt::RightDockWidgetArea,m_functionlist_widget);
|
this->addDockWidget(Qt::RightDockWidgetArea,m_functionlist_widget);
|
||||||
this->addDockWidget(Qt::LeftDockWidgetArea,m_command_queue);
|
this->addDockWidget(Qt::LeftDockWidgetArea,m_command_queue);
|
||||||
connect(m_functionlist_widget,&FunctionListDockWidget::selectFunction,
|
connect(m_functionlist_widget,&FunctionListDockWidget::selectFunction,
|
||||||
m_command_queue, &CommandQueueView::onCurrentFunctionChanged);
|
m_command_queue, &CommandQueueView::onCurrentFunctionChanged);
|
||||||
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()
|
DccMainWindow::~DccMainWindow()
|
||||||
@ -71,13 +63,22 @@ void DccMainWindow::changeEvent(QEvent *e)
|
|||||||
void DccMainWindow::onFunctionSelected(PtrFunction func) {
|
void DccMainWindow::onFunctionSelected(PtrFunction func) {
|
||||||
m_selected_func = func;
|
m_selected_func = func;
|
||||||
}
|
}
|
||||||
|
// TODO: consider increasing granularity of change events to reduce redraw/refresh spam
|
||||||
|
void DccMainWindow::onFunctionUpdated(const PtrFunction &f) {
|
||||||
|
// some function was updated refresh the list and the view if open
|
||||||
|
auto iter = m_map_function_to_view.find(f);
|
||||||
|
if(iter!=m_map_function_to_view.end()) {
|
||||||
|
iter->second->renderCurrent();
|
||||||
|
}
|
||||||
|
emit functionListChanged();
|
||||||
|
}
|
||||||
void DccMainWindow::onNewFunction(PtrFunction f) {
|
void DccMainWindow::onNewFunction(PtrFunction f) {
|
||||||
emit functionListChanged();
|
emit functionListChanged();
|
||||||
}
|
}
|
||||||
void DccMainWindow::onOptim()
|
void DccMainWindow::onOptim()
|
||||||
{
|
{
|
||||||
Project::get()->processCommands();
|
Project::get()->processCommands();
|
||||||
g_EXE2C->analysis_Once();
|
g_IDCC->analysis_Once();
|
||||||
emit functionListChanged();
|
emit functionListChanged();
|
||||||
if(m_last_display==m_selected_func)
|
if(m_last_display==m_selected_func)
|
||||||
{
|
{
|
||||||
@ -87,7 +88,7 @@ void DccMainWindow::onOptim()
|
|||||||
void DccMainWindow::onOptim10()
|
void DccMainWindow::onOptim10()
|
||||||
{
|
{
|
||||||
for(int i=0; i<10; i++)
|
for(int i=0; i<10; i++)
|
||||||
g_EXE2C->analysis_Once();
|
g_IDCC->analysis_Once();
|
||||||
emit functionListChanged();
|
emit functionListChanged();
|
||||||
if(m_last_display==m_selected_func)
|
if(m_last_display==m_selected_func)
|
||||||
{
|
{
|
||||||
@ -101,20 +102,43 @@ void DccMainWindow::onOpenFile_Action()
|
|||||||
tr("Select DOS executable"),
|
tr("Select DOS executable"),
|
||||||
".",
|
".",
|
||||||
tr("Executable files (*.exe *.EXE *.com *.COM)"));
|
tr("Executable files (*.exe *.EXE *.com *.COM)"));
|
||||||
if(!g_EXE2C->load(name)) {
|
if(!g_IDCC->load(name)) {
|
||||||
QMessageBox::critical(this,tr("Error"),QString(tr("Cannot open file %1")).arg(name));
|
QMessageBox::critical(this,tr("Error"),QString(tr("Cannot open file %1")).arg(name));
|
||||||
}
|
}
|
||||||
//bool m_bSucc = m_xTextBuffer.LoadFromFile(lpszPathName);
|
//bool m_bSucc = m_xTextBuffer.LoadFromFile(lpszPathName);
|
||||||
emit functionListChanged();
|
emit functionListChanged();
|
||||||
}
|
}
|
||||||
|
void DccMainWindow::functionViewClosed() {
|
||||||
|
FunctionViewWidget *sndr = qobject_cast<FunctionViewWidget *>(sender());
|
||||||
|
for(auto iter = m_mdi_function_views.begin(); iter!=m_mdi_function_views.end(); ++iter) {
|
||||||
|
if(*iter==sndr) {
|
||||||
|
m_map_function_to_view.erase(sndr->viewedFunction());
|
||||||
|
m_mdi_function_views.erase(iter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui->mdiArea->removeSubWindow(sndr);
|
||||||
|
sndr->deleteLater();
|
||||||
|
|
||||||
|
}
|
||||||
void DccMainWindow::displayCurrentFunction()
|
void DccMainWindow::displayCurrentFunction()
|
||||||
{
|
{
|
||||||
if(m_last_display!=m_selected_func)
|
if(m_last_display!=m_selected_func) {
|
||||||
m_last_display=m_selected_func;
|
m_last_display=m_selected_func;
|
||||||
g_EXE2C->prtout_asm(m_last_display, m_asm_view);
|
// Check if function's view is already open, if it is, acivate it
|
||||||
//g_EXE2C->prtout_itn(m_internal_view);
|
auto iter = m_map_function_to_view.find(m_selected_func);
|
||||||
g_EXE2C->prtout_cpp(m_last_display,m_c_view);
|
if(iter!=m_map_function_to_view.end()) {
|
||||||
|
ui->mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(iter->second->parent()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FunctionViewWidget *view = new FunctionViewWidget(m_selected_func,this);
|
||||||
|
view->setWindowTitle(QString(tr("Listing for %1")).arg(m_selected_func->name));
|
||||||
|
connect(view,SIGNAL(close()),SLOT(functionViewClosed()));
|
||||||
|
ui->mdiArea->addSubWindow(view);
|
||||||
|
view->show();
|
||||||
|
m_mdi_function_views.push_back(view);
|
||||||
|
m_map_function_to_view[m_selected_func] = view;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void DccMainWindow::prt_log(const char *v)
|
void DccMainWindow::prt_log(const char *v)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
class FunctionViewWidget;
|
class FunctionViewWidget;
|
||||||
class FunctionListDockWidget;
|
class FunctionListDockWidget;
|
||||||
@ -36,11 +37,12 @@ private slots:
|
|||||||
void on_actionExit_triggered();
|
void on_actionExit_triggered();
|
||||||
void onNewFunction(PtrFunction f);
|
void onNewFunction(PtrFunction f);
|
||||||
void onFunctionSelected(PtrFunction func);
|
void onFunctionSelected(PtrFunction func);
|
||||||
|
void functionViewClosed();
|
||||||
|
void onFunctionUpdated(const PtrFunction & f);
|
||||||
private:
|
private:
|
||||||
|
std::vector<FunctionViewWidget *> m_mdi_function_views;
|
||||||
FunctionViewWidget *m_asm_view;
|
std::unordered_map<PtrFunction,FunctionViewWidget *> m_map_function_to_view;
|
||||||
// FunctionViewWidget *m_internal_view;
|
// FunctionViewWidget *m_internal_view;
|
||||||
FunctionViewWidget *m_c_view;
|
|
||||||
CommandQueueView *m_command_queue;
|
CommandQueueView *m_command_queue;
|
||||||
FunctionListDockWidget *m_functionlist_widget;
|
FunctionListDockWidget *m_functionlist_widget;
|
||||||
Ui::DccMainWindow *ui;
|
Ui::DccMainWindow *ui;
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
//#include "exe2c.h"
|
//#include "exe2c.h"
|
||||||
extern IDcc *g_EXE2C;
|
extern IDcc *g_IDCC;
|
||||||
FunctionListDockWidget::FunctionListDockWidget(QWidget *parent) :
|
FunctionListDockWidget::FunctionListDockWidget(QWidget *parent) :
|
||||||
QDockWidget(parent),
|
QDockWidget(parent),
|
||||||
ui(new Ui::FunctionListDockWidget)
|
ui(new Ui::FunctionListDockWidget)
|
||||||
|
|||||||
@ -1,16 +1,21 @@
|
|||||||
#include <QDebug>
|
|
||||||
#include <QtCore>
|
|
||||||
#include "FunctionViewWidget.h"
|
#include "FunctionViewWidget.h"
|
||||||
#include "ui_FunctionViewWidget.h"
|
#include "ui_FunctionViewWidget.h"
|
||||||
#include "RenderTags.h"
|
#include "RenderTags.h"
|
||||||
|
#include "Procedure.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QtCore>
|
||||||
|
#include "dcc_interface.h"
|
||||||
|
extern IDcc* g_IDCC;
|
||||||
//#include "XMLTYPE.h"
|
//#include "XMLTYPE.h"
|
||||||
FunctionViewWidget::FunctionViewWidget(QWidget *parent) :
|
FunctionViewWidget::FunctionViewWidget(PtrFunction func, QWidget *parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
ui(new Ui::FunctionViewWidget)
|
ui(new Ui::FunctionViewWidget),
|
||||||
|
m_viewed_function(func)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
m_current_rendering = new QTextDocument(ui->textEdit);
|
m_assembly_rendering = new QTextDocument(ui->textEdit);
|
||||||
m_doc_cursor = new QTextCursor(m_current_rendering);
|
m_doc_cursor = new QTextCursor(m_assembly_rendering);
|
||||||
ui->textEdit->setTextBackgroundColor(Qt::black);
|
ui->textEdit->setTextBackgroundColor(Qt::black);
|
||||||
m_current_format = m_doc_cursor->blockFormat();
|
m_current_format = m_doc_cursor->blockFormat();
|
||||||
m_current_format.setNonBreakableLines(true); // each block is single line
|
m_current_format.setNonBreakableLines(true); // each block is single line
|
||||||
@ -25,6 +30,11 @@ FunctionViewWidget::~FunctionViewWidget()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FunctionViewWidget::renderCurrent()
|
||||||
|
{
|
||||||
|
m_viewed_function->toStructuredText(this,0);
|
||||||
|
}
|
||||||
|
|
||||||
void FunctionViewWidget::prtt(const char *s)
|
void FunctionViewWidget::prtt(const char *s)
|
||||||
{
|
{
|
||||||
m_doc_cursor->insertText(s);
|
m_doc_cursor->insertText(s);
|
||||||
@ -50,7 +60,7 @@ void FunctionViewWidget::TAGbegin(TAG_TYPE tag_type, void *p)
|
|||||||
switch(tag_type)
|
switch(tag_type)
|
||||||
{
|
{
|
||||||
case XT_Function:
|
case XT_Function:
|
||||||
m_current_rendering->clear();
|
m_assembly_rendering->clear();
|
||||||
m_chars_format.setForeground(Qt::white);
|
m_chars_format.setForeground(Qt::white);
|
||||||
m_doc_cursor->setBlockFormat(m_current_format);
|
m_doc_cursor->setBlockFormat(m_current_format);
|
||||||
m_doc_cursor->setCharFormat(m_chars_format);
|
m_doc_cursor->setCharFormat(m_chars_format);
|
||||||
@ -79,9 +89,9 @@ void FunctionViewWidget::TAGend(TAG_TYPE tag_type)
|
|||||||
// TODO: What about attributes with spaces?
|
// TODO: What about attributes with spaces?
|
||||||
QFile res("result.html");
|
QFile res("result.html");
|
||||||
res.open(QFile::WriteOnly);
|
res.open(QFile::WriteOnly);
|
||||||
res.write(m_current_rendering->toHtml().toUtf8());
|
res.write(m_assembly_rendering->toHtml().toUtf8());
|
||||||
res.close();
|
res.close();
|
||||||
ui->textEdit->setDocument(m_current_rendering);
|
ui->textEdit->setDocument(m_assembly_rendering);
|
||||||
collected_text.clear();
|
collected_text.clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -100,3 +110,7 @@ void FunctionViewWidget::TAGend(TAG_TYPE tag_type)
|
|||||||
qDebug()<<"Tag end:"<<tag_type;
|
qDebug()<<"Tag end:"<<tag_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void FunctionViewWidget::on_tabWidget_currentChanged(int index)
|
||||||
|
{
|
||||||
|
renderCurrent();
|
||||||
|
}
|
||||||
|
|||||||
@ -4,28 +4,42 @@
|
|||||||
#include "StructuredTextTarget.h"
|
#include "StructuredTextTarget.h"
|
||||||
#include "RenderTags.h"
|
#include "RenderTags.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
#include <QTextBlockFormat>
|
#include <QTextBlockFormat>
|
||||||
//#include "XmlPrt.h"
|
|
||||||
|
class Function;
|
||||||
|
typedef std::shared_ptr<Function> PtrFunction;
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class FunctionViewWidget;
|
class FunctionViewWidget;
|
||||||
}
|
}
|
||||||
|
//TODO: convert 'controllers' of each hex/asm/high-level areas into standalone classes
|
||||||
class FunctionViewWidget : public QWidget,public IStructuredTextTarget
|
class FunctionViewWidget : public QWidget,public IStructuredTextTarget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
QTextDocument *m_current_rendering;
|
PtrFunction m_viewed_function; // 'model' this view is bound to
|
||||||
|
QTextDocument *m_assembly_rendering;
|
||||||
QTextCursor* m_doc_cursor;
|
QTextCursor* m_doc_cursor;
|
||||||
QTextBlockFormat m_current_format;
|
QTextBlockFormat m_current_format;
|
||||||
QTextCharFormat m_chars_format;
|
QTextCharFormat m_chars_format;
|
||||||
public:
|
public:
|
||||||
explicit FunctionViewWidget(QWidget *parent = 0);
|
explicit FunctionViewWidget(PtrFunction func,QWidget *parent = 0);
|
||||||
~FunctionViewWidget();
|
~FunctionViewWidget();
|
||||||
|
const PtrFunction &viewedFunction() const { return m_viewed_function; }
|
||||||
|
void renderCurrent();
|
||||||
|
|
||||||
|
// IStructuredTextTarget interface
|
||||||
void prtt(const char * s);
|
void prtt(const char * s);
|
||||||
void prtt(const QString &s);
|
void prtt(const QString &s);
|
||||||
void addEOL() override;
|
void addEOL() override;
|
||||||
void TAGbegin(enum TAG_TYPE tag_type, void * p);
|
void TAGbegin(enum TAG_TYPE tag_type, void * p);
|
||||||
void TAGend(enum TAG_TYPE tag_type);
|
void TAGend(enum TAG_TYPE tag_type);
|
||||||
|
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_tabWidget_currentChanged(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::FunctionViewWidget *ui;
|
Ui::FunctionViewWidget *ui;
|
||||||
QString collected_text;
|
QString collected_text;
|
||||||
|
|||||||
@ -6,14 +6,51 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>400</width>
|
<width>708</width>
|
||||||
<height>300</height>
|
<height>582</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="binaryTab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Binary</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QTextEdit" name="edtBinary">
|
||||||
|
<property name="undoRedoEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="lineWrapMode">
|
||||||
|
<enum>QTextEdit::NoWrap</enum>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="html">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'Corbel'; font-size:10pt; font-weight:400; font-style:normal;" bgcolor="#000000">
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="assemblyTab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Assembly</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTextEdit" name="textEdit">
|
<widget class="QTextEdit" name="textEdit">
|
||||||
<property name="undoRedoEnabled">
|
<property name="undoRedoEnabled">
|
||||||
@ -36,6 +73,37 @@ p, li { white-space: pre-wrap; }
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="highLevelTab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>High level</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QTextEdit" name="edtHighLevel">
|
||||||
|
<property name="undoRedoEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="lineWrapMode">
|
||||||
|
<enum>QTextEdit::NoWrap</enum>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="html">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'Corbel'; font-size:10pt; font-weight:400; font-style:normal;" bgcolor="#000000">
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user