mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-16 15:40:14 +00:00
dominant COPY model working
This commit is contained in:
parent
908632eac0
commit
faa69124ab
@ -3579,6 +3579,7 @@ bool ActionCopyMarker::shadowedVarnode(const Varnode *vn)
|
||||
int4 ActionCopyMarker::apply(Funcdata &data)
|
||||
|
||||
{
|
||||
vector<HighVariable *> multiCopy;
|
||||
list<PcodeOp *>::const_iterator iter;
|
||||
PcodeOp *op;
|
||||
HighVariable *h1,*h2,*h3;
|
||||
@ -3596,6 +3597,12 @@ int4 ActionCopyMarker::apply(Funcdata &data)
|
||||
count += 1;
|
||||
}
|
||||
else { // COPY between different HighVariables
|
||||
if (!h1->hasCopyIn1()) { // If this is the first COPY we've seen for this high
|
||||
h1->setCopyIn1(); // Mark it
|
||||
multiCopy.push_back(h1);
|
||||
}
|
||||
else
|
||||
h1->setCopyIn2(); // This is at least the second COPY we've seen
|
||||
if (v1->hasNoDescend()) { // Don't print shadow assignments
|
||||
if (shadowedVarnode(v1)) {
|
||||
data.opSetFlag(op, PcodeOp::nonprinting);
|
||||
@ -3635,6 +3642,12 @@ int4 ActionCopyMarker::apply(Funcdata &data)
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(int4 i=0;i<multiCopy.size();++i) {
|
||||
HighVariable *high = multiCopy[i];
|
||||
if (high->hasCopyIn2())
|
||||
data.getMerge().processHighRedundantCopy(high);
|
||||
high->clearCopyIns();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -959,6 +959,19 @@ bool Merge::checkCopyPair(HighVariable *high,PcodeOp *domOp,PcodeOp *subOp)
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Try to replace a set of COPYs from the same Varnode with a single dominant COPY
|
||||
///
|
||||
/// All the COPY outputs must be instances of the same HighVariable (not the same Varnode).
|
||||
/// Either an existing COPY dominates all the others, or a new dominating COPY is constructed.
|
||||
/// The read locations of all other COPY outputs are replaced with the output of the dominating
|
||||
/// COPY, if it does not cause intersections in the HighVariable's Cover. Because of
|
||||
/// intersections, replacement may fail or partially succeed. Replacement only happens with
|
||||
/// COPY outputs that are temporary registers. The cover of the HighVariable may be extended
|
||||
/// because of a new COPY output instance.
|
||||
/// \param high is the HighVariable being copied to
|
||||
/// \param copy is the list of COPY ops into the HighVariable
|
||||
/// \param pos is the index of the first COPY from the specific input Varnode
|
||||
/// \param size is the number of COPYs (in sequence) from the same specific Varnode
|
||||
void Merge::buildDominantCopy(HighVariable *high,vector<PcodeOp *> ©,int4 pos,int4 size)
|
||||
|
||||
{
|
||||
@ -1067,24 +1080,60 @@ void Merge::markRedundantCopies(HighVariable *high,vector<PcodeOp *> ©,int4
|
||||
}
|
||||
}
|
||||
|
||||
void Merge::processCopyTrimsForHigh(HighVariable *high)
|
||||
/// \brief Find all the COPY ops into the given HighVariable
|
||||
///
|
||||
/// Collect all the COPYs whose output is the given HighVariable but
|
||||
/// the input is from a different HighVariable. Returned COPYs are sorted
|
||||
/// first by the input Varnode then by block order.
|
||||
/// \param high is the given HighVariable
|
||||
/// \param copyIns will hold the list of COPYs
|
||||
/// \param filterTemps is \b true if COPYs must have a temporary output
|
||||
void Merge::findAllIntoCopies(HighVariable *high,vector<PcodeOp *> ©Ins,bool filterTemps)
|
||||
|
||||
{
|
||||
vector<PcodeOp *> copyIns;
|
||||
|
||||
// Find all the COPY ops into this HighVariable from a different HighVariable
|
||||
for(int4 i=0;i<high->numInstances();++i) {
|
||||
Varnode *vn = high->getInstance(i);
|
||||
if (!vn->isWritten()) continue;
|
||||
PcodeOp *op = vn->getDef();
|
||||
if (op->code() != CPUI_COPY) continue;
|
||||
if (op->getIn(0)->getHigh() == high) continue;
|
||||
if (op->getOut()->getSpace()->getType() != IPTR_INTERNAL) continue;
|
||||
if (filterTemps && op->getOut()->getSpace()->getType() != IPTR_INTERNAL) continue;
|
||||
copyIns.push_back(op);
|
||||
}
|
||||
|
||||
// Group COPYs based on the incoming Varnode
|
||||
// Group COPYs based on the incoming Varnode then block order
|
||||
sort(copyIns.begin(),copyIns.end(),compareCopyByInVarnode);
|
||||
}
|
||||
|
||||
void Merge::processHighDominantCopy(HighVariable *high)
|
||||
|
||||
{
|
||||
vector<PcodeOp *> copyIns;
|
||||
|
||||
findAllIntoCopies(high,copyIns,true); // Get all COPYs into this with temporary output
|
||||
if (copyIns.size() < 2) return;
|
||||
int4 pos = 0;
|
||||
while(pos < copyIns.size()) {
|
||||
// Find a group of COPYs coming from the same Varnode
|
||||
Varnode *inVn = copyIns[pos]->getIn(0);
|
||||
int4 sz = 1;
|
||||
while(pos + sz < copyIns.size()) {
|
||||
Varnode *nextVn = copyIns[pos+sz]->getIn(0);
|
||||
if (nextVn != inVn) break;
|
||||
sz += 1;
|
||||
}
|
||||
if (sz > 1) // If there is more than one COPY in a group
|
||||
buildDominantCopy(high, copyIns, pos, sz); // Try to construct a dominant COPY
|
||||
pos += sz;
|
||||
}
|
||||
}
|
||||
|
||||
void Merge::processHighRedundantCopy(HighVariable *high)
|
||||
|
||||
{
|
||||
vector<PcodeOp *> copyIns;
|
||||
|
||||
findAllIntoCopies(high,copyIns,false);
|
||||
if (copyIns.size() < 2) return;
|
||||
int4 pos = 0;
|
||||
while(pos < copyIns.size()) {
|
||||
// Find a group of COPYs coming from the same Varnode
|
||||
@ -1096,7 +1145,6 @@ void Merge::processCopyTrimsForHigh(HighVariable *high)
|
||||
sz += 1;
|
||||
}
|
||||
if (sz > 1) { // If there is more than one COPY in a group
|
||||
buildDominantCopy(high, copyIns, pos, sz);
|
||||
markRedundantCopies(high, copyIns, pos, sz);
|
||||
}
|
||||
pos += sz;
|
||||
@ -1110,18 +1158,20 @@ void Merge::processCopyTrims(void)
|
||||
|
||||
for(int4 i=0;i<copyTrims.size();++i) {
|
||||
HighVariable *high = copyTrims[i]->getOut()->getHigh();
|
||||
if (high->hasCopyIn()) { // If we've seen COPYs into this high before
|
||||
if (!high->isCopyProcessed()) { // and we haven't processed it before,
|
||||
multiCopy.push_back(high); // slate the high for copy trim processing
|
||||
high->setCopyProcessed();
|
||||
}
|
||||
if (!high->hasCopyIn1()) {
|
||||
multiCopy.push_back(high);
|
||||
high->setCopyIn1();
|
||||
}
|
||||
else
|
||||
high->setCopyIn();
|
||||
high->setCopyIn2();
|
||||
}
|
||||
copyTrims.clear();
|
||||
for(int4 i=0;i<multiCopy.size();++i)
|
||||
processCopyTrimsForHigh(multiCopy[i]);
|
||||
for(int4 i=0;i<multiCopy.size();++i) {
|
||||
HighVariable *high = multiCopy[i];
|
||||
if (high->hasCopyIn2()) // If the high has at least 2 COPYs into it
|
||||
processHighDominantCopy(high); // Try to replace with a dominant copy
|
||||
high->clearCopyIns();
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Perform low-level details of merging two HighVariables if possible
|
||||
|
@ -91,6 +91,7 @@ class Merge {
|
||||
static void findSingleCopy(HighVariable *high,vector<Varnode *> &singlelist);
|
||||
static bool compareHighByBlock(const HighVariable *a,const HighVariable *b);
|
||||
static bool compareCopyByInVarnode(PcodeOp *op1,PcodeOp *op2);
|
||||
static void findAllIntoCopies(HighVariable *high,vector<PcodeOp *> ©Ins,bool filterTemps);
|
||||
void collectCovering(vector<Varnode *> &vlist,HighVariable *high,PcodeOp *op);
|
||||
bool collectCorrectable(const vector<Varnode *> &vlist,list<PcodeOp *> &oplist,vector<int4> &slotlist,
|
||||
PcodeOp *op);
|
||||
@ -109,7 +110,7 @@ class Merge {
|
||||
bool checkCopyPair(HighVariable *high,PcodeOp *domOp,PcodeOp *subOp);
|
||||
void buildDominantCopy(HighVariable *high,vector<PcodeOp *> ©,int4 pos,int4 size);
|
||||
void markRedundantCopies(HighVariable *high,vector<PcodeOp *> ©,int4 pos,int4 size);
|
||||
void processCopyTrimsForHigh(HighVariable *high);
|
||||
void processHighDominantCopy(HighVariable *high);
|
||||
public:
|
||||
Merge(Funcdata &fd) : data(fd) {} ///< Construct given a specific function
|
||||
bool intersection(HighVariable *a,HighVariable *b);
|
||||
@ -124,6 +125,7 @@ public:
|
||||
void mergeAdjacent(void);
|
||||
bool hideShadows(HighVariable *high);
|
||||
void processCopyTrims(void);
|
||||
void processHighRedundantCopy(HighVariable *high);
|
||||
};
|
||||
|
||||
/// \brief Compare HighVariables by the blocks they cover
|
||||
|
@ -46,8 +46,8 @@ public:
|
||||
flagsdirty = 1, ///< Boolean properties for the HighVariable are dirty
|
||||
typedirty = 2, ///< The data-type for the HighVariable is dirty
|
||||
coverdirty = 4, ///< The cover for the HighVariable is dirty
|
||||
copy_in = 8, ///< There exist COPY ops into \b this HighVariable from other HighVariables
|
||||
copy_processed = 16 ///< COPY ops into \b this HighVariable have been analyzed
|
||||
copy_in1 = 8, ///< There exists at least 1 COPY into \b this HighVariable from other HighVariables
|
||||
copy_in2 = 16 ///< There exists at least 2 COPYs into \b this HighVariable from other HighVariables
|
||||
};
|
||||
private:
|
||||
friend class Merge;
|
||||
@ -63,10 +63,6 @@ private:
|
||||
void updateFlags(void) const; ///< (Re)derive boolean properties of \b this from the member Varnodes
|
||||
void updateCover(void) const; ///< (Re)derive the cover of \b this from the member Varnodes
|
||||
void updateType(void) const; ///< (Re)derive the data-type for \b this from the member Varnodes
|
||||
void setCopyIn(void) const { highflags |= copy_in; } ///< Mark the existence of COPY ops into \b this
|
||||
bool hasCopyIn(void) const { return ((highflags©_in)!=0); } ///< Are there COPY ops into \b this
|
||||
bool isCopyProcessed(void) const { return ((highflags©_processed)!=0); } ///< Have COPY ops into \b this been processed
|
||||
void setCopyProcessed(void) const { highflags |= copy_processed; } ///< Mark that \b this has had its COPY ins processed
|
||||
public:
|
||||
HighVariable(Varnode *vn); ///< Construct a HighVariable with a single member Varnode
|
||||
Datatype *getType(void) const { updateType(); return type; } ///< Get the data-type
|
||||
@ -114,6 +110,11 @@ public:
|
||||
void setMark(void) const { flags |= Varnode::mark; } ///< Set the mark on this variable
|
||||
void clearMark(void) const { flags &= ~Varnode::mark; } ///< Clear the mark on this variable
|
||||
bool isMark(void) const { return ((flags&Varnode::mark)!=0); } ///< Return \b true if \b this is marked
|
||||
void setCopyIn1(void) const { highflags |= copy_in1; } ///< Mark the existence of one COPY into \b this
|
||||
void setCopyIn2(void) const { highflags |= copy_in2; } ///< Mark the existence of two COPYs into \b this
|
||||
void clearCopyIns(void) const { highflags &= ~(copy_in1 | copy_in2); } ///< Clear marks indicating COPYs into \b this
|
||||
bool hasCopyIn1(void) const { return ((highflags©_in1)!=0); } ///< Is there at least one COPY into \b this
|
||||
bool hasCopyIn2(void) const { return ((highflags©_in2)!=0); } ///< Is there at least two COPYs into \b this
|
||||
|
||||
/// \brief Determine if \b this HighVariable has an associated cover.
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user