fixes from first stress test

This commit is contained in:
caheckman 2019-06-02 16:02:47 -04:00
parent 94e289d494
commit f51cb8b4a1
2 changed files with 97 additions and 20 deletions

View file

@ -1076,6 +1076,7 @@ bool CircleRange::pushForwardUnary(OpCode opc,const CircleRange &in1,int4 inSize
return true; return true;
} }
switch(opc) { switch(opc) {
case CPUI_CAST:
case CPUI_COPY: case CPUI_COPY:
*this = in1; *this = in1;
break; break;
@ -1125,6 +1126,7 @@ bool CircleRange::pushForwardUnary(OpCode opc,const CircleRange &in1,int4 inSize
} }
return true; return true;
} }
/// \brief Push \b this range forward through a binary operation /// \brief Push \b this range forward through a binary operation
/// ///
/// Push all values in the given ranges through a binary p-code operator. /// Push all values in the given ranges through a binary p-code operator.
@ -1144,6 +1146,7 @@ bool CircleRange::pushForwardBinary(OpCode opc,const CircleRange &in1,const Circ
return true; return true;
} }
switch(opc) { switch(opc) {
case CPUI_PTRSUB:
case CPUI_INT_ADD: case CPUI_INT_ADD:
isempty = false; isempty = false;
mask = in1.mask | in2.mask; mask = in1.mask | in2.mask;
@ -1301,6 +1304,28 @@ bool CircleRange::pushForwardBinary(OpCode opc,const CircleRange &in1,const Circ
return true; return true;
} }
/// \brief Push \b this range forward through a trinary operation
///
/// Push all values in the given ranges through a trinary p-code operator (currenly only CPUI_PTRADD).
/// If the output set of values forms a range, then set \b this to the range and return \b true.
/// \param opc is the given p-code operator
/// \param in1 is the first given input range
/// \param in2 is the second given input range
/// \param in3 is the third given input range
/// \param inSize is the storage space in bytes for the input
/// \param outSize is the storage space in bytes for the output
/// \param maxStep is the maximum to allow step to grow via multiplication
/// \return \b true if the result is known and forms a range
bool CircleRange::pushForwardTrinary(OpCode opc,const CircleRange &in1,const CircleRange &in2,const CircleRange &in3,
int4 inSize,int4 outSize,int4 maxStep)
{
if (opc != CPUI_PTRADD) return false;
CircleRange tmpRange;
if (!tmpRange.pushForwardBinary(CPUI_INT_MULT, in2, in3, inSize, inSize, maxStep))
return false;
return pushForwardBinary(CPUI_INT_ADD, in1, tmpRange, inSize, outSize, maxStep);
}
/// Widen \b this range so at least one of the boundaries matches with the given /// Widen \b this range so at least one of the boundaries matches with the given
/// range, which must contain \b this. /// range, which must contain \b this.
/// \param op2 is the given containing range /// \param op2 is the given containing range
@ -1398,6 +1423,9 @@ void CircleRange::printRaw(ostream &s) const
} }
} }
const int4 ValueSet::FULL = 100;
const int4 ValueSet::MAX_STEP = 32;
/// The initial values in \b this are set based on the type of Varnode: /// The initial values in \b this are set based on the type of Varnode:
/// - Constant gets the single value /// - Constant gets the single value
/// - Input gets all possible values /// - Input gets all possible values
@ -1434,6 +1462,7 @@ void ValueSet::setVarnode(Varnode *v,int4 tCode)
else { // Some other form of input else { // Some other form of input
opCode = CPUI_MAX; opCode = CPUI_MAX;
numParams = 0; numParams = 0;
typeCode = FULL;
range.setFull(vn->getSize()); range.setFull(vn->getSize());
} }
} }
@ -1552,7 +1581,7 @@ bool ValueSet::iterate(void)
{ {
if (!vn->isWritten()) return false; if (!vn->isWritten()) return false;
if (typeCode >= 100) return false; if (typeCode >= FULL) return false;
if (count == 0) if (count == 0)
computeTypeCode(); computeTypeCode();
count += 1; // Count this iteration count += 1; // Count this iteration
@ -1575,12 +1604,12 @@ bool ValueSet::iterate(void)
pieces = res.circleUnion(inSet->range); pieces = res.circleUnion(inSet->range);
} }
if (pieces == 2) { if (pieces == 2) {
if (res.minimalContainer(inSet->range,32)) // Could not get clean union, force it if (res.minimalContainer(inSet->range,MAX_STEP)) // Could not get clean union, force it
break; break;
} }
} }
if (0 != res.circleUnion(range)) { // Union with the previous iteration's set if (0 != res.circleUnion(range)) { // Union with the previous iteration's set
res.minimalContainer(range,32); res.minimalContainer(range,MAX_STEP);
} }
} }
else if (numParams == 1) { else if (numParams == 1) {
@ -1605,7 +1634,7 @@ bool ValueSet::iterate(void)
ValueSet *inSet1 = op->getIn(0)->getValueSet(); ValueSet *inSet1 = op->getIn(0)->getValueSet();
ValueSet *inSet2 = op->getIn(1)->getValueSet(); ValueSet *inSet2 = op->getIn(1)->getValueSet();
if (equations.size() == 0) { if (equations.size() == 0) {
if (!res.pushForwardBinary(opCode, inSet1->range, inSet2->range, inSet1->vn->getSize(), vn->getSize(), 32)) { if (!res.pushForwardBinary(opCode, inSet1->range, inSet2->range, inSet1->vn->getSize(), vn->getSize(), MAX_STEP)) {
setFull(); setFull();
return true; return true;
} }
@ -1622,11 +1651,32 @@ bool ValueSet::iterate(void)
if (0 != range2.intersect(equations[eqPos].range)) if (0 != range2.intersect(equations[eqPos].range))
range2 = equations[eqPos].range; range2 = equations[eqPos].range;
} }
if (!res.pushForwardBinary(opCode, range1, range2, inSet1->vn->getSize(), vn->getSize(), 32)) { if (!res.pushForwardBinary(opCode, range1, range2, inSet1->vn->getSize(), vn->getSize(), MAX_STEP)) {
setFull(); setFull();
return true;
} }
} }
} }
else if (numParams == 3) {
ValueSet *inSet1 = op->getIn(0)->getValueSet();
ValueSet *inSet2 = op->getIn(1)->getValueSet();
ValueSet *inSet3 = op->getIn(2)->getValueSet();
CircleRange range1 = inSet1->range;
CircleRange range2 = inSet2->range;
if (doesEquationApply(eqPos, 0)) {
if (0 != range1.intersect(equations[eqPos].range))
range1 = equations[eqPos].range;
eqPos += 1;
}
if (doesEquationApply(eqPos, 1)) {
if (0 != range2.intersect(equations[eqPos].range))
range2 = equations[eqPos].range;
}
if (!res.pushForwardTrinary(opCode, range1, range2, inSet3->range, inSet1->vn->getSize(), vn->getSize(), MAX_STEP)) {
setFull();
return true;
}
}
else else
return false; // No way to change this value set return false; // No way to change this value set
@ -1671,7 +1721,7 @@ void ValueSetRead::setPcodeOp(PcodeOp *o,int4 slt)
typeCode = 0; typeCode = 0;
op = o; op = o;
slot = slt; slot = slt;
equationTypeCode = 100; equationTypeCode = ValueSet::FULL;
} }
/// \param slt is the given slot /// \param slt is the given slot
@ -2006,7 +2056,7 @@ void ValueSetSolver::generateConstraints(vector<Varnode *> &worklist)
bl->setMark(); bl->setMark();
blockList.push_back(bl); blockList.push_back(bl);
PcodeOp *lastOp = bl->lastOp(); PcodeOp *lastOp = bl->lastOp();
if (lastOp->code() == CPUI_CBRANCH) { if (lastOp != (PcodeOp *)0 && lastOp->code() == CPUI_CBRANCH) {
constraintsFromCBranch(lastOp); constraintsFromCBranch(lastOp);
} }
bl = (BlockBasic *)bl->getImmedDom(); bl = (BlockBasic *)bl->getImmedDom();
@ -2119,11 +2169,12 @@ void ValueSetSolver::establishValueSets(const vector<Varnode *> &sinks,const vec
{ {
vector<Varnode *> worklist; vector<Varnode *> worklist;
int4 workPos = 1; int4 workPos = 0;
if (stackReg != (Varnode *)0) { if (stackReg != (Varnode *)0) {
newValueSet(stackReg,1); // Establish stack pointer as special newValueSet(stackReg,1); // Establish stack pointer as special
stackReg->setMark(); stackReg->setMark();
worklist.push_back(stackReg); worklist.push_back(stackReg);
workPos += 1;
rootNodes.push_back(stackReg->getValueSet()); rootNodes.push_back(stackReg->getValueSet());
} }
for(int4 i=0;i<sinks.size();++i) { for(int4 i=0;i<sinks.size();++i) {
@ -2145,17 +2196,39 @@ void ValueSetSolver::establishValueSets(const vector<Varnode *> &sinks,const vec
continue; continue;
} }
PcodeOp *op = vn->getDef(); PcodeOp *op = vn->getDef();
if (op->isCall()) { switch(op->code()) { // Distinguish ops where we can never predict an integer range
vn->getValueSet()->range.setFull(vn->getSize()); case CPUI_CALL:
rootNodes.push_back(vn->getValueSet()); case CPUI_CALLIND:
continue; case CPUI_CALLOTHER:
} case CPUI_LOAD:
for(int4 i=0;i<op->numInput();++i) { case CPUI_NEW:
Varnode *inVn = op->getIn(i); case CPUI_SEGMENTOP:
if (inVn->isMark() || inVn->isAnnotation()) continue; case CPUI_CPOOLREF:
newValueSet(inVn,0); case CPUI_FLOAT_ADD:
inVn->setMark(); case CPUI_FLOAT_DIV:
worklist.push_back(inVn); case CPUI_FLOAT_MULT:
case CPUI_FLOAT_SUB:
case CPUI_FLOAT_NEG:
case CPUI_FLOAT_ABS:
case CPUI_FLOAT_SQRT:
case CPUI_FLOAT_INT2FLOAT:
case CPUI_FLOAT_FLOAT2FLOAT:
case CPUI_FLOAT_TRUNC:
case CPUI_FLOAT_CEIL:
case CPUI_FLOAT_FLOOR:
case CPUI_FLOAT_ROUND:
vn->getValueSet()->setFull();
rootNodes.push_back(vn->getValueSet());
break;
default:
for(int4 i=0;i<op->numInput();++i) {
Varnode *inVn = op->getIn(i);
if (inVn->isMark() || inVn->isAnnotation()) continue;
newValueSet(inVn,0);
inVn->setMark();
worklist.push_back(inVn);
}
break;
} }
} }
for(int4 i=0;i<reads.size();++i) { for(int4 i=0;i<reads.size();++i) {

View file

@ -91,6 +91,8 @@ public:
Varnode *pullBack(PcodeOp *op,Varnode **constMarkup,bool usenzmask); ///< Pull-back \b this range through given PcodeOp. Varnode *pullBack(PcodeOp *op,Varnode **constMarkup,bool usenzmask); ///< Pull-back \b this range through given PcodeOp.
bool pushForwardUnary(OpCode opc,const CircleRange &in1,int4 inSize,int4 outSize); ///< Push-forward thru given unary operator bool pushForwardUnary(OpCode opc,const CircleRange &in1,int4 inSize,int4 outSize); ///< Push-forward thru given unary operator
bool pushForwardBinary(OpCode opc,const CircleRange &in1,const CircleRange &in2,int4 inSize,int4 outSize,int4 maxStep); bool pushForwardBinary(OpCode opc,const CircleRange &in1,const CircleRange &in2,int4 inSize,int4 outSize,int4 maxStep);
bool pushForwardTrinary(OpCode opc,const CircleRange &in1,const CircleRange &in2,const CircleRange &in3,
int4 inSize,int4 outSize,int4 maxStep);
void widen(const CircleRange &op2,bool leftIsStable); ///< Widen the unstable bound to match containing range void widen(const CircleRange &op2,bool leftIsStable); ///< Widen the unstable bound to match containing range
int4 translate2Op(OpCode &opc,uintb &c,int4 &cslot) const; ///< Translate range to a comparison op int4 translate2Op(OpCode &opc,uintb &c,int4 &cslot) const; ///< Translate range to a comparison op
void printRaw(ostream &s) const; ///< Write a text representation of \b this to stream void printRaw(ostream &s) const; ///< Write a text representation of \b this to stream
@ -107,6 +109,8 @@ class Partition; // Forward declaration
/// or some other register (if \b typeCode is non-zero). /// or some other register (if \b typeCode is non-zero).
class ValueSet { class ValueSet {
public: public:
static const int4 FULL; ///< Special typeCode indicating is permanently marked full
static const int4 MAX_STEP; ///< Maximum step inferred for a value set
/// \brief An external that can be applied to a ValueSet /// \brief An external that can be applied to a ValueSet
/// ///
/// An Equation is attached to a particular ValueSet and its underlying Varnode /// An Equation is attached to a particular ValueSet and its underlying Varnode
@ -132,7 +136,7 @@ private:
Partition *partHead; ///< If Varnode is a component head, pointer to corresponding Partition Partition *partHead; ///< If Varnode is a component head, pointer to corresponding Partition
ValueSet *next; ///< Next ValueSet to iterate ValueSet *next; ///< Next ValueSet to iterate
bool doesEquationApply(int4 num,int4 slot) const; ///< Does the indicated equation apply for the given input slot bool doesEquationApply(int4 num,int4 slot) const; ///< Does the indicated equation apply for the given input slot
void setFull(void) { range.setFull(vn->getSize()); typeCode = 100; } ///< Mark value set as possibly containing any value void setFull(void) { range.setFull(vn->getSize()); typeCode = FULL; } ///< Mark value set as possibly containing any value
void setVarnode(Varnode *v,int4 tCode); ///< Attach \b this to given Varnode and set initial values void setVarnode(Varnode *v,int4 tCode); ///< Attach \b this to given Varnode and set initial values
void addEquation(int4 slot,int4 type,const CircleRange &constraint); ///< Insert an equation restricting \b this value set void addEquation(int4 slot,int4 type,const CircleRange &constraint); ///< Insert an equation restricting \b this value set
void addLandmark(int4 type,const CircleRange &constraint) { addEquation(numParams,type,constraint); } ///< Add a widening landmark void addLandmark(int4 type,const CircleRange &constraint) { addEquation(numParams,type,constraint); } ///< Add a widening landmark