mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
ValueSetRead objects
This commit is contained in:
parent
16fd5df590
commit
94e289d494
3 changed files with 118 additions and 13 deletions
|
@ -2485,17 +2485,28 @@ void IfcAnalyzeRange::execute(istream &s)
|
||||||
|
|
||||||
Varnode *vn = iface_read_varnode(dcp,s);
|
Varnode *vn = iface_read_varnode(dcp,s);
|
||||||
vector<Varnode *> sinks;
|
vector<Varnode *> sinks;
|
||||||
|
vector<PcodeOp *> reads;
|
||||||
sinks.push_back(vn);
|
sinks.push_back(vn);
|
||||||
|
for(list<PcodeOp *>::const_iterator iter=vn->beginDescend();iter!=vn->endDescend();++iter) {
|
||||||
|
PcodeOp *op = *iter;
|
||||||
|
if (op->code() == CPUI_LOAD || op->code() == CPUI_STORE)
|
||||||
|
reads.push_back(op);
|
||||||
|
}
|
||||||
Varnode *stackReg = dcp->fd->findSpacebaseInput(dcp->conf->getStackSpace());
|
Varnode *stackReg = dcp->fd->findSpacebaseInput(dcp->conf->getStackSpace());
|
||||||
ValueSetSolver vsSolver;
|
ValueSetSolver vsSolver;
|
||||||
vsSolver.establishValueSets(sinks, stackReg);
|
vsSolver.establishValueSets(sinks, reads, stackReg);
|
||||||
vsSolver.solve(10000);
|
vsSolver.solve(10000);
|
||||||
list<ValueSet>::const_iterator iter;
|
list<ValueSet>::const_iterator iter;
|
||||||
for(iter=vsSolver.beginValueSets();iter!=vsSolver.endValueSets();++iter) {
|
for(iter=vsSolver.beginValueSets();iter!=vsSolver.endValueSets();++iter) {
|
||||||
(*iter).printRaw(*status->optr);
|
(*iter).printRaw(*status->optr);
|
||||||
*status->optr << endl;
|
*status->optr << endl;
|
||||||
}
|
}
|
||||||
}
|
map<SeqNum,ValueSetRead>::const_iterator riter;
|
||||||
|
for(riter=vsSolver.beginValueSetReads();riter!=vsSolver.endValueSetReads();++riter) {
|
||||||
|
(*riter).second.printRaw(*status->optr);
|
||||||
|
*status->optr << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef OPACTION_DEBUG
|
#ifdef OPACTION_DEBUG
|
||||||
|
|
||||||
|
|
|
@ -1472,6 +1472,7 @@ void ValueSet::doWidening(const CircleRange &newRange)
|
||||||
const Equation &landmark(equations.back());
|
const Equation &landmark(equations.back());
|
||||||
if (landmark.slot == numParams && typeCode == landmark.typeCode) {
|
if (landmark.slot == numParams && typeCode == landmark.typeCode) {
|
||||||
bool leftIsStable = range.getMin() == newRange.getMin();
|
bool leftIsStable = range.getMin() == newRange.getMin();
|
||||||
|
range = newRange; // Preserve any new step information
|
||||||
if (landmark.range.contains(range)) {
|
if (landmark.range.contains(range)) {
|
||||||
range.widen(landmark.range,leftIsStable);
|
range.widen(landmark.range,leftIsStable);
|
||||||
return;
|
return;
|
||||||
|
@ -1599,17 +1600,11 @@ bool ValueSet::iterate(void)
|
||||||
setFull();
|
setFull();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
typeCode = inSet1->typeCode;
|
|
||||||
}
|
}
|
||||||
else if (numParams == 2) {
|
else if (numParams == 2) {
|
||||||
ValueSet *inSet1 = op->getIn(0)->getValueSet();
|
ValueSet *inSet1 = op->getIn(0)->getValueSet();
|
||||||
ValueSet *inSet2 = op->getIn(1)->getValueSet();
|
ValueSet *inSet2 = op->getIn(1)->getValueSet();
|
||||||
typeCode = inSet1->typeCode + inSet2->typeCode;
|
if (equations.size() == 0) {
|
||||||
if (inSet1->typeCode != 0 && inSet2->typeCode != 0) { // Combining two based constants
|
|
||||||
typeCode = 0;
|
|
||||||
res.setFull(vn->getSize());
|
|
||||||
}
|
|
||||||
else 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(), 32)) {
|
||||||
setFull();
|
setFull();
|
||||||
return true;
|
return true;
|
||||||
|
@ -1668,6 +1663,57 @@ void ValueSet::printRaw(ostream &s) const
|
||||||
range.printRaw(s);
|
range.printRaw(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \param o is the PcodeOp reading the value set
|
||||||
|
/// \param slt is the input slot the values are coming in from
|
||||||
|
void ValueSetRead::setPcodeOp(PcodeOp *o,int4 slt)
|
||||||
|
|
||||||
|
{
|
||||||
|
typeCode = 0;
|
||||||
|
op = o;
|
||||||
|
slot = slt;
|
||||||
|
equationTypeCode = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \param slt is the given slot
|
||||||
|
/// \param type is the constraint characteristic
|
||||||
|
/// \param constraint is the given range
|
||||||
|
void ValueSetRead::addEquation(int4 slt,int4 type,const CircleRange &constraint)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (slot == slt) {
|
||||||
|
equationTypeCode = type;
|
||||||
|
equationConstraint = constraint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This value set will be the same as the ValueSet of the Varnode being read but may
|
||||||
|
/// be modified due to additional control-flow constraints
|
||||||
|
void ValueSetRead::compute(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
Varnode *vn = op->getIn(slot);
|
||||||
|
ValueSet *valueSet = vn->getValueSet();
|
||||||
|
typeCode = valueSet->getTypeCode();
|
||||||
|
range = valueSet->getRange();
|
||||||
|
if (typeCode == equationTypeCode) {
|
||||||
|
if (0 != range.intersect(equationConstraint)) {
|
||||||
|
range = equationConstraint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \param s is the stream to print to
|
||||||
|
void ValueSetRead::printRaw(ostream &s) const
|
||||||
|
|
||||||
|
{
|
||||||
|
s << "Read: " << get_opname(op->code());
|
||||||
|
if (typeCode == 0)
|
||||||
|
s << " absolute ";
|
||||||
|
else
|
||||||
|
s << " stackptr ";
|
||||||
|
range.printRaw(s);
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Construct an iterator over the outbound edges of the given ValueSet node
|
/// \brief Construct an iterator over the outbound edges of the given ValueSet node
|
||||||
///
|
///
|
||||||
/// Mostly this just forwards the ValueSets attached to output Varnodes
|
/// Mostly this just forwards the ValueSets attached to output Varnodes
|
||||||
|
@ -1848,6 +1894,10 @@ void ValueSetSolver::applyConstraints(Varnode *vn,int4 type,const CircleRange &r
|
||||||
FlowBlock *falseBlock = splitPoint->getFalseOut();
|
FlowBlock *falseBlock = splitPoint->getFalseOut();
|
||||||
for(iter=vn->beginDescend();iter!=vn->endDescend();++iter) {
|
for(iter=vn->beginDescend();iter!=vn->endDescend();++iter) {
|
||||||
PcodeOp *op = *iter;
|
PcodeOp *op = *iter;
|
||||||
|
if (op->isMark()) { // Special read site being tracked
|
||||||
|
readNodes[op->getSeqNum()].addEquation(op->getSlot(vn), type, range);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Varnode *outVn = op->getOut();
|
Varnode *outVn = op->getOut();
|
||||||
if (outVn == (Varnode *)0) continue;
|
if (outVn == (Varnode *)0) continue;
|
||||||
if (!outVn->isMark()) continue;
|
if (!outVn->isMark()) continue;
|
||||||
|
@ -2063,8 +2113,9 @@ void ValueSetSolver::generateRelativeConstraint(PcodeOp *compOp,PcodeOp *cbranch
|
||||||
|
|
||||||
/// Given a set of sinks, find all the Varnodes that flow directly into them.
|
/// Given a set of sinks, find all the Varnodes that flow directly into them.
|
||||||
/// \param sinks is the list terminating Varnodes
|
/// \param sinks is the list terminating Varnodes
|
||||||
|
/// \param reads are add-on PcodeOps where we would like to know input ValueSets at the point of read
|
||||||
/// \param stackReg (if non-NULL) gives the stack pointer (for keeping track of relative offsets)
|
/// \param stackReg (if non-NULL) gives the stack pointer (for keeping track of relative offsets)
|
||||||
void ValueSetSolver::establishValueSets(const vector<Varnode *> &sinks,Varnode *stackReg)
|
void ValueSetSolver::establishValueSets(const vector<Varnode *> &sinks,const vector<PcodeOp *> &reads,Varnode *stackReg)
|
||||||
|
|
||||||
{
|
{
|
||||||
vector<Varnode *> worklist;
|
vector<Varnode *> worklist;
|
||||||
|
@ -2107,7 +2158,21 @@ void ValueSetSolver::establishValueSets(const vector<Varnode *> &sinks,Varnode *
|
||||||
worklist.push_back(inVn);
|
worklist.push_back(inVn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for(int4 i=0;i<reads.size();++i) {
|
||||||
|
PcodeOp *op = reads[i];
|
||||||
|
for(int4 slot=0;slot<op->numInput();++slot) {
|
||||||
|
Varnode *vn = op->getIn(slot);
|
||||||
|
if (vn->isMark()) {
|
||||||
|
readNodes[op->getSeqNum()].setPcodeOp(op, slot);
|
||||||
|
op->setMark(); // Mark read ops for equation generation stage
|
||||||
|
break; // Only 1 read allowed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
generateConstraints(worklist);
|
generateConstraints(worklist);
|
||||||
|
for(int4 i=0;i<reads.size();++i)
|
||||||
|
reads[i]->clearMark(); // Clear marks on read ops
|
||||||
|
|
||||||
establishTopologicalOrder();
|
establishTopologicalOrder();
|
||||||
for(int4 i=0;i<worklist.size();++i)
|
for(int4 i=0;i<worklist.size();++i)
|
||||||
worklist[i]->clearMark();
|
worklist[i]->clearMark();
|
||||||
|
@ -2170,4 +2235,7 @@ void ValueSetSolver::solve(int4 max)
|
||||||
curSet = curSet->next;
|
curSet = curSet->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
map<SeqNum,ValueSetRead>::iterator riter;
|
||||||
|
for(riter=readNodes.begin();riter!=readNodes.end();++riter)
|
||||||
|
(*riter).second.compute(); // Calculate any follow-on value sets
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,6 +159,29 @@ public:
|
||||||
} ///< Construct empty partition
|
} ///< Construct empty partition
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief A special form of ValueSet associated with the \e read \e point of a Varnode
|
||||||
|
///
|
||||||
|
/// When a Varnode is read, it may have a more restricted range at the point of the read
|
||||||
|
/// compared to the full scope. This class officially stores the value set at the point
|
||||||
|
/// of the read (specified by PcodeOp and slot). It is computed as a final step after
|
||||||
|
/// the main iteration has completed.
|
||||||
|
class ValueSetRead {
|
||||||
|
friend class ValueSetSolver;
|
||||||
|
int4 typeCode; ///< 0=pure constant 1=stack relative
|
||||||
|
PcodeOp *op; ///< The PcodeOp at the point of the value set read
|
||||||
|
int4 slot; ///< The slot being read
|
||||||
|
CircleRange range; ///< Range of values or offsets in this set
|
||||||
|
int4 equationTypeCode; ///< Type code of the associated equation
|
||||||
|
CircleRange equationConstraint; ///< Constraint associated with the equation
|
||||||
|
void setPcodeOp(PcodeOp *o,int4 slt); ///< Establish \e read this value set corresponds to
|
||||||
|
void addEquation(int4 slt,int4 type,const CircleRange &constraint); ///< Insert an equation restricting \b this value set
|
||||||
|
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
|
||||||
|
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 the determines a ValueSet for each Varnode in a data-flow system
|
/// \brief Class the 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)
|
/// This class uses \e value \e set \e analysis to calculate (an overestimation of)
|
||||||
|
@ -185,6 +208,7 @@ class ValueSetSolver {
|
||||||
};
|
};
|
||||||
|
|
||||||
list<ValueSet> valueNodes; ///< Storage for all the current value sets
|
list<ValueSet> valueNodes; ///< Storage for all the current value sets
|
||||||
|
map<SeqNum,ValueSetRead> readNodes; ///< Additional, after iteration, add-on value sets
|
||||||
Partition orderPartition; ///< Value sets in iteration order
|
Partition orderPartition; ///< Value sets in iteration order
|
||||||
list<Partition> recordStorage; ///< Storage for the Partitions establishing components
|
list<Partition> recordStorage; ///< Storage for the Partitions establishing components
|
||||||
vector<ValueSet *> rootNodes; ///< Values treated as inputs
|
vector<ValueSet *> rootNodes; ///< Values treated as inputs
|
||||||
|
@ -206,11 +230,13 @@ class ValueSetSolver {
|
||||||
bool checkRelativeConstant(Varnode *vn,int4 &typeCode,uintb &value) const; ///< Check if the given Varnode is a \e relative constant
|
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
|
void generateRelativeConstraint(PcodeOp *compOp,PcodeOp *cbranch); ///< Try to find a \e relative constraint
|
||||||
public:
|
public:
|
||||||
void establishValueSets(const vector<Varnode *> &sinks,Varnode *stackReg); ///< Build value sets for a data-flow system
|
void establishValueSets(const vector<Varnode *> &sinks,const vector<PcodeOp *> &reads,Varnode *stackReg); ///< Build value sets for a data-flow system
|
||||||
int4 getNumIterations(void) const { return numIterations; } ///< Get the current number of iterations
|
int4 getNumIterations(void) const { return numIterations; } ///< Get the current number of iterations
|
||||||
void solve(int4 max); ///< Iterate the ValueSet system until it stabilizes
|
void solve(int4 max); ///< Iterate the ValueSet system until it stabilizes
|
||||||
list<ValueSet>::const_iterator beginValueSets(void) { return valueNodes.begin(); } ///< Start of all ValueSets in the system
|
list<ValueSet>::const_iterator beginValueSets(void) const { return valueNodes.begin(); } ///< Start of all ValueSets in the system
|
||||||
list<ValueSet>::const_iterator endValueSets(void) { return valueNodes.end(); } ///< End of all ValueSets in the system
|
list<ValueSet>::const_iterator endValueSets(void) const { return valueNodes.end(); } ///< End of all ValueSets in the system
|
||||||
|
map<SeqNum,ValueSetRead>::const_iterator beginValueSetReads(void) const { return readNodes.begin(); } ///< Start of ValueSetReads
|
||||||
|
map<SeqNum,ValueSetRead>::const_iterator endValueSetReads(void) const { return readNodes.end(); } ///< End of ValueSetReads
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \param op2 is the range to compare \b this to
|
/// \param op2 is the range to compare \b this to
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue