GP-4960 Recursively walk implied Varnodes when building a Cover

This commit is contained in:
caheckman 2024-09-30 22:53:40 +00:00
parent a3d0b40f36
commit 4eef52216d
4 changed files with 35 additions and 34 deletions

View File

@ -3402,8 +3402,7 @@ int4 ActionMarkImplied::apply(Funcdata &data)
{ {
VarnodeLocSet::const_iterator viter; VarnodeLocSet::const_iterator viter;
list<PcodeOp *>::const_iterator oiter; list<PcodeOp *>::const_iterator oiter;
Varnode *vn,*vncur,*defvn,*outvn; Varnode *vn,*vncur,*outvn;
PcodeOp *op;
vector<DescTreeElement> varstack; // Depth first varnode traversal stack vector<DescTreeElement> varstack; // Depth first varnode traversal stack
for(viter=data.beginLoc();viter!=data.endLoc();++viter) { for(viter=data.beginLoc();viter!=data.endLoc();++viter) {
@ -3420,16 +3419,9 @@ int4 ActionMarkImplied::apply(Funcdata &data)
if (!checkImpliedCover(data,vncur)) // Can this variable be implied if (!checkImpliedCover(data,vncur)) // Can this variable be implied
vncur->setExplicit(); // if not, mark explicit vncur->setExplicit(); // if not, mark explicit
else { else {
vncur->setImplied(); // Mark as implied Merge::markImplied(vncur);
op = vncur->getDef();
// setting the implied type is now taken care of by ActionSetCasts // setting the implied type is now taken care of by ActionSetCasts
// vn->updatetype(op->outputtype_token(),false,false); // implied must have parsed type // vn->updatetype(op->outputtype_token(),false,false); // implied must have parsed type
// Back propagate varnode's cover to inputs of defining op
for(int4 i=0;i<op->numInput();++i) {
defvn = op->getIn(i);
if (!defvn->hasCover()) continue;
data.getMerge().inflate(defvn,vncur->getHigh());
}
} }
varstack.pop_back(); varstack.pop_back();
} }

View File

@ -477,11 +477,22 @@ void Cover::merge(const Cover &op2)
void Cover::rebuild(const Varnode *vn) void Cover::rebuild(const Varnode *vn)
{ {
list<PcodeOp *>::const_iterator iter; vector<const Varnode *> path(1,vn);
int4 pos = 0;
addDefPoint(vn); addDefPoint(vn);
for(iter=vn->beginDescend();iter!=vn->endDescend();++iter) do {
addRefPoint(*iter,vn); const Varnode *curVn = path[pos];
pos += 1;
list<PcodeOp *>::const_iterator iter;
for(iter=curVn->beginDescend();iter!=curVn->endDescend();++iter) {
const PcodeOp *op = *iter;
addRefPoint(op,vn);
const Varnode *outVn = op->getOut();
if (outVn != (Varnode *)0 && outVn->isImplied())
path.push_back(outVn);
}
} while(pos < path.size());
} }
/// Any previous cover is removed. Calling this with an /// Any previous cover is removed. Calling this with an

View File

@ -1586,24 +1586,22 @@ void Merge::clear(void)
stackAffectingOps.clear(); stackAffectingOps.clear();
} }
/// \brief Inflate the Cover of a given Varnode with a HighVariable /// \brief Mark the given Varnode as \e implied
/// ///
/// An expression involving a HighVariable can be propagated to all the read sites of the /// The covers of the immediate Varnodes involved in the expression are marked as dirty.
/// output Varnode of the expression if the Varnode Cover can be \b inflated to include the /// This assumes covers for the whole expression are ultimately marked because all its internal Varnodes
/// Cover of the HighVariable, even though the Varnode is not part of the HighVariable. /// are passed to this method.
/// This routine performs the inflation, assuming an intersection test is already performed. /// \param vn is the given Varnode being marked as \e implied
/// \param a is the given Varnode to inflate void Merge::markImplied(Varnode *vn)
/// \param high is the HighVariable to inflate with
void Merge::inflate(Varnode *a,HighVariable *high)
{ {
testCache.updateHigh(a->getHigh()); vn->setImplied(); // Mark as implied
testCache.updateHigh(high); PcodeOp *op = vn->getDef();
for(int4 i=0;i<high->numInstances();++i) { for(int4 i=0;i<op->numInput();++i) {
Varnode *b = high->getInstance(i); Varnode *defvn = op->getIn(i);
a->cover->merge(*b->cover); if (!defvn->hasCover()) continue;
defvn->setFlags(Varnode::coverdirty);
} }
a->getHigh()->coverDirty();
} }
/// \brief Test if we can inflate the Cover of the given Varnode without incurring intersections /// \brief Test if we can inflate the Cover of the given Varnode without incurring intersections

View File

@ -117,8 +117,8 @@ class Merge {
public: public:
Merge(Funcdata &fd) : data(fd), stackAffectingOps(fd), testCache(stackAffectingOps) {} ///< Construct given a specific function Merge(Funcdata &fd) : data(fd), stackAffectingOps(fd), testCache(stackAffectingOps) {} ///< Construct given a specific function
void clear(void); void clear(void);
static void markImplied(Varnode *vn);
bool inflateTest(Varnode *a,HighVariable *high); bool inflateTest(Varnode *a,HighVariable *high);
void inflate(Varnode *a,HighVariable *high);
bool mergeTest(HighVariable *high,vector<HighVariable *> &tmplist); bool mergeTest(HighVariable *high,vector<HighVariable *> &tmplist);
void mergeOpcode(OpCode opc); void mergeOpcode(OpCode opc);