mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Extending incidental copy
This commit is contained in:
parent
4fc507f711
commit
00ac31c788
8 changed files with 39 additions and 12 deletions
|
@ -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());
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -765,6 +765,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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue