diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc index 4c25c59fca..969c8ccebf 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc @@ -81,6 +81,35 @@ PcodeOp::PcodeOp(int4 s,const SeqNum &sq) : start(sq),inrefs(s) inrefs[i] = (Varnode *)0; } +/// \brief Find the slot for a given Varnode, which may be take up multiple input slots +/// +/// In the rare case that \b this PcodeOp takes the same Varnode as input multiple times, +/// use the specific descendant iterator producing \b this PcodeOp to work out the corresponding slot. +/// Every slot containing the given Varnode will be produced exactly once over the course of iteration. +/// \param vn is the given Varnode +/// \param firstSlot is the first instance of the Varnode in \b this input list +/// \param iter is the specific descendant iterator producing \b this +/// \return the slot corresponding to the iterator +int4 PcodeOp::getRepeatSlot(const Varnode *vn,int4 firstSlot,list::const_iterator iter) const + +{ + int4 count = 1; + for(list::const_iterator oiter=vn->beginDescend();oiter != iter;++oiter) { + if ((*oiter) == this) + count += 1; + } + if (count == 1) return firstSlot; + int4 recount = 1; + for(int4 i=firstSlot+1;i::iterator getBasicIter(void) const { return basiciter; } ///< Get position within basic block /// \brief Get the slot number of the indicated input varnode int4 getSlot(const Varnode *vn) const { int4 i,n; n=inrefs.size(); for(i=0;i::const_iterator iter) const; /// \brief Get the evaluation type of this op uint4 getEvalType(void) const { return (flags&(PcodeOp::unary|PcodeOp::binary|PcodeOp::special)); } /// \brief Get type which indicates unusual halt in control-flow diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/subflow.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/subflow.cc index 6c509dfcf6..bc358a2465 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/subflow.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/subflow.cc @@ -347,14 +347,14 @@ bool SubvariableFlow::traceForward(ReplaceVarnode *rvn) bool booldir; int4 dcount = 0; int4 hcount = 0; + int4 callcount = 0; list::const_iterator iter,enditer; - iter = rvn->vn->beginDescend(); enditer = rvn->vn->endDescend(); - while(iter != enditer) { - op = *iter++; + for(iter = rvn->vn->beginDescend();iter != enditer;++iter) { + op = *iter; outvn = op->getOut(); - if ((outvn!=(Varnode *)0)&&(outvn->isMark())) + if ((outvn!=(Varnode *)0)&&outvn->isMark()&&!op->isCall()) continue; dcount += 1; // Count this descendant slot = op->getSlot(rvn->vn); @@ -557,6 +557,9 @@ bool SubvariableFlow::traceForward(ReplaceVarnode *rvn) break; case CPUI_CALL: case CPUI_CALLIND: + callcount += 1; + if (callcount > 1) + slot = op->getRepeatSlot(rvn->vn, slot, iter); if (!tryCallPull(op,rvn,slot)) return false; hcount += 1; // Dealt with this descendant break; @@ -781,14 +784,14 @@ bool SubvariableFlow::traceForwardSext(ReplaceVarnode *rvn) int4 slot; int4 dcount = 0; int4 hcount = 0; + int4 callcount = 0; list::const_iterator iter,enditer; - iter = rvn->vn->beginDescend(); enditer = rvn->vn->endDescend(); - while(iter != enditer) { - op = *iter++; + for(iter=rvn->vn->beginDescend();iter != enditer;++iter) { + op = *iter; outvn = op->getOut(); - if ((outvn!=(Varnode *)0)&&(outvn->isMark())) + if ((outvn!=(Varnode *)0)&&outvn->isMark()&&!op->isCall()) continue; dcount += 1; // Count this descendant slot = op->getSlot(rvn->vn); @@ -836,6 +839,9 @@ bool SubvariableFlow::traceForwardSext(ReplaceVarnode *rvn) break; case CPUI_CALL: case CPUI_CALLIND: + callcount += 1; + if (callcount > 1) + slot = op->getRepeatSlot(rvn->vn, slot, iter); if (!tryCallPull(op,rvn,slot)) return false; hcount += 1; // Dealt with this descendant break;