diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc index 219423c415..f29bc2aef4 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc @@ -1144,7 +1144,8 @@ int4 ActionDirectWrite::apply(Funcdata &data) dvn = op->getOut(); if (!dvn->isDirectWrite()) { dvn->setDirectWrite(); - if (propagateIndirect || op->code() != CPUI_INDIRECT) // If INDIRECT, output is marked, but does not propagate + // For call based INDIRECTs, output is marked, but does not propagate depending on setting + if (propagateIndirect || op->code() != CPUI_INDIRECT || op->isIndirectStore()) worklist.push_back(dvn); } } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh index cd7dbb1ef1..9ced5d3f61 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh @@ -384,7 +384,7 @@ public: PcodeOp *newOpBefore(PcodeOp *follow,OpCode opc,Varnode *in1,Varnode *in2,Varnode *in3=(Varnode *)0); PcodeOp *cloneOp(const PcodeOp *op,const SeqNum &seq); /// Clone a PcodeOp into \b this function PcodeOp *canonicalReturnOp(void) const; /// Find a representative CPUI_RETURN op for \b this function - PcodeOp *newIndirectOp(PcodeOp *indeffect,const Address &addr,int4 size); + PcodeOp *newIndirectOp(PcodeOp *indeffect,const Address &addr,int4 size,uint4 extraFlags); void setIndirectCreation(PcodeOp *op,PcodeOp *indeffect,Varnode *outvn,bool possibleout); PcodeOp *newIndirectCreation(PcodeOp *indeffect,const Address &addr,int4 size,bool possibleout); void truncateIndirect(PcodeOp *indop); ///< Convert CPUI_INDIRECT into an \e indirect \e creation diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc index b92f64a5bc..7486aa5139 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc @@ -608,8 +608,9 @@ PcodeOp *Funcdata::newOpBefore(PcodeOp *follow,OpCode opc,Varnode *in1,Varnode * /// \param indeffect is the PcodeOp with the indirect effect /// \param addr is the starting address of the storage range to protect /// \param size is the number of bytes in the storage range +/// \param extraFlags are extra boolean properties to put on the INDIRECT /// \return the new CPUI_INDIRECT op -PcodeOp *Funcdata::newIndirectOp(PcodeOp *indeffect,const Address &addr,int4 size) +PcodeOp *Funcdata::newIndirectOp(PcodeOp *indeffect,const Address &addr,int4 size,uint4 extraFlags) { Varnode *newin; @@ -617,6 +618,7 @@ PcodeOp *Funcdata::newIndirectOp(PcodeOp *indeffect,const Address &addr,int4 siz newin = newVarnode(size,addr); newop = newOp(2,indeffect->getAddr()); + newop->flags |= extraFlags; newVarnodeOut(size,addr,newop); opSetOpcode(newop,CPUI_INDIRECT); opSetInput(newop,newin,0); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc index a26d820f42..f00a725ff4 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc @@ -1402,7 +1402,6 @@ bool AncestorRealistic::checkConditionalExe(State &state) int4 AncestorRealistic::enterNode(State &state) { - PcodeOp *indop; // If the node has already been visited, we truncate the traversal to prevent cycles. // We always return success assuming the proper result will get returned along the first path if (state.vn->isMark()) return pop_success; @@ -1424,8 +1423,7 @@ int4 AncestorRealistic::enterNode(State &state) return pop_failkill; // Truncate this path, indicating killedbycall return pop_success; // otherwise it could be valid } - indop = PcodeOp::getOpFromConst(op->getIn(1)->getAddr()); - if (indop->isCall()) { // If flow goes THROUGH a call + if (!op->isIndirectStore()) { // If flow goes THROUGH a call if (op->getOut()->isReturnAddress()) return pop_fail; // Storage address location is completely invalid if (trial->isKilledByCall()) return pop_fail; // "Likely" killedbycall is invalid } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/heritage.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/heritage.cc index 68cd1a3af5..84b7855c20 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/heritage.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/heritage.cc @@ -1088,7 +1088,7 @@ void Heritage::guardCalls(uint4 flags,const Address &addr,int4 size,vectornewIndirectOp(fc->getOp(),addr,size); + indop = fd->newIndirectOp(fc->getOp(),addr,size,0); indop->getIn(0)->setActiveHeritage(); indop->getOut()->setActiveHeritage(); write.push_back(indop->getOut()); @@ -1129,7 +1129,7 @@ void Heritage::guardStores(const Address &addr,int4 size,vector &writ AddrSpace *storeSpace = Address::getSpaceFromConst(op->getIn(0)->getAddr()); if ((container == storeSpace && op->usesSpacebasePtr()) || (spc == storeSpace)) { - indop = fd->newIndirectOp(op,addr,size); + indop = fd->newIndirectOp(op,addr,size,PcodeOp::indirect_store); indop->getIn(0)->setActiveHeritage(); indop->getOut()->setActiveHeritage(); write.push_back(indop->getOut()); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh index 4fd005ef85..eff509db7f 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh @@ -96,7 +96,8 @@ public: indirect_creation = 0x8000000, ///< Output varnode is created by indirect effect calculated_bool = 0x10000000, ///< Output has been determined to be a 1-bit boolean value is_cpool_transformed = 0x20000000, ///< Have we checked for cpool transforms - ptrflow = 0x40000000 ///< Op consumes or produces a ptr + ptrflow = 0x40000000, ///< Op consumes or produces a ptr + indirect_store = 0x80000000 ///< CPUI_INDIRECT is caused by CPUI_STORE }; enum { has_thisptr = 0x1, ///< First parameter ( getIn(1) ) is a this pointer @@ -163,6 +164,7 @@ public: bool isCall(void) const { return ((flags&PcodeOp::call)!=0); } ///< Return \b true if this op indicates call semantics bool isMarker(void) const { return ((flags&PcodeOp::marker)!=0); } ///< Return \b true is a special SSA form op bool isIndirectCreation(void) const { return ((flags&PcodeOp::indirect_creation)!=0); } ///< Return \b true if op creates a varnode indirectly + bool isIndirectStore(void) const { return ((flags&PcodeOp::indirect_store)!=0); } ///< Return \b true if \b this INDIRECT is caused by STORE /// \brief Return \b true if this op is not directly represented in C output bool notPrinted(void) const { return ((flags&(PcodeOp::marker|PcodeOp::nonprinting|PcodeOp::noreturn))!=0); } /// \brief Return \b true if this op produces a boolean output