reads and constraint adjustments

This commit is contained in:
caheckman 2019-06-04 13:45:14 -04:00
parent 0c5bd081c5
commit 9cdd91a053
5 changed files with 99 additions and 27 deletions

View file

@ -369,6 +369,31 @@ bool FlowBlock::dominates(const FlowBlock *subBlock) const
return false;
}
/// \brief Check if the condition from the given block holds for \b this block
///
/// We assume the given block has 2 out-edges and that \b this block is immediately reached by
/// one of these two edges. Some condition holds when traversing the out-edge to \b this, and the complement
/// of the condition holds for traversing the other out-edge. We verify that the condition holds for
/// this entire block. More specifically, we check that that there is no path to \b this through the
/// sibling edge, where the complement of the condition holds (unless we loop back through the conditional block).
/// \param cond is the conditional block with 2 out-edges
/// \return \b true if the condition holds for this block
bool FlowBlock::restrictedByConditional(const FlowBlock *cond) const
{
if (sizeIn() == 1) return true; // Its impossible for any path to come through sibling to this
if (getImmedDom() != cond) return false; // This is not dominated by conditional block at all
for(int4 i=0;i<sizeIn();++i) {
const FlowBlock *inBlock = getIn(i);
if (inBlock == cond) continue; // The unique edge from cond to this
while(inBlock != this) {
if (inBlock == cond) return false; // Must have come through sibling
inBlock = inBlock->getImmedDom();
}
}
return true;
}
/// \return \b true if \b this is the top of a loop
bool FlowBlock::hasLoopIn(void) const

View file

@ -215,6 +215,7 @@ public:
FlowBlock *getFrontLeaf(void); ///< Get the first leaf FlowBlock
int4 calcDepth(const FlowBlock *leaf) const; ///< Get the depth of the given component FlowBlock
bool dominates(const FlowBlock *subBlock) const; ///< Does \b this block dominate the given block
bool restrictedByConditional(const FlowBlock *cond) const;
int4 sizeOut(void) const { return outofthis.size(); } ///< Get the number of out edges
int4 sizeIn(void) const { return intothis.size(); } ///< Get the number of in edges
bool hasLoopIn(void) const; ///< Is there a looping edge coming into \b this block

View file

@ -3246,7 +3246,7 @@ int4 ActionConditionalConst::apply(Funcdata &data)
if (flipEdge)
constEdge = 1 - constEdge;
FlowBlock *constBlock = bl->getOut(constEdge);
if (constBlock->sizeIn() != 1) continue; // Must only be one path to constant block directly through CBRANCH
if (!constBlock->restrictedByConditional(bl)) continue; // Make sure condition holds
propagateConstant(varVn,constVn,constBlock,data);
}
return 0;

View file

@ -1927,44 +1927,73 @@ void ValueSetSolver::establishTopologicalOrder(void)
/// \param vn is the given Varnode
/// \param type is the constraint characteristic
/// \param range is the known constraint (assuming the \b true branch was taken)
/// \param splitPoint is the basic block making the conditional branch
void ValueSetSolver::applyConstraints(Varnode *vn,int4 type,const CircleRange &range,FlowBlock *splitPoint)
/// \param cbranch is conditional branch creating the constraint
void ValueSetSolver::applyConstraints(Varnode *vn,int4 type,const CircleRange &range,PcodeOp *cbranch)
{
FlowBlock *splitPoint = cbranch->getParent();
FlowBlock *trueBlock,*falseBlock;
if (cbranch->isBooleanFlip()) {
trueBlock = splitPoint->getFalseOut();
falseBlock = splitPoint->getTrueOut();
}
else {
trueBlock = splitPoint->getTrueOut();
falseBlock = splitPoint->getFalseOut();
}
// Check if the only path to trueBlock or falseBlock is via a splitPoint out-edge induced by the condition
bool trueIsRestricted = trueBlock->restrictedByConditional(splitPoint);
bool falseIsRestricted = falseBlock->restrictedByConditional(splitPoint);
list<PcodeOp *>::const_iterator iter;
FlowBlock *defBlock = (FlowBlock *)0;
if (vn->isWritten()) {
defBlock = vn->getDef()->getParent();
ValueSet *vSet = vn->getValueSet();
if (vSet->opCode == CPUI_MULTIEQUAL) {
vSet->addLandmark(type,range); // Leave landmark for widening
}
}
FlowBlock *trueBlock = splitPoint->getTrueOut();
FlowBlock *falseBlock = splitPoint->getFalseOut();
for(iter=vn->beginDescend();iter!=vn->endDescend();++iter) {
PcodeOp *op = *iter;
if (op->isMark()) { // Special read site being tracked
readNodes[op->getSeqNum()].addEquation(op->getSlot(vn), type, range);
continue;
Varnode *outVn = (Varnode *)0;
if (!op->isMark()) { // If this is not a special read site
outVn = op->getOut(); // Make sure there is a Varnode in the system
if (outVn == (Varnode *)0) continue;
if (!outVn->isMark()) continue;
}
Varnode *outVn = op->getOut();
if (outVn == (Varnode *)0) continue;
if (!outVn->isMark()) continue;
FlowBlock *curBlock = op->getParent();
int4 slot = op->getSlot(vn);
for(;;) {
if (curBlock == trueBlock) {
outVn->getValueSet()->addEquation(op->getSlot(vn), type, range);
if (!trueIsRestricted) {
// If its possible that both the true and false edges can reach trueBlock
// then the only input we can restrict is a MULTIEQUAL input along the exact true edge
if (op->code() != CPUI_MULTIEQUAL) break;
if (op->getParent() != trueBlock) break;
if (trueBlock->getIn(slot) != splitPoint) break;
}
if (outVn != (Varnode *)0)
outVn->getValueSet()->addEquation(slot, type, range);
else
readNodes[op->getSeqNum()].addEquation(slot, type, range); // Special read site
break;
}
else if (curBlock == falseBlock) {
if (!falseIsRestricted) {
// If its possible that both the true and false edges can reach falseBlock
// then the only input we can restrict is a MULTIEQUAL input along the exact false edge
if (op->code() != CPUI_MULTIEQUAL) break;
if (op->getParent() != falseBlock) break;
if (falseBlock->getIn(slot) != splitPoint) break;
}
CircleRange falseRange(range);
falseRange.invert();
outVn->getValueSet()->addEquation(op->getSlot(vn), type, falseRange);
if (outVn != (Varnode *)0)
outVn->getValueSet()->addEquation(slot, type, falseRange);
else
readNodes[op->getSeqNum()].addEquation(slot, type, falseRange); // Special read site
break;
}
else if (curBlock == splitPoint || curBlock == (FlowBlock *)0
|| curBlock == defBlock)
else if (curBlock == splitPoint || curBlock == (FlowBlock *)0)
break;
curBlock = curBlock->getImmedDom();
}
@ -1980,8 +2009,8 @@ void ValueSetSolver::applyConstraints(Varnode *vn,int4 type,const CircleRange &r
/// \param lift is the given range that will be lifted
/// \param startVn is the starting Varnode
/// \param endVn is the given ending Varnode in the system
/// \param splitPoint is the point where control-flow splits
void ValueSetSolver::constraintsFromPath(int4 type,CircleRange &lift,Varnode *startVn,Varnode *endVn,FlowBlock *splitPoint)
/// \param cbranch is the PcodeOp causing the control-flow split
void ValueSetSolver::constraintsFromPath(int4 type,CircleRange &lift,Varnode *startVn,Varnode *endVn,PcodeOp *cbranch)
{
while(startVn != endVn) {
@ -1991,7 +2020,7 @@ void ValueSetSolver::constraintsFromPath(int4 type,CircleRange &lift,Varnode *st
}
for(;;) {
Varnode *constVn;
applyConstraints(endVn,type,lift,splitPoint);
applyConstraints(endVn,type,lift,cbranch);
if (!endVn->isWritten()) break;
PcodeOp *op = endVn->getDef();
if (op->isCall() || op->isMarker()) break;
@ -2032,7 +2061,7 @@ void ValueSetSolver::constraintsFromCBranch(PcodeOp *cbranch)
if (vn->isMark()) {
CircleRange lift(true);
Varnode *startVn = cbranch->getIn(1);
constraintsFromPath(0,lift,startVn,vn,cbranch->getParent());
constraintsFromPath(0,lift,startVn,vn,cbranch);
}
}
@ -2043,7 +2072,8 @@ void ValueSetSolver::constraintsFromCBranch(PcodeOp *cbranch)
/// - Which applies at a particular \e read of the Varnode
///
/// \param worklist is the set of Varnodes in the data-flow system (all marked)
void ValueSetSolver::generateConstraints(vector<Varnode *> &worklist)
/// \param reads is the additional set of PcodeOps that read a Varnode from the system
void ValueSetSolver::generateConstraints(const vector<Varnode *> &worklist,const vector<PcodeOp *> &reads)
{
vector<FlowBlock *> blockList;
@ -2065,6 +2095,22 @@ void ValueSetSolver::generateConstraints(vector<Varnode *> &worklist)
break;
}
}
for(int4 i=0;i<reads.size();++i) {
BlockBasic *bl = (BlockBasic *)reads[i]->getParent()->getImmedDom();
while(bl != (FlowBlock *)0) {
if (!bl->isMark()) {
bl->setMark();
blockList.push_back(bl);
PcodeOp *lastOp = bl->lastOp();
if (lastOp != (PcodeOp *)0 && lastOp->code() == CPUI_CBRANCH) {
constraintsFromCBranch(lastOp);
}
bl = (BlockBasic *)bl->getImmedDom();
}
else
break;
}
}
for(int4 i=0;i<blockList.size();++i)
blockList[i]->clearMark();
}
@ -2158,7 +2204,7 @@ void ValueSetSolver::generateRelativeConstraint(PcodeOp *compOp,PcodeOp *cbranch
endVn = op->getIn(0);
}
if (endVn != (Varnode *)0)
constraintsFromPath(typeCode,lift,endVn,endVn,cbranch->getParent());
constraintsFromPath(typeCode,lift,endVn,endVn,cbranch);
}
/// Given a set of sinks, find all the Varnodes that flow directly into them.
@ -2242,7 +2288,7 @@ void ValueSetSolver::establishValueSets(const vector<Varnode *> &sinks,const vec
}
}
}
generateConstraints(worklist);
generateConstraints(worklist,reads);
for(int4 i=0;i<reads.size();++i)
reads[i]->clearMark(); // Clear marks on read ops

View file

@ -226,10 +226,10 @@ class ValueSetSolver {
void component(ValueSet *vertex,Partition &part); ///< Generate a partition component given its head
int4 visit(ValueSet *vertex,Partition &part); ///< Recursively walk the data-flow graph finding partitions
void establishTopologicalOrder(void); ///< Find the optimal order for iterating through the ValueSets
void applyConstraints(Varnode *vn,int4 type,const CircleRange &range,FlowBlock *splitPoint);
void constraintsFromPath(int4 type,CircleRange &lift,Varnode *startVn,Varnode *endVn,FlowBlock *splitPoint);
void applyConstraints(Varnode *vn,int4 type,const CircleRange &range,PcodeOp *cbranch);
void constraintsFromPath(int4 type,CircleRange &lift,Varnode *startVn,Varnode *endVn,PcodeOp *cbranch);
void constraintsFromCBranch(PcodeOp *cbranch); ///< Generate constraints arising from the given branch
void generateConstraints(vector<Varnode *> &worklist); ///< Generate constraints given a system of Varnodes
void generateConstraints(const vector<Varnode *> &worklist,const vector<PcodeOp *> &reads); ///< Generate constraints given a system of Varnodes
bool checkRelativeConstant(Varnode *vn,int4 &typeCode,uintb &value) const; ///< Check if the given Varnode is a \e relative constant
void generateRelativeConstraint(PcodeOp *compOp,PcodeOp *cbranch); ///< Try to find a \e relative constraint
public: