diff --git a/3rd_party/libdisasm/libdis.h b/3rd_party/libdisasm/libdis.h index 2d5ad3f..3bdde91 100644 --- a/3rd_party/libdisasm/libdis.h +++ b/3rd_party/libdisasm/libdis.h @@ -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 */ diff --git a/include/dcc_interface.h b/include/dcc_interface.h index a587642..1b355d4 100644 --- a/include/dcc_interface.h +++ b/include/dcc_interface.h @@ -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; diff --git a/include/icode.h b/include/icode.h index f0c666c..fa3aadf 100644 --- a/include/icode.h +++ b/include/icode.h @@ -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); @@ -252,17 +252,17 @@ public: /* LOW_LEVEL icode operand record */ struct LLOperand { - eReg seg; /* CS, DS, ES, SS */ - eReg segOver; /* CS, DS, ES, SS if segment override */ - int16_t segValue; /* Value of segment seg during analysis */ - eReg regi; /* 0 < regs < INDEXBASE <= index modes */ - int16_t off; /* memory address offset */ - uint32_t opz; /* idx of immed src op */ - bool immed; - bool is_offset; // set by jumps - bool is_compound; - size_t width; - //union {/* Source operand if (flg & I) */ + eReg seg; /* CS, DS, ES, SS */ + eReg segOver; /* CS, DS, ES, SS if segment override */ + int16_t segValue; /* Value of segment seg during analysis */ + eReg regi; /* 0 < regs < INDEXBASE <= index modes */ + int16_t off; /* memory address offset */ + uint32_t opz; /* idx of immed src op */ + bool immed; + bool is_offset; // set by jumps + bool is_compound; + size_t width; + /* Source operand if (flg & I) */ struct { /* Call & # actual arg bytes */ Function *proc; /* pointer to target proc (for CALL(F))*/ int cb; /* # actual arg bytes */ @@ -323,36 +323,28 @@ struct LLInst : public llvm::MCInst //: public llvm::ilist_node { protected: uint32_t flg; /* icode flags */ - LLOperand m_src; /* source operand */ + LLOperand m_src; /* source operand */ public: - int codeIdx; /* Index into cCode.code */ + int codeIdx; /* Index into cCode.code */ uint8_t numBytes; /* Number of bytes this instr */ uint32_t label; /* offset in image (20-bit adr) */ - LLOperand m_dst; /* destination operand */ + LLOperand m_dst; /* destination operand */ DU flagDU; /* def/use of flags */ int caseEntry; std::vector caseTbl2; - int hllLabNum; /* label # for hll codegen */ + int hllLabNum; /* label # for hll codegen */ bool conditionalJump() { return (getOpcode() >= iJB) and (getOpcode() < iJCXZ); } 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) { @@ -403,45 +395,30 @@ public: m_src = src_op; flg =flags; } - void emitGotoLabel(int indLevel); - void findJumpTargets(CIcodeRec &_pc); - void writeIntComment(QTextStream & s); - void dis1Line(int loc_ip, int pass); - QTextStream & strSrc(QTextStream & os, bool skip_comma=false); + void emitGotoLabel(int indLevel); + void findJumpTargets(CIcodeRec &_pc); + void writeIntComment(QTextStream & s); + void dis1Line(int loc_ip, int pass); + QTextStream & strSrc(QTextStream & os, bool skip_comma=false); - void flops(QTextStream & out); - bool isJmpInst(); - HLTYPE createCall(); - LLInst(ICODE *container) : flg(0),codeIdx(0),numBytes(0),m_link(container) - { - 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; - condId idType(opLoc sd) const; + void flops(QTextStream & out); + bool isJmpInst(); + HLTYPE createCall(); + LLInst(ICODE *container) : flg(0),codeIdx(0),numBytes(0),m_link(container) + { + 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; } + 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 */ diff --git a/include/project.h b/include/project.h index 2847963..cdff231 100644 --- a/include/project.h +++ b/include/project.h @@ -158,6 +158,7 @@ public slots: void onCommandStreamFinished(bool state); signals: void newFunctionCreated(PtrFunction); + void functionUpdate(const PtrFunction &); void loaderSelected(); void commandListChanged(); protected: diff --git a/src/dataflow.cpp b/src/dataflow.cpp index 2dfaf7b..f619ab1 100644 --- a/src/dataflow.cpp +++ b/src/dataflow.cpp @@ -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(_icHl.expr())->ident.idNode.longIdx, + forwardSubsLong (static_cast(_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(_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; diff --git a/src/dcc_interface.cpp b/src/dcc_interface.cpp index 95fe957..fd15a75 100644 --- a/src/dcc_interface.cpp +++ b/src/dcc_interface.cpp @@ -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)); diff --git a/src/disassem.cpp b/src/disassem.cpp index 9634543..7b3e3b0 100644 --- a/src/disassem.cpp +++ b/src/disassem.cpp @@ -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"<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(); } diff --git a/src/hlicode.cpp b/src/hlicode.cpp index 68e32c3..a0196e5 100644 --- a/src/hlicode.cpp +++ b/src/hlicode.cpp @@ -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(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 diff --git a/src/icode.cpp b/src/icode.cpp index c1928ce..912eecf 100644 --- a/src/icode.cpp +++ b/src/icode.cpp @@ -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 */ diff --git a/src/parser.cpp b/src/parser.cpp index f197241..f310850 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -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) { diff --git a/src/procs.cpp b/src/procs.cpp index 5204f82..6db112a 100644 --- a/src/procs.cpp +++ b/src/procs.cpp @@ -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) { diff --git a/src/project.cpp b/src/project.cpp index fcab187..29b9c35 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -228,6 +228,7 @@ void Project::processFunctionCommands(const PtrFunction &func,int count) { } } emit commandListChanged(); + emit functionUpdate(func); } void Project::resetCommandsAndErrorState() { diff --git a/src/scanner.cpp b/src/scanner.cpp index 8b6f967..b8a85a9 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -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. diff --git a/src/ui/DccMainWindow.cpp b/src/ui/DccMainWindow.cpp index 00fd6ed..73b8120 100644 --- a/src/ui/DccMainWindow.cpp +++ b/src/ui/DccMainWindow.cpp @@ -12,7 +12,7 @@ #include #include #include -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(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(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) { diff --git a/src/ui/DccMainWindow.h b/src/ui/DccMainWindow.h index 3f5d0e0..b2b24f7 100644 --- a/src/ui/DccMainWindow.h +++ b/src/ui/DccMainWindow.h @@ -8,6 +8,7 @@ #include #include #include +#include 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 m_mdi_function_views; + std::unordered_map m_map_function_to_view; // FunctionViewWidget *m_internal_view; - FunctionViewWidget *m_c_view; CommandQueueView *m_command_queue; FunctionListDockWidget *m_functionlist_widget; Ui::DccMainWindow *ui; diff --git a/src/ui/FunctionListDockWidget.cpp b/src/ui/FunctionListDockWidget.cpp index 6fe9832..28c63f7 100644 --- a/src/ui/FunctionListDockWidget.cpp +++ b/src/ui/FunctionListDockWidget.cpp @@ -8,7 +8,7 @@ #include //#include "exe2c.h" -extern IDcc *g_EXE2C; +extern IDcc *g_IDCC; FunctionListDockWidget::FunctionListDockWidget(QWidget *parent) : QDockWidget(parent), ui(new Ui::FunctionListDockWidget) diff --git a/src/ui/FunctionViewWidget.cpp b/src/ui/FunctionViewWidget.cpp index 5bb65ef..daadffc 100644 --- a/src/ui/FunctionViewWidget.cpp +++ b/src/ui/FunctionViewWidget.cpp @@ -1,16 +1,21 @@ -#include -#include #include "FunctionViewWidget.h" #include "ui_FunctionViewWidget.h" #include "RenderTags.h" +#include "Procedure.h" + +#include +#include +#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:"< #include #include #include -//#include "XmlPrt.h" + +class Function; +typedef std::shared_ptr 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; diff --git a/src/ui/FunctionViewWidget.ui b/src/ui/FunctionViewWidget.ui index ae685ea..8c55788 100644 --- a/src/ui/FunctionViewWidget.ui +++ b/src/ui/FunctionViewWidget.ui @@ -6,32 +6,100 @@ 0 0 - 400 - 300 + 708 + 582 Form - + - - - false + + + 0 - - QTextEdit::NoWrap - - - true - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + Binary + + + + + + false + + + QTextEdit::NoWrap + + + true + + + <!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> - + + + + + + + + Assembly + + + + + + false + + + QTextEdit::NoWrap + + + true + + + <!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> + + + + + + + + High level + + + + + + false + + + QTextEdit::NoWrap + + + true + + + <!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> + + + + +