diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc index c34ce04ff7..8b6532a23f 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc @@ -2059,17 +2059,24 @@ int4 ActionSetCasts::apply(Funcdata &data) for(iter=bb->beginOp();iter!=bb->endOp();++iter) { op = *iter; if (op->notPrinted()) continue; - if (op->code() == CPUI_CAST) continue; + OpCode opc = op->code(); + if (opc == CPUI_CAST) continue; + if (opc == CPUI_PTRADD) { // Check for PTRADD that no longer fits its pointer + int4 sz = (int4)op->getIn(2)->getOffset(); + TypePointer *ct = (TypePointer *)op->getIn(0)->getHigh()->getType(); + if ((ct->getMetatype() != TYPE_PTR)||(ct->getPtrTo()->getSize() != AddrSpace::addressToByteInt(sz, ct->getWordSize()))) + data.opUndoPtradd(op,true); + } for(int4 i=0;inumInput();++i) // Do input casts first, as output may depend on input count += castInput(op,i,data,castStrategy); - if (op->code() == CPUI_LOAD) { + if (opc == CPUI_LOAD) { TypePointer *ptrtype = (TypePointer *)op->getIn(1)->getHigh()->getType(); int4 valsize = op->getOut()->getSize(); if ((ptrtype->getMetatype()!=TYPE_PTR)|| (ptrtype->getPtrTo()->getSize() != valsize)) data.warning("Load size is inaccurate",op->getAddr()); } - else if (op->code() == CPUI_STORE) { + else if (opc == CPUI_STORE) { TypePointer *ptrtype = (TypePointer *)op->getIn(1)->getHigh()->getType(); int4 valsize = op->getIn(2)->getSize(); if ((ptrtype->getMetatype()!=TYPE_PTR)|| diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh index 617c7e7dfe..137b23c5e7 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh @@ -428,6 +428,7 @@ public: Varnode *createStackRef(AddrSpace *spc,uintb off,PcodeOp *op,Varnode *stackptr,bool insertafter); Varnode *opStackLoad(AddrSpace *spc,uintb off,uint4 sz,PcodeOp *op,Varnode *stackptr,bool insertafter); PcodeOp *opStackStore(AddrSpace *spc,uintb off,PcodeOp *op,bool insertafter); + void opUndoPtradd(PcodeOp *op,bool finalize); ///< Convert a CPUI_PTRADD back into a CPUI_INT_ADD /// \brief Start of PcodeOp objects with the given op-code list::const_iterator beginOp(OpCode opc) const { return obank.begin(opc); } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc index 17b4a0322d..a4ec654f6b 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc @@ -521,6 +521,42 @@ Varnode *Funcdata::opStackLoad(AddrSpace *spc,uintb off,uint4 sz,PcodeOp *op,Var return res; } +/// Convert the given CPUI_PTRADD into the equivalent CPUI_INT_ADD. This may involve inserting a +/// CPUI_INT_MULT PcodeOp. If finalization is requested and a new PcodeOp is needed, the output +/// Varnode is marked as \e implicit and has its data-type set +/// \param op is the given PTRADD +void Funcdata::opUndoPtradd(PcodeOp *op,bool finalize) + +{ + Varnode *multVn = op->getIn(2); + int4 multSize = multVn->getOffset(); // Size the PTRADD thinks we are pointing + + opRemoveInput(op,2); + opSetOpcode(op,CPUI_INT_ADD); + if (multSize == 1) return; // If no multiplier, we are done + Varnode *offVn = op->getIn(1); + if (offVn->isConstant()) { + uintb newVal = multSize * offVn->getOffset(); + newVal &= calc_mask(offVn->getSize()); + Varnode *newOffVn = newConstant(offVn->getSize(), newVal); + if (finalize) + newOffVn->updateType(offVn->getType(), false, false); + opSetInput(op,newOffVn,1); + return; + } + PcodeOp *multOp = newOp(2,op->getAddr()); + opSetOpcode(multOp,CPUI_INT_MULT); + Varnode *addVn = newUniqueOut(offVn->getSize(),multOp); + if (finalize) { + addVn->updateType(multVn->getType(), false, false); + addVn->setImplied(); + } + opSetInput(multOp,offVn,0); + opSetInput(multOp,multVn,1); + opSetInput(op,addVn,1); + opInsertBefore(multOp,op); +} + /// Make a clone of the given PcodeOp, copying control-flow properties as well. The data-type /// is \e not cloned. /// \param op is the PcodeOp to clone diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc index 39c0d3c937..5fbc713fb6 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc @@ -6105,14 +6105,11 @@ void RulePtraddUndo::getOpList(vector &oplist) const int4 RulePtraddUndo::applyOp(PcodeOp *op,Funcdata &data) { - int4 size; - Varnode *basevn,*offvn,*multvn,*addvn; - PcodeOp *multop; + Varnode *basevn; TypePointer *tp; if (!data.isTypeRecoveryOn()) return 0; - multvn = op->getIn(2); - size = multvn->getOffset(); // Size the PTRADD thinks we are pointing + int4 size = (int4)op->getIn(2)->getOffset(); // Size the PTRADD thinks we are pointing basevn = op->getIn(0); tp = (TypePointer *)basevn->getType(); if (tp->getMetatype() == TYPE_PTR) // Make sure we are still a pointer @@ -6122,19 +6119,7 @@ int4 RulePtraddUndo::applyOp(PcodeOp *op,Funcdata &data) return 0; } - // At this point we have a type mismatch to fix - data.opRemoveInput(op,2); - data.opSetOpcode(op,CPUI_INT_ADD); - if (size == 1) return 1; // If no multiplier, we are done - multop = data.newOp(2,op->getAddr()); - data.opSetOpcode(multop,CPUI_INT_MULT); - offvn = op->getIn(1); - addvn = data.newUniqueOut(offvn->getSize(),multop); - data.opSetInput(multop,offvn,0); - data.opSetInput(multop,multvn,1); - data.opSetInput(op,addvn,1); - data.opInsertBefore(multop,op); - + data.opUndoPtradd(op,false); return 1; }