Merge remote-tracking branch 'origin/patch'

Conflicts:
	Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java
This commit is contained in:
Ryan Kurtz 2019-12-10 12:29:41 -05:00
commit b8f07b8351
9 changed files with 53 additions and 18 deletions

View file

@ -1177,6 +1177,8 @@ void FlowInfo::doInjection(InjectPayload *payload,InjectContext &icontext,PcodeO
data.opMarkStartBasic(*iter); // as start of basic block data.opMarkStartBasic(*iter); // as start of basic block
} }
if (payload->isIncidentalCopy())
obank.markIncidentalCopy(firstop, lastop);
obank.moveSequenceDead(firstop,lastop,op); // Move the injection to right after the call obank.moveSequenceDead(firstop,lastop,op); // Move the injection to right after the call
map<Address,VisitStat>::iterator viter = visited.find(op->getAddr()); map<Address,VisitStat>::iterator viter = visited.find(op->getAddr());

View file

@ -4106,6 +4106,7 @@ int4 FuncCallSpecs::transferLockedInputParam(ProtoParameter *param)
if (startaddr < curtrial.getAddress()) continue; if (startaddr < curtrial.getAddress()) continue;
Address trialend = curtrial.getAddress() + (curtrial.getSize() - 1); Address trialend = curtrial.getAddress() + (curtrial.getSize() - 1);
if (trialend < lastaddr) continue; if (trialend < lastaddr) continue;
if (curtrial.isDefinitelyNotUsed()) return 0; // Trial has already been stripped
return curtrial.getSlot(); return curtrial.getSlot();
} }
if (startaddr.getSpace()->getType() == IPTR_SPACEBASE) if (startaddr.getSpace()->getType() == IPTR_SPACEBASE)

View file

@ -1341,13 +1341,7 @@ bool Funcdata::ancestorOpUse(int4 maxlevel,const Varnode *invn,
return false; return false;
case CPUI_COPY: case CPUI_COPY:
if ((invn->getSpace()->getType()==IPTR_INTERNAL)||(invn->isAddrForce())) { if ((invn->getSpace()->getType()==IPTR_INTERNAL)||def->isIncidentalCopy()||def->getIn(0)->isIncidentalCopy()) {
// Bit of a kludge to take into account
// uniq <- LOAD uniq=stackX
// <->
// call( uniq ) call( uniq )
//
// We follow copys into uniques
if (!ancestorOpUse(maxlevel-1,def->getIn(0),op,trial)) return false; if (!ancestorOpUse(maxlevel-1,def->getIn(0),op,trial)) return false;
return true; return true;
} }
@ -1442,7 +1436,8 @@ int4 AncestorRealistic::enterNode(State &state)
case CPUI_SUBPIECE: case CPUI_SUBPIECE:
// Extracting to a temporary, or to the same storage location, or otherwise incidental // Extracting to a temporary, or to the same storage location, or otherwise incidental
// are viewed as just another node on the path to traverse // are viewed as just another node on the path to traverse
if (op->getOut()->getSpace()->getType()==IPTR_INTERNAL||op->getIn(0)->isIncidentalCopy() if (op->getOut()->getSpace()->getType()==IPTR_INTERNAL
|| op->isIncidentalCopy() || op->getIn(0)->isIncidentalCopy()
|| (op->getOut()->overlap(*op->getIn(0)) == (int4)op->getIn(1)->getOffset())) { || (op->getOut()->overlap(*op->getIn(0)) == (int4)op->getIn(1)->getOffset())) {
stateStack.push_back(State(op,0)); stateStack.push_back(State(op,0));
return enter_node; // Push into the new node return enter_node; // Push into the new node
@ -1461,7 +1456,8 @@ int4 AncestorRealistic::enterNode(State &state)
case CPUI_COPY: case CPUI_COPY:
// Copies to a temporary, or between varnodes with same storage location, or otherwise incidental // Copies to a temporary, or between varnodes with same storage location, or otherwise incidental
// are viewed as just another node on the path to traverse // are viewed as just another node on the path to traverse
if (op->getOut()->getSpace()->getType()==IPTR_INTERNAL||op->getIn(0)->isIncidentalCopy() if (op->getOut()->getSpace()->getType()==IPTR_INTERNAL
|| op->isIncidentalCopy() || op->getIn(0)->isIncidentalCopy()
|| (op->getOut()->getAddr() == op->getIn(0)->getAddr())) { || (op->getOut()->getAddr() == op->getIn(0)->getAddr())) {
stateStack.push_back(State(op,0)); stateStack.push_back(State(op,0));
return enter_node; // Push into the new node return enter_node; // Push into the new node
@ -1471,7 +1467,7 @@ int4 AncestorRealistic::enterNode(State &state)
do { do {
Varnode *vn = op->getIn(0); Varnode *vn = op->getIn(0);
if ((!vn->isMark())&&(vn->isInput())) { if ((!vn->isMark())&&(vn->isInput())) {
if (vn->isUnaffected()||(!vn->isDirectWrite())) if (!vn->isDirectWrite())
return pop_fail; return pop_fail;
} }
op = vn->getDef(); op = vn->getDef();

View file

@ -770,6 +770,24 @@ void PcodeOpBank::moveSequenceDead(PcodeOp *firstop,PcodeOp *lastop,PcodeOp *pre
deadlist.splice(previter,deadlist,firstop->insertiter,enditer); deadlist.splice(previter,deadlist,firstop->insertiter,enditer);
} }
/// Incidental COPYs are not considered active use of parameter passing Varnodes by
/// parameter analysis algorithms.
/// \param firstop is the start of the range of incidental COPY ops
/// \param lastop is the end of the range of incidental COPY ops
void PcodeOpBank::markIncidentalCopy(PcodeOp *firstop,PcodeOp *lastop)
{
list<PcodeOp *>::iterator iter = firstop->insertiter;
list<PcodeOp *>::iterator enditer = lastop->insertiter;
++enditer;
while(iter != enditer) {
PcodeOp *op = *iter;
++iter;
if (op->code() == CPUI_COPY)
op->setAdditionalFlag(PcodeOp::incidental_copy);
}
}
/// Find the first PcodeOp at or after the given Address assuming they have not /// Find the first PcodeOp at or after the given Address assuming they have not
/// yet been broken up into basic blocks. Take into account delay slots. /// yet been broken up into basic blocks. Take into account delay slots.
/// \param addr is the given Address /// \param addr is the given Address

View file

@ -106,7 +106,8 @@ public:
special_prop = 0x8, ///< Does some special form of datatype propagation special_prop = 0x8, ///< Does some special form of datatype propagation
special_print = 0x10, ///< Op is marked for special printing special_print = 0x10, ///< Op is marked for special printing
modified = 0x20, ///< This op has been modified by the current action modified = 0x20, ///< This op has been modified by the current action
warning = 0x40 ///< Warning has been generated for this op warning = 0x40, ///< Warning has been generated for this op
incidental_copy = 0x80 ///< Treat this as \e incidental for parameter recovery algorithms
}; };
private: private:
TypeOp *opcode; ///< Pointer to class providing behavioral details of the operation TypeOp *opcode; ///< Pointer to class providing behavioral details of the operation
@ -197,6 +198,7 @@ public:
bool hasThisPointer(void) const { return ((addlflags&PcodeOp::has_thisptr)!=0); } ///< Return \b true if this is a call taking 'this' parameter bool hasThisPointer(void) const { return ((addlflags&PcodeOp::has_thisptr)!=0); } ///< Return \b true if this is a call taking 'this' parameter
bool isConstructor(void) const { return ((addlflags&PcodeOp::is_constructor)!=0); } ///< Return \b true if this is call to a constructor bool isConstructor(void) const { return ((addlflags&PcodeOp::is_constructor)!=0); } ///< Return \b true if this is call to a constructor
bool isDestructor(void) const { return ((addlflags&PcodeOp::is_destructor)!=0); } ///< Return \b true if this is call to a destructor bool isDestructor(void) const { return ((addlflags&PcodeOp::is_destructor)!=0); } ///< Return \b true if this is call to a destructor
bool isIncidentalCopy(void) const { return ((addlflags&PcodeOp::incidental_copy)!=0); } ///< Return \b true if \b this COPY is \e incidental
/// \brief Return \b true if output is 1-bit boolean /// \brief Return \b true if output is 1-bit boolean
bool isCalculatedBool(void) const { return ((flags&(PcodeOp::calculated_bool|PcodeOp::booloutput))!=0); } bool isCalculatedBool(void) const { return ((flags&(PcodeOp::calculated_bool|PcodeOp::booloutput))!=0); }
/// \brief Return \b true if we have already examined this cpool /// \brief Return \b true if we have already examined this cpool
@ -267,6 +269,7 @@ public:
void markDead(PcodeOp *op); ///< Mark the given PcodeOp as \e dead void markDead(PcodeOp *op); ///< Mark the given PcodeOp as \e dead
void insertAfterDead(PcodeOp *op,PcodeOp *prev); ///< Insert the given PcodeOp after a point in the \e dead list void insertAfterDead(PcodeOp *op,PcodeOp *prev); ///< Insert the given PcodeOp after a point in the \e dead list
void moveSequenceDead(PcodeOp *firstop,PcodeOp *lastop,PcodeOp *prev); void moveSequenceDead(PcodeOp *firstop,PcodeOp *lastop,PcodeOp *prev);
void markIncidentalCopy(PcodeOp *firstop,PcodeOp *lastop); ///< Mark any COPY ops in the given range as \e incidental
bool empty(void) const { return optree.empty(); } ///< Return \b true if there are no PcodeOps in \b this container bool empty(void) const { return optree.empty(); } ///< Return \b true if there are no PcodeOps in \b this container
PcodeOp *target(const Address &addr) const; ///< Find the first executing PcodeOp for a target address PcodeOp *target(const Address &addr) const; ///< Find the first executing PcodeOp for a target address
PcodeOp *findOp(const SeqNum &num) const; ///< Find a PcodeOp by sequence number PcodeOp *findOp(const SeqNum &num) const; ///< Find a PcodeOp by sequence number

View file

@ -74,6 +74,8 @@ void InjectPayload::restoreXml(const Element *el)
} }
else if (elname == "dynamic") else if (elname == "dynamic")
dynamic = xml_readbool(el->getAttributeValue(i)); dynamic = xml_readbool(el->getAttributeValue(i));
else if (elname == "incidentalcopy")
incidentalCopy = xml_readbool(el->getAttributeValue(i));
} }
const List &list(el->getChildren()); const List &list(el->getChildren());
List::const_iterator iter; List::const_iterator iter;

View file

@ -87,15 +87,17 @@ protected:
string name; ///< Formal name of the payload string name; ///< Formal name of the payload
int4 type; ///< Type of this payload: CALLFIXUP_TYPE, CALLOTHERFIXUP_TYPE, etc. int4 type; ///< Type of this payload: CALLFIXUP_TYPE, CALLOTHERFIXUP_TYPE, etc.
bool dynamic; ///< True if the injection is generated dynamically bool dynamic; ///< True if the injection is generated dynamically
bool incidentalCopy; ///< True if injected COPYs are considered \e incidental
int4 paramshift; ///< Number of parameters shifted in the original call int4 paramshift; ///< Number of parameters shifted in the original call
vector<InjectParameter> inputlist; ///< List of input parameters to this payload vector<InjectParameter> inputlist; ///< List of input parameters to this payload
vector<InjectParameter> output; ///< List of output parameters vector<InjectParameter> output; ///< List of output parameters
static void readParameter(const Element *el,string &name,uint4 &size); static void readParameter(const Element *el,string &name,uint4 &size);
void orderParameters(void); ///< Assign an index to parameters void orderParameters(void); ///< Assign an index to parameters
public: public:
InjectPayload(const string &nm,int4 tp) { name=nm; type=tp; paramshift=0; dynamic = false; } ///< Construct for use with restoreXml InjectPayload(const string &nm,int4 tp) { name=nm; type=tp; paramshift=0; dynamic = false; incidentalCopy = false; } ///< Construct for use with restoreXml
int4 getParamShift(void) const { return paramshift; } ///< Get the number of parameters shifted int4 getParamShift(void) const { return paramshift; } ///< Get the number of parameters shifted
bool isDynamic(void) const { return dynamic; } ///< Return \b true if p-code in the injection is generated dynamically bool isDynamic(void) const { return dynamic; } ///< Return \b true if p-code in the injection is generated dynamically
bool isIncidentalCopy(void) const { return incidentalCopy; }
int4 sizeInput(void) const { return inputlist.size(); } ///< Return the number of input parameters int4 sizeInput(void) const { return inputlist.size(); } ///< Return the number of input parameters
int4 sizeOutput(void) const { return output.size(); } ///< Return the number of output parameters int4 sizeOutput(void) const { return output.size(); } ///< Return the number of output parameters
InjectParameter &getInput(int4 i) { return inputlist[i]; } ///< Get the i-th input parameter InjectParameter &getInput(int4 i) { return inputlist[i]; } ///< Get the i-th input parameter

View file

@ -212,6 +212,9 @@
<optional> <optional>
<attribute name="dynamic"/> <attribute name="dynamic"/>
</optional> </optional>
<optional>
<attribute name="incidentalcopy"/>
</optional>
<interleave> <interleave>
<zeroOrMore> <zeroOrMore>
<element name="input"><ref name="inject_parameter_type"/></element> <element name="input"><ref name="inject_parameter_type"/></element>

View file

@ -120,9 +120,12 @@ public class PcodeDataTypeManager {
} }
/** /**
* Find a data type with the given name. * Find a base/built-in data-type with the given name and/or id. If an id is provided and
* @param nm name of data type * a corresponding data-type exists, this data-type is returned. Otherwise the first
* @return may return null if no data type exists with the given name * built-in data-type with a matching name is returned
* @param nm name of data-type
* @param idstr is an optional string containing a data-type id number
* @return the data-type object or null if no matching data-type exists
*/ */
public DataType findBaseType(String nm, String idstr) { public DataType findBaseType(String nm, String idstr) {
long id = 0; long id = 0;
@ -242,8 +245,13 @@ public class PcodeDataTypeManager {
} }
/** /**
* @param type to be converted * Generate an XML tag describing the given data-type. Most data-types produce a <type> tag,
* @return either a typeref tag giving the name, or a full type tag * fully describing the data-type. Where possible a <typeref> tag is produced, which just gives
* the name of the data-type, deferring a full description of the data-type. For certain simple or
* nameless data-types, a <type> tag is emitted giving a full description.
* @param type is the data-type to be converted
* @param size is the size in bytes of the specific instance of the data-type
* @return a StringBuilder containing the XML tag
*/ */
public StringBuilder buildTypeRef(DataType type, int size) { public StringBuilder buildTypeRef(DataType type, int size) {
if (type != null && type.getDataTypeManager() != progDataTypes) { if (type != null && type.getDataTypeManager() != progDataTypes) {
@ -424,7 +432,7 @@ public class PcodeDataTypeManager {
resBuf.append(">\n"); resBuf.append(">\n");
for (long key : keys) { for (long key : keys) {
resBuf.append("<val"); resBuf.append("<val");
SpecXmlUtils.encodeStringAttribute(resBuf, "name", enumDt.getName(key)); SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", enumDt.getName(key));
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "value", key); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "value", key);
resBuf.append("/>"); resBuf.append("/>");
} }