fixed constraint finding corner case

This commit is contained in:
caheckman 2019-06-15 18:22:28 -04:00
parent e506f27b31
commit d51d8259b5
2 changed files with 43 additions and 15 deletions

View File

@ -2132,8 +2132,8 @@ void ValueSetSolver::applyConstraints(Varnode *vn,int4 type,const CircleRange &r
generateFalseEquation(outVn, op, slot, type, range);
continue;
}
// else
// curBlock = curBlock->getIn(slot); // MULTIEQUAL input is really only from one in-block
else
curBlock = curBlock->getIn(slot); // MULTIEQUAL input is really only from one in-block
}
for(;;) {
if (curBlock == trueBlock) {
@ -2230,26 +2230,39 @@ void ValueSetSolver::generateConstraints(const vector<Varnode *> &worklist,const
{
vector<FlowBlock *> blockList;
// Collect all blocks that contain a system op or dominate a container
// Collect all blocks that contain a system op (input) or dominate a container
for(int4 i=0;i<worklist.size();++i) {
PcodeOp *op = worklist[i]->getDef();
if (op == (PcodeOp *)0) continue;
FlowBlock *bl = op->getParent();
while(bl != (FlowBlock *)0) {
if (bl->isMark()) break;
bl->setMark();
blockList.push_back(bl);
bl = bl->getImmedDom();
if (op->code() == CPUI_MULTIEQUAL) {
for(int4 j=0;j<bl->sizeIn();++j) {
FlowBlock *curBl = bl->getIn(j);
do {
if (curBl->isMark()) break;
curBl->setMark();
blockList.push_back(curBl);
curBl = curBl->getImmedDom();
} while(curBl != (FlowBlock *)0);
}
}
else {
do {
if (bl->isMark()) break;
bl->setMark();
blockList.push_back(bl);
bl = bl->getImmedDom();
} while(bl != (FlowBlock *)0);
}
}
for(int4 i=0;i<reads.size();++i) {
FlowBlock *bl = reads[i]->getParent();
while(bl != (FlowBlock *)0) {
do {
if (bl->isMark()) break;
bl->setMark();
blockList.push_back(bl);
bl = bl->getImmedDom();
}
} while(bl != (FlowBlock *)0);
}
for(int4 i=0;i<blockList.size();++i)
blockList[i]->clearMark();

View File

@ -150,8 +150,8 @@ public:
int4 getTypeCode(void) const { return typeCode; } ///< Return '0' for normal constant, '1' for spacebase relative
Varnode *getVarnode(void) const { return vn; } ///< Get the Varnode attached to \b this ValueSet
const CircleRange &getRange(void) const { return range; } ///< Get the actual range of values
bool isLeftStable(void) const { return leftIsStable; }
bool isRightStable(void) const { return rightIsStable; }
bool isLeftStable(void) const { return leftIsStable; } ///< Return \b true if the left boundary hasn't been changing
bool isRightStable(void) const { return rightIsStable; } ///< Return \b true if the right boundary hasn't been changing
void printRaw(ostream &s) const; ///< Write a text description of \b to the given stream
};
@ -188,12 +188,17 @@ class ValueSetRead {
public:
int4 getTypeCode(void) const { return typeCode; } ///< Return '0' for normal constant, '1' for spacebase relative
const CircleRange &getRange(void) const { return range; } ///< Get the actual range of values
bool isLeftStable(void) const { return leftIsStable; }
bool isRightStable(void) const { return rightIsStable; }
bool isLeftStable(void) const { return leftIsStable; } ///< Return \b true if the left boundary hasn't been changing
bool isRightStable(void) const { return rightIsStable; } ///< Return \b true if the right boundary hasn't been changing
void compute(void); ///< Compute \b this value set
void printRaw(ostream &s) const; ///< Write a text description of \b to the given stream
};
/// \brief Class holding a particular widening strategy for the ValueSetSolver iteration algorithm
///
/// This obects gets to decide when a value set gets \e frozen (checkFreeze()), meaning the set
/// doesn't change for the remaining iteration steps. It also gets to decide when and by how much
/// value sets get artificially increased in size to accelerate reaching their stable state (doWidening()).
class Widener {
public:
virtual ~Widener(void) {} ///< Destructor
@ -237,6 +242,13 @@ public:
virtual bool doWidening(const ValueSet &valueSet,CircleRange &range,const CircleRange &newRange);
};
/// \brief Class for freezing value sets at a specific iteration (to accelerate convergence)
///
/// The value sets don't reach a true stable state but instead lock in a description of the
/// first few values that \e reach a given Varnode. The ValueSetSolver does normal iteration,
/// but individual ValueSets \e freeze after a specific number of iterations (3 by default),
/// instead of growing to a true stable state. This gives evidence of iteration in the underlying
/// code, showing the initial value and frequently the step size.
class WidenerNone : public Widener {
int4 freezeIteration; ///< The iteration at which all change ceases
public:
@ -246,7 +258,7 @@ public:
virtual bool doWidening(const ValueSet &valueSet,CircleRange &range,const CircleRange &newRange);
};
/// \brief Class the determines a ValueSet for each Varnode in a data-flow system
/// \brief Class that determines a ValueSet for each Varnode in a data-flow system
///
/// This class uses \e value \e set \e analysis to calculate (an overestimation of)
/// the range of values that can reach each Varnode. The system is formed by providing
@ -254,6 +266,9 @@ public:
/// This creates a system of Varnodes (within the single function) that can flow to the sinks.
/// Running the method solve() does the analysis, and the caller can examine the results
/// by examining the ValueSet attached to any of the Varnodes in the system (via Varnode::getValueSet()).
/// The ValueSetSolver::solve() starts with minimal value sets and does iteration steps by pushing
/// them through the PcodeOps until stability is reached. A Widener object is passed to solve()
/// which selects the specific strategy for accelerating convergence.
class ValueSetSolver {
/// \brief An iterator over out-bound edges for a single ValueSet node in a data-flow system
///