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 */
|
||||
enum x86_insn_prefix prefix; /* prefixes ORed together */
|
||||
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 */
|
||||
size_t operand_count; /* total number of operands */
|
||||
size_t explicit_count; /* number of explicit operands */
|
||||
|
||||
@ -10,12 +10,7 @@ class IStructuredTextTarget;
|
||||
struct IDcc {
|
||||
static IDcc *get();
|
||||
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 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 QDir installDir()=0;
|
||||
virtual QDir dataDir(QString kind)=0;
|
||||
|
||||
@ -175,7 +175,7 @@ struct AssignType : public HlTypeSupport
|
||||
protected:
|
||||
public:
|
||||
Expr *m_lhs;
|
||||
Expr *rhs;
|
||||
Expr *m_rhs;
|
||||
AssignType() {}
|
||||
Expr *lhs() const {return m_lhs;}
|
||||
void lhs(Expr *l);
|
||||
@ -262,7 +262,7 @@ struct LLOperand
|
||||
bool is_offset; // set by jumps
|
||||
bool is_compound;
|
||||
size_t width;
|
||||
//union {/* Source operand if (flg & I) */
|
||||
/* Source operand if (flg & I) */
|
||||
struct { /* Call & # actual arg bytes */
|
||||
Function *proc; /* pointer to target proc (for CALL(F))*/
|
||||
int cb; /* # actual arg bytes */
|
||||
@ -339,20 +339,12 @@ public:
|
||||
}
|
||||
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
|
||||
void setFlags(uint32_t flag) {flg |= flag;}
|
||||
void clrFlags(uint32_t flag)
|
||||
{
|
||||
if(getOpcode()==iMOD)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
flg &= ~flag;
|
||||
}
|
||||
void clrFlags(uint32_t flag);
|
||||
uint32_t getFlag() const {return flg;}
|
||||
uint32_t GetLlLabel() const { return label;}
|
||||
|
||||
void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);}
|
||||
|
||||
|
||||
bool match(llIcode op)
|
||||
{
|
||||
return (getOpcode()==op);
|
||||
@ -363,19 +355,19 @@ public:
|
||||
}
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return (m_dst.regi==dest) and (m_src.regi==src_reg);
|
||||
return match(dest) and (m_src.regi==src_reg);
|
||||
}
|
||||
bool match(eReg dest)
|
||||
{
|
||||
@ -383,7 +375,7 @@ public:
|
||||
}
|
||||
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)
|
||||
{
|
||||
@ -416,32 +408,17 @@ public:
|
||||
{
|
||||
setOpcode(0);
|
||||
}
|
||||
const LLOperand &src() const {return m_src;}
|
||||
LLOperand &src() {return m_src;}
|
||||
void replaceSrc(const LLOperand &with)
|
||||
{
|
||||
m_src = 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;
|
||||
const LLOperand & src() const { return m_src; }
|
||||
LLOperand & src() { return m_src; }
|
||||
void replaceSrc(const LLOperand &with) { m_src = 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; }
|
||||
condId idType(opLoc sd) const;
|
||||
const LLOperand * get(opLoc sd) const { 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 */
|
||||
|
||||
@ -158,6 +158,7 @@ public slots:
|
||||
void onCommandStreamFinished(bool state);
|
||||
signals:
|
||||
void newFunctionCreated(PtrFunction);
|
||||
void functionUpdate(const PtrFunction &);
|
||||
void loaderSelected();
|
||||
void commandListChanged();
|
||||
protected:
|
||||
|
||||
@ -578,7 +578,7 @@ void LOCAL_ID::forwardSubs (Expr *lhs, Expr *rhs, iICODE picode, iICODE ticode,
|
||||
return;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
picode->invalidate();
|
||||
@ -617,7 +617,7 @@ static void forwardSubsLong (int longIdx, Expr *_exp, iICODE picode, iICODE tico
|
||||
return;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
picode->invalidate();
|
||||
@ -758,11 +758,11 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
|
||||
if(isLong)
|
||||
{
|
||||
forwardSubsLong (lhs_ident->ident.idNode.longIdx,
|
||||
p_hl.asgn.rhs, picode,ticode,
|
||||
p_hl.asgn.m_rhs, picode,ticode,
|
||||
&numHlIcodes);
|
||||
}
|
||||
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;
|
||||
|
||||
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);
|
||||
res = Expr::insertSubTreeLongReg (
|
||||
p_hl.asgn.rhs,
|
||||
p_hl.asgn.m_rhs,
|
||||
t_hl.exp.v,
|
||||
lhs_ident->ident.idNode.longIdx);
|
||||
}
|
||||
@ -780,7 +780,7 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
|
||||
assert(lhs_reg);
|
||||
res = Expr::insertSubTreeReg (
|
||||
t_hl.exp.v,
|
||||
p_hl.asgn.rhs,
|
||||
p_hl.asgn.m_rhs,
|
||||
id_arr[lhs_reg->regiIdx].id.regi,
|
||||
this);
|
||||
}
|
||||
@ -914,7 +914,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
(ticode->hl()->opcode != HLI_RET)))
|
||||
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))
|
||||
{
|
||||
locals.processTargetIcode(picode.base(), numHlIcodes, ticode,false);
|
||||
@ -973,9 +973,9 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
switch (ti_hl->opcode)
|
||||
{
|
||||
case HLI_ASSIGN:
|
||||
assert(ti_hl->asgn.rhs);
|
||||
assert(ti_hl->asgn.m_rhs);
|
||||
_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)
|
||||
Expr::insertSubTreeReg (ti_hl->asgn.m_lhs, _exp,_retVal->id.regi, &locals);
|
||||
//TODO: HERE missing: 2 regs
|
||||
@ -1023,8 +1023,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
|
||||
switch (_icHl.opcode)
|
||||
{
|
||||
case HLI_ASSIGN:
|
||||
/* Replace rhs of current icode into target
|
||||
* icode expression */
|
||||
/* Replace rhs of current icode into target icode expression */
|
||||
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
|
||||
{
|
||||
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 */
|
||||
switch (ticode->hl()->opcode) {
|
||||
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);
|
||||
break;
|
||||
case HLI_JCOND: case HLI_PUSH:
|
||||
case HLI_JCOND:
|
||||
case HLI_PUSH:
|
||||
res = Expr::insertSubTreeLongReg (_exp,
|
||||
ticode->hlU()->exp.v,
|
||||
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,
|
||||
ticode,HIGH_FIRST, picode.base(),
|
||||
eDEF, *(++iICODE(ticode))->ll()));
|
||||
ticode->hlU()->asgn.rhs = _exp;
|
||||
ticode->hlU()->asgn.m_rhs = _exp;
|
||||
picode->invalidate();
|
||||
numHlIcodes--;
|
||||
break;
|
||||
|
||||
@ -5,53 +5,12 @@ struct DccImpl : public IDcc {
|
||||
PtrFunction m_current_func;
|
||||
// IDcc interface
|
||||
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)
|
||||
{
|
||||
option.filename = name;
|
||||
Project::get()->create(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)
|
||||
{
|
||||
PtrFunction p(Project::get()->findByName(v));
|
||||
|
||||
@ -828,7 +828,7 @@ void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
|
||||
const LLInst &inst(*insn);
|
||||
QString opcode = Machine_X86::opcodeName(insn->getOpcode());
|
||||
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->addTaggedString(XT_Keyword,Machine_X86::opcodeName(insn->getOpcode()),insn);
|
||||
out->addSpace(2);
|
||||
@ -905,17 +905,12 @@ void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
|
||||
}
|
||||
else if (inst.testFlags(I) )
|
||||
{
|
||||
out->addTaggedString(XT_AsmLabel,strHex(inst.src().getImm2()));
|
||||
// j = inst.src().getImm2();
|
||||
// if (pl.count(j)==0) /* Forward jump */
|
||||
// {
|
||||
// pl[j] = ++g_lab;
|
||||
// }
|
||||
// if (inst.getOpcode() == iJMPF)
|
||||
// {
|
||||
// operands_s<<" far ptr ";
|
||||
// }
|
||||
// operands_s<<"L"<<pl[j];
|
||||
int64_t tgt_addr = inst.src().getImm2();
|
||||
if (inst.getOpcode() == iJMPF)
|
||||
{
|
||||
out->addTaggedString(XT_Keyword," far ptr ");
|
||||
}
|
||||
out->addTaggedString(XT_AsmLabel,QString("L_%1").arg(strHex(tgt_addr)));
|
||||
}
|
||||
else if (inst.getOpcode() == iJMPF)
|
||||
{
|
||||
@ -928,6 +923,36 @@ void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@ -399,7 +399,8 @@ void Function::highLevelGen()
|
||||
}
|
||||
break;
|
||||
|
||||
case iMOV: pIcode->setAsgn(lhs, rhs);
|
||||
case iMOV:
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMUL:
|
||||
@ -432,7 +433,8 @@ void Function::highLevelGen()
|
||||
break;
|
||||
|
||||
case iRET:
|
||||
case iRETF: pIcode->setUnary(HLI_RET, nullptr);
|
||||
case iRETF:
|
||||
pIcode->setUnary(HLI_RET, nullptr);
|
||||
break;
|
||||
|
||||
case iSHL:
|
||||
@ -461,6 +463,8 @@ void Function::highLevelGen()
|
||||
rhs = new BinaryOperator(XOR,lhs, rhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
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")
|
||||
.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
|
||||
{
|
||||
@ -553,7 +557,7 @@ void HLTYPE::set(Expr *l, Expr *r)
|
||||
//assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
|
||||
assert(dynamic_cast<UnaryOperator *>(l));
|
||||
asgn.m_lhs=l;
|
||||
asgn.rhs=r;
|
||||
asgn.m_rhs=r;
|
||||
}
|
||||
/* 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
|
||||
|
||||
@ -67,6 +67,15 @@ extern bundle cCode;
|
||||
* is created and a goto is also emitted.
|
||||
* Note: this procedure is to be used when the label is to be backpatched
|
||||
* onto code in cCode.code */
|
||||
void LLInst::clrFlags(uint32_t flag)
|
||||
{
|
||||
if(getOpcode()==iMOD)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
flg &= ~flag;
|
||||
}
|
||||
|
||||
void LLInst::emitGotoLabel (int indLevel)
|
||||
{
|
||||
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++;
|
||||
if (ll->getOpcode() == iJAE or ll->getOpcode() == iJA)
|
||||
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;
|
||||
|
||||
@ -212,8 +212,10 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
||||
/* Next icode. Note: not the same as GetLastIcode() because of the call
|
||||
to FollowCtrl() */
|
||||
pIcode = Icode.GetIcode(ip);
|
||||
} /* Fall through to do the jump path */
|
||||
|
||||
/* do the jump path */
|
||||
done = process_JMP (*pIcode, pstate, pcallGraph);
|
||||
break;
|
||||
}
|
||||
/*** Jumps ***/
|
||||
case iJMP:
|
||||
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 iRETF:
|
||||
this->flg |= (ll->getOpcode() == iRET)? PROC_NEAR:PROC_FAR;
|
||||
/* Fall through */
|
||||
this->flg &= ~TERMINATES;
|
||||
done = true;
|
||||
break;
|
||||
case iIRET:
|
||||
this->flg &= ~TERMINATES;
|
||||
done = true;
|
||||
@ -868,7 +872,7 @@ static void process_MOV(LLInst & ll, STATE * pstate)
|
||||
pstate->setMemoryByte(psym->label,(uint8_t)pstate->r[srcReg]);
|
||||
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);
|
||||
}
|
||||
psym->duVal.setFlags(eDuVal::DEF);
|
||||
@ -1276,7 +1280,9 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
|
||||
use(SRC, pIcode, this, pstate, cb);
|
||||
break;
|
||||
|
||||
case iLOOP: case iLOOPE: case iLOOPNE:
|
||||
case iLOOP:
|
||||
case iLOOPE:
|
||||
case iLOOPNE:
|
||||
pIcode.du.def.addReg(rCX);
|
||||
pIcode.du1.addDef(rCX);
|
||||
case iJCXZ:
|
||||
@ -1331,7 +1337,8 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
|
||||
pIcode.du.use.addReg(rDX).addReg(sseg);
|
||||
break;
|
||||
|
||||
case iIN: case iOUT:
|
||||
case iIN:
|
||||
case iOUT:
|
||||
def(DST, pIcode, this, pstate, cb);
|
||||
if (not Imm)
|
||||
{
|
||||
|
||||
@ -187,7 +187,7 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
|
||||
/* Do ps (actual arguments) */
|
||||
STKSYM newsym;
|
||||
newsym.setArgName(call_args_stackframe->size());
|
||||
newsym.actual = picode->hl()->asgn.rhs;
|
||||
newsym.actual = picode->hl()->asgn.m_rhs;
|
||||
newsym.regs = lhs;
|
||||
/* Mask off high and low register(s) in picode */
|
||||
switch (type) {
|
||||
|
||||
@ -228,6 +228,7 @@ void Project::processFunctionCommands(const PtrFunction &func,int count) {
|
||||
}
|
||||
}
|
||||
emit commandListChanged();
|
||||
emit functionUpdate(func);
|
||||
}
|
||||
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)
|
||||
{
|
||||
/* 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
|
||||
* provide the value of this segment in the field segValue.
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#include <QtWidgets>
|
||||
#include <QLabel>
|
||||
#include <QFileDialog>
|
||||
IDcc* g_EXE2C = NULL;
|
||||
IDcc* g_IDCC = NULL;
|
||||
extern bool exe2c_Init();
|
||||
|
||||
DccMainWindow::DccMainWindow(QWidget *parent) :
|
||||
@ -22,9 +22,9 @@ DccMainWindow::DccMainWindow(QWidget *parent) :
|
||||
ui->setupUi(this);
|
||||
ui->statusbar->addPermanentWidget(new QLabel("Test"));
|
||||
|
||||
g_EXE2C = IDcc::get();
|
||||
g_EXE2C->BaseInit();
|
||||
g_EXE2C->Init(this);
|
||||
g_IDCC = IDcc::get();
|
||||
g_IDCC->BaseInit();
|
||||
g_IDCC->Init(this);
|
||||
|
||||
m_last_display = nullptr;
|
||||
m_command_queue = new CommandQueueView(this);
|
||||
@ -36,20 +36,12 @@ DccMainWindow::DccMainWindow(QWidget *parent) :
|
||||
// we are beeing signalled when display is requested
|
||||
connect(this,SIGNAL(functionListChanged()), m_functionlist_widget->model(),SLOT(updateFunctionList()));
|
||||
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::LeftDockWidgetArea,m_command_queue);
|
||||
connect(m_functionlist_widget,&FunctionListDockWidget::selectFunction,
|
||||
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()
|
||||
@ -71,13 +63,22 @@ void DccMainWindow::changeEvent(QEvent *e)
|
||||
void DccMainWindow::onFunctionSelected(PtrFunction 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) {
|
||||
emit functionListChanged();
|
||||
}
|
||||
void DccMainWindow::onOptim()
|
||||
{
|
||||
Project::get()->processCommands();
|
||||
g_EXE2C->analysis_Once();
|
||||
g_IDCC->analysis_Once();
|
||||
emit functionListChanged();
|
||||
if(m_last_display==m_selected_func)
|
||||
{
|
||||
@ -87,7 +88,7 @@ void DccMainWindow::onOptim()
|
||||
void DccMainWindow::onOptim10()
|
||||
{
|
||||
for(int i=0; i<10; i++)
|
||||
g_EXE2C->analysis_Once();
|
||||
g_IDCC->analysis_Once();
|
||||
emit functionListChanged();
|
||||
if(m_last_display==m_selected_func)
|
||||
{
|
||||
@ -101,20 +102,43 @@ void DccMainWindow::onOpenFile_Action()
|
||||
tr("Select DOS executable"),
|
||||
".",
|
||||
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));
|
||||
}
|
||||
//bool m_bSucc = m_xTextBuffer.LoadFromFile(lpszPathName);
|
||||
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()
|
||||
{
|
||||
if(m_last_display!=m_selected_func)
|
||||
if(m_last_display!=m_selected_func) {
|
||||
m_last_display=m_selected_func;
|
||||
g_EXE2C->prtout_asm(m_last_display, m_asm_view);
|
||||
//g_EXE2C->prtout_itn(m_internal_view);
|
||||
g_EXE2C->prtout_cpp(m_last_display,m_c_view);
|
||||
// Check if function's view is already open, if it is, acivate it
|
||||
auto iter = m_map_function_to_view.find(m_selected_func);
|
||||
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)
|
||||
{
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include <QAbstractTableModel>
|
||||
#include <QVariant>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
class FunctionViewWidget;
|
||||
class FunctionListDockWidget;
|
||||
@ -36,11 +37,12 @@ private slots:
|
||||
void on_actionExit_triggered();
|
||||
void onNewFunction(PtrFunction f);
|
||||
void onFunctionSelected(PtrFunction func);
|
||||
void functionViewClosed();
|
||||
void onFunctionUpdated(const PtrFunction & f);
|
||||
private:
|
||||
|
||||
FunctionViewWidget *m_asm_view;
|
||||
std::vector<FunctionViewWidget *> m_mdi_function_views;
|
||||
std::unordered_map<PtrFunction,FunctionViewWidget *> m_map_function_to_view;
|
||||
// FunctionViewWidget *m_internal_view;
|
||||
FunctionViewWidget *m_c_view;
|
||||
CommandQueueView *m_command_queue;
|
||||
FunctionListDockWidget *m_functionlist_widget;
|
||||
Ui::DccMainWindow *ui;
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
#include <QtCore>
|
||||
//#include "exe2c.h"
|
||||
extern IDcc *g_EXE2C;
|
||||
extern IDcc *g_IDCC;
|
||||
FunctionListDockWidget::FunctionListDockWidget(QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::FunctionListDockWidget)
|
||||
|
||||
@ -1,16 +1,21 @@
|
||||
#include <QDebug>
|
||||
#include <QtCore>
|
||||
#include "FunctionViewWidget.h"
|
||||
#include "ui_FunctionViewWidget.h"
|
||||
#include "RenderTags.h"
|
||||
#include "Procedure.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QtCore>
|
||||
#include "dcc_interface.h"
|
||||
extern IDcc* g_IDCC;
|
||||
//#include "XMLTYPE.h"
|
||||
FunctionViewWidget::FunctionViewWidget(QWidget *parent) :
|
||||
FunctionViewWidget::FunctionViewWidget(PtrFunction func, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::FunctionViewWidget)
|
||||
ui(new Ui::FunctionViewWidget),
|
||||
m_viewed_function(func)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
m_current_rendering = new QTextDocument(ui->textEdit);
|
||||
m_doc_cursor = new QTextCursor(m_current_rendering);
|
||||
m_assembly_rendering = new QTextDocument(ui->textEdit);
|
||||
m_doc_cursor = new QTextCursor(m_assembly_rendering);
|
||||
ui->textEdit->setTextBackgroundColor(Qt::black);
|
||||
m_current_format = m_doc_cursor->blockFormat();
|
||||
m_current_format.setNonBreakableLines(true); // each block is single line
|
||||
@ -25,6 +30,11 @@ FunctionViewWidget::~FunctionViewWidget()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void FunctionViewWidget::renderCurrent()
|
||||
{
|
||||
m_viewed_function->toStructuredText(this,0);
|
||||
}
|
||||
|
||||
void FunctionViewWidget::prtt(const char *s)
|
||||
{
|
||||
m_doc_cursor->insertText(s);
|
||||
@ -50,7 +60,7 @@ void FunctionViewWidget::TAGbegin(TAG_TYPE tag_type, void *p)
|
||||
switch(tag_type)
|
||||
{
|
||||
case XT_Function:
|
||||
m_current_rendering->clear();
|
||||
m_assembly_rendering->clear();
|
||||
m_chars_format.setForeground(Qt::white);
|
||||
m_doc_cursor->setBlockFormat(m_current_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?
|
||||
QFile res("result.html");
|
||||
res.open(QFile::WriteOnly);
|
||||
res.write(m_current_rendering->toHtml().toUtf8());
|
||||
res.write(m_assembly_rendering->toHtml().toUtf8());
|
||||
res.close();
|
||||
ui->textEdit->setDocument(m_current_rendering);
|
||||
ui->textEdit->setDocument(m_assembly_rendering);
|
||||
collected_text.clear();
|
||||
break;
|
||||
}
|
||||
@ -100,3 +110,7 @@ void FunctionViewWidget::TAGend(TAG_TYPE tag_type)
|
||||
qDebug()<<"Tag end:"<<tag_type;
|
||||
}
|
||||
}
|
||||
void FunctionViewWidget::on_tabWidget_currentChanged(int index)
|
||||
{
|
||||
renderCurrent();
|
||||
}
|
||||
|
||||
@ -4,28 +4,42 @@
|
||||
#include "StructuredTextTarget.h"
|
||||
#include "RenderTags.h"
|
||||
|
||||
#include <memory>
|
||||
#include <QWidget>
|
||||
#include <QTextDocument>
|
||||
#include <QTextBlockFormat>
|
||||
//#include "XmlPrt.h"
|
||||
|
||||
class Function;
|
||||
typedef std::shared_ptr<Function> PtrFunction;
|
||||
namespace Ui {
|
||||
class FunctionViewWidget;
|
||||
}
|
||||
//TODO: convert 'controllers' of each hex/asm/high-level areas into standalone classes
|
||||
class FunctionViewWidget : public QWidget,public IStructuredTextTarget
|
||||
{
|
||||
Q_OBJECT
|
||||
QTextDocument *m_current_rendering;
|
||||
PtrFunction m_viewed_function; // 'model' this view is bound to
|
||||
QTextDocument *m_assembly_rendering;
|
||||
QTextCursor* m_doc_cursor;
|
||||
QTextBlockFormat m_current_format;
|
||||
QTextCharFormat m_chars_format;
|
||||
public:
|
||||
explicit FunctionViewWidget(QWidget *parent = 0);
|
||||
explicit FunctionViewWidget(PtrFunction func,QWidget *parent = 0);
|
||||
~FunctionViewWidget();
|
||||
const PtrFunction &viewedFunction() const { return m_viewed_function; }
|
||||
void renderCurrent();
|
||||
|
||||
// IStructuredTextTarget interface
|
||||
void prtt(const char * s);
|
||||
void prtt(const QString &s);
|
||||
void addEOL() override;
|
||||
void TAGbegin(enum TAG_TYPE tag_type, void * p);
|
||||
void TAGend(enum TAG_TYPE tag_type);
|
||||
|
||||
|
||||
private slots:
|
||||
void on_tabWidget_currentChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::FunctionViewWidget *ui;
|
||||
QString collected_text;
|
||||
|
||||
@ -6,14 +6,51 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
<width>708</width>
|
||||
<height>582</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</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>
|
||||
<widget class="QTextEdit" name="textEdit">
|
||||
<property name="undoRedoEnabled">
|
||||
@ -36,6 +73,37 @@ p, li { white-space: pre-wrap; }
|
||||
</item>
|
||||
</layout>
|
||||
</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/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user