CircleRange contain and widen adjustments

This commit is contained in:
caheckman 2019-06-14 11:18:02 -04:00
parent ab9b8dd602
commit 49f72d2de7

View file

@ -295,7 +295,7 @@ int4 CircleRange::getMaxInfo(void) const
} }
/// \param op2 is the specific range to test for containment. /// \param op2 is the specific range to test for containment.
/// \return \b true if \b true contains the interval \b op2 /// \return \b true if \b this contains the interval \b op2
bool CircleRange::contains(const CircleRange &op2) const bool CircleRange::contains(const CircleRange &op2) const
{ {
@ -303,13 +303,24 @@ bool CircleRange::contains(const CircleRange &op2) const
return op2.isempty; return op2.isempty;
if (op2.isempty) if (op2.isempty)
return true; return true;
if (step > op2.step) return false; // Cannot be containment because step is wrong if (step > op2.step) {
// This must have a smaller or equal step to op2 or containment is impossible
// except in the corner case where op2 consists of a single element (its step is meaningless)
if (!op2.isSingle())
return false;
}
if (left == right) return true; if (left == right) return true;
if (op2.left == op2.right) return false; if (op2.left == op2.right) return false;
if (left % step != op2.left % step) return false; // Wrong phase
if (left == op2.left && right == op2.right) return true;
char overlapCode = encodeRangeOverlaps(left, right, op2.left, op2.right); char overlapCode = encodeRangeOverlaps(left, right, op2.left, op2.right);
return (overlapCode == 'c'); if (overlapCode == 'c')
return true;
if (overlapCode == 'b' && (right == op2.right))
return true;
return false;
// Missing one case where op2.step > this->step, and the boundaries don't show containment, // Missing one case where op2.step > this->step, and the boundaries don't show containment,
// but there is containment because the lower step size UP TO right still contains the edge points // but there is containment because the lower step size UP TO right still contains the edge points
@ -1368,7 +1379,13 @@ void CircleRange::widen(const CircleRange &op2,bool leftIsStable)
{ {
if (leftIsStable) { if (leftIsStable) {
right = (op2.right + step-1) & mask; uintb lmod = left % step;
uintb mod = op2.right % step;
if (mod <= lmod)
right = op2.right + (lmod - mod);
else
right = op2.right - (mod - lmod);
right &= mask;
} }
else { else {
left = op2.left & mask; left = op2.left & mask;
@ -1534,7 +1551,7 @@ bool ValueSet::computeTypeCode(void)
{ {
int4 relCount = 0; int4 relCount = 0;
int4 lastTypeCode; int4 lastTypeCode = 0;
PcodeOp *op = vn->getDef(); PcodeOp *op = vn->getDef();
for(int4 i=0;i<numParams;++i) { for(int4 i=0;i<numParams;++i) {
ValueSet *valueSet = op->getIn(i)->getValueSet(); ValueSet *valueSet = op->getIn(i)->getValueSet();
@ -2176,42 +2193,48 @@ void ValueSetSolver::generateConstraints(const vector<Varnode *> &worklist,const
{ {
vector<FlowBlock *> blockList; vector<FlowBlock *> blockList;
// Collect all blocks that contain a system op or dominate a container
for(int4 i=0;i<worklist.size();++i) { for(int4 i=0;i<worklist.size();++i) {
PcodeOp *op = worklist[i]->getDef(); PcodeOp *op = worklist[i]->getDef();
if (op == (PcodeOp *)0) continue; if (op == (PcodeOp *)0) continue;
BlockBasic *bl = (BlockBasic *)op->getParent()->getImmedDom(); FlowBlock *bl = op->getParent();
while(bl != (FlowBlock *)0) { while(bl != (FlowBlock *)0) {
if (!bl->isMark()) { if (bl->isMark()) break;
bl->setMark(); bl->setMark();
blockList.push_back(bl); blockList.push_back(bl);
PcodeOp *lastOp = bl->lastOp(); bl = bl->getImmedDom();
if (lastOp != (PcodeOp *)0 && lastOp->code() == CPUI_CBRANCH) {
constraintsFromCBranch(lastOp);
}
bl = (BlockBasic *)bl->getImmedDom();
}
else
break;
} }
} }
for(int4 i=0;i<reads.size();++i) { for(int4 i=0;i<reads.size();++i) {
BlockBasic *bl = (BlockBasic *)reads[i]->getParent()->getImmedDom(); FlowBlock *bl = reads[i]->getParent();
while(bl != (FlowBlock *)0) { while(bl != (FlowBlock *)0) {
if (!bl->isMark()) { if (bl->isMark()) break;
bl->setMark(); bl->setMark();
blockList.push_back(bl); blockList.push_back(bl);
PcodeOp *lastOp = bl->lastOp(); bl = bl->getImmedDom();
if (lastOp != (PcodeOp *)0 && lastOp->code() == CPUI_CBRANCH) {
constraintsFromCBranch(lastOp);
}
bl = (BlockBasic *)bl->getImmedDom();
}
else
break;
} }
} }
for(int4 i=0;i<blockList.size();++i) for(int4 i=0;i<blockList.size();++i)
blockList[i]->clearMark(); blockList[i]->clearMark();
vector<FlowBlock *> finalList;
// Now go through input blocks to the previously calculated blocks
for(int4 i=0;i<blockList.size();++i) {
FlowBlock *bl = blockList[i];
for(int4 j=0;j<bl->sizeIn();++j) {
BlockBasic *splitPoint = (BlockBasic *)bl->getIn(j);
if (splitPoint->isMark()) continue;
if (splitPoint->sizeOut() != 2) continue;
PcodeOp *lastOp = splitPoint->lastOp();
if (lastOp != (PcodeOp *)0 && lastOp->code() == CPUI_CBRANCH) {
splitPoint->setMark();
finalList.push_back(splitPoint);
constraintsFromCBranch(lastOp); // Try to generate constraints from this splitPoint
}
}
}
for(int4 i=0;i<finalList.size();++i)
finalList[i]->clearMark();
} }
/// Verify that the given Varnode is produced by a straight line sequence of /// Verify that the given Varnode is produced by a straight line sequence of
@ -2248,7 +2271,7 @@ bool ValueSetSolver::checkRelativeConstant(Varnode *vn,int4 &typeCode,uintb &val
else else
return false; return false;
} }
return true; // Never reach here return true;
} }
/// Given a binary PcodeOp producing a conditional branch, check if it can be interpreted /// Given a binary PcodeOp producing a conditional branch, check if it can be interpreted
@ -2298,12 +2321,19 @@ void ValueSetSolver::generateRelativeConstraint(PcodeOp *compOp,PcodeOp *cbranch
while(!endVn->isMark()) { while(!endVn->isMark()) {
if (!endVn->isWritten()) return; if (!endVn->isWritten()) return;
PcodeOp *op = endVn->getDef(); PcodeOp *op = endVn->getDef();
if (op->code() != CPUI_COPY && op->code() != CPUI_INDIRECT) opc = op->code();
if (opc == CPUI_COPY || opc == CPUI_PTRSUB) {
endVn = op->getIn(0);
}
else if (opc == CPUI_INT_ADD) { // Can pull-back through INT_ADD
if (!op->getIn(1)->isConstant()) // if second param is constant
return; return;
endVn = op->getIn(0); endVn = op->getIn(0);
} }
if (endVn != (Varnode *)0) else
constraintsFromPath(typeCode,lift,endVn,endVn,cbranch); return;
}
constraintsFromPath(typeCode,lift,vn,endVn,cbranch);
} }
/// \brief Build value sets for a data-flow system /// \brief Build value sets for a data-flow system