diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc index fd8f9ad546..a4c5bfc399 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc @@ -2289,6 +2289,16 @@ int4 ActionSetCasts::apply(Funcdata &data) if ((ct->getMetatype() != TYPE_PTR)||(ct->getPtrTo()->getSize() != AddrSpace::addressToByteInt(sz, ct->getWordSize()))) data.opUndoPtradd(op,true); } + else if (opc == CPUI_PTRSUB) { // Check for PTRSUB that no longer fits pointer + if (!op->getIn(0)->getHigh()->getType()->isPtrsubMatching(op->getIn(1)->getOffset())) { + if (op->getIn(1)->getOffset() == 0) { + data.opRemoveInput(op, 1); + data.opSetOpcode(op, CPUI_COPY); + } + else + data.opSetOpcode(op, CPUI_INT_ADD); + } + } for(int4 i=0;inumInput();++i) // Do input casts first, as output may depend on input count += castInput(op,i,data,castStrategy); if (opc == CPUI_LOAD) { diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc index 558ed12b65..48c774cb5c 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc @@ -6363,30 +6363,8 @@ int4 RulePtrsubUndo::applyOp(PcodeOp *op,Funcdata &data) if (!data.isTypeRecoveryOn()) return 0; Varnode *basevn = op->getIn(0); - TypePointer *ct = (TypePointer *)basevn->getType(); - bool undo = false; - - if (ct->getMetatype()!=TYPE_PTR) - undo = true; - else { - Datatype *basetype = ct->getPtrTo(); - if (basetype->getMetatype()==TYPE_SPACEBASE) { - uintb newoff = AddrSpace::addressToByte(op->getIn(1)->getOffset(),ct->getWordSize()); - basetype->getSubType(newoff,&newoff); - if (newoff != 0) - undo = true; - } - else { - int4 size = op->getIn(1)->getOffset(); - int4 typesize = basetype->getSize(); - if ((basetype->getMetatype()!=TYPE_ARRAY)&&(basetype->getMetatype()!=TYPE_STRUCT)) - undo = true; // Not a pointer to a structured type - else if ((typesize <= AddrSpace::addressToByteInt(size,ct->getWordSize()))&&(typesize!=0)) - undo = true; - } - } - - if (!undo) return 0; + if (basevn->getType()->isPtrsubMatching(op->getIn(1)->getOffset())) + return 0; data.opSetOpcode(op,CPUI_INT_ADD); return 1; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc index a6bbef9298..ff79355d3b 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc @@ -316,6 +316,35 @@ void Datatype::saveXmlRef(ostream &s) const saveXml(s); } +/// A CPUI_PTRSUB must act on a pointer data-type where the given offset addresses a component. +/// Perform this check. +/// \param is the given offset +/// \return \b true if \b this is a suitable PTRSUB data-type +bool Datatype::isPtrsubMatching(uintb offset) const + +{ + if (metatype != TYPE_PTR) + return false; + + Datatype *basetype = ((TypePointer *)this)->getPtrTo(); + uint4 wordsize = ((TypePointer *)this)->getWordSize(); + if (basetype->metatype==TYPE_SPACEBASE) { + uintb newoff = AddrSpace::addressToByte(offset,wordsize); + basetype->getSubType(newoff,&newoff); + if (newoff != 0) + return false; + } + else { + int4 size = offset; + int4 typesize = basetype->getSize(); + if ((basetype->metatype != TYPE_ARRAY)&&(basetype->metatype != TYPE_STRUCT)) + return false; // Not a pointer to a structured type + else if ((typesize <= AddrSpace::addressToByteInt(size,wordsize))&&(typesize!=0)) + return false; + } + return true; +} + /// Restore the basic properties (name,size,id) of a data-type from an XML element /// Properties are read from the attributes of the element /// \param el is the XML element diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh index 187499d123..1fb0b1404e 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh @@ -126,6 +126,7 @@ public: int4 typeOrderBool(const Datatype &op) const; ///< Order \b this with -op-, treating \e bool data-type as special void saveXmlBasic(ostream &s) const; ///< Save basic data-type properties void saveXmlRef(ostream &s) const; ///< Write an XML reference of \b this to stream + bool isPtrsubMatching(uintb offset) const; ///< Is this data-type suitable as input to a CPUI_PTRSUB op }; /// \brief Specifies subfields of a structure or what a pointer points to