dominant COPY model working

This commit is contained in:
caheckman 2019-05-02 08:59:41 -04:00
parent 908632eac0
commit faa69124ab
4 changed files with 89 additions and 23 deletions

View File

@ -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;
}

View File

@ -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 *> &copy,int4 pos,int4 size)
{
@ -1067,24 +1080,60 @@ void Merge::markRedundantCopies(HighVariable *high,vector<PcodeOp *> &copy,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 *> &copyIns,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

View File

@ -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 *> &copyIns,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 *> &copy,int4 pos,int4 size);
void markRedundantCopies(HighVariable *high,vector<PcodeOp *> &copy,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

View File

@ -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&copy_in)!=0); } ///< Are there COPY ops into \b this
bool isCopyProcessed(void) const { return ((highflags&copy_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&copy_in1)!=0); } ///< Is there at least one COPY into \b this
bool hasCopyIn2(void) const { return ((highflags&copy_in2)!=0); } ///< Is there at least two COPYs into \b this
/// \brief Determine if \b this HighVariable has an associated cover.
///