rearrange LoadGuard class

This commit is contained in:
caheckman 2019-06-12 15:07:39 -04:00
parent e1507d05ec
commit 8cad85e36c
3 changed files with 47 additions and 34 deletions

View file

@ -232,6 +232,8 @@ public:
/// \return \b true if the Varnode is fully linked
bool isHeritaged(Varnode *vn) { return (heritage.heritagePass(vn->getAddr())>=0); }
const list<LoadGuard> &getLoadGuards(void) const { return heritage.getLoadGuards(); }
// Function prototype and call specification routines
int4 numCalls(void) const { return qlst.size(); } ///< Get the number of calls made by \b this function
FuncCallSpecs *getCallSpecs(int4 i) const { return qlst[i]; } ///< Get the i-th call specification

View file

@ -578,22 +578,20 @@ void Heritage::handleNewLoadCopies(void)
///
/// isAnalyzed is set to \b true, if full range analysis is not needed
/// \param valueSet is the calculated value set as seen by the LOAD operation
void Heritage::LoadGuard::establishRange(const ValueSetRead &valueSet)
void LoadGuard::establishRange(const ValueSetRead &valueSet)
{
const CircleRange &range( valueSet.getRange() );
uintb rangeSize = range.getSize();
uintb size;
if (range.isEmpty()) {
step = 0;
minimumOffset = pointerBase;
size = 0x1000;
}
else if (range.isFull() || rangeSize > 0xffffff) {
step = 1;
minimumOffset = pointerBase;
size = 0x1000;
isAnalyzed = true; // Don't bother doing more analysis
analysisState = 1; // Don't bother doing more analysis
}
else {
step = (rangeSize == 3) ? range.getStep() : 0; // Check for consistent step
@ -627,21 +625,20 @@ void Heritage::LoadGuard::establishRange(const ValueSetRead &valueSet)
}
}
void Heritage::LoadGuard::finalizeRange(const ValueSetRead &valueSet)
void LoadGuard::finalizeRange(const ValueSetRead &valueSet)
{
isAnalyzed = true; // In all cases the settings determined here are final
analysisState = 1; // In all cases the settings determined here are final
const CircleRange &range( valueSet.getRange() );
uintb rangeSize = range.getSize();
if (rangeSize > 1 && rangeSize < 0xffffff) { // Did we converge to something reasonable
analysisState = 2; // Mark that we got a definitive result
step = range.getStep();
minimumOffset = range.getMin();
maximumOffset = range.getMax();
if (maximumOffset < minimumOffset) // Values extend into what is usually stack parameters
maximumOffset = spc->getHighest();
}
if (step == 0)
step = 1;
if (minimumOffset > spc->getHighest())
minimumOffset = spc->getHighest();
if (maximumOffset > spc->getHighest())
@ -652,14 +649,14 @@ void Heritage::analyzeNewLoadGuards(void)
{
if (loadGuard.empty()) return;
if (loadGuard.back().isAnalyzed) return; // Nothing new
if (loadGuard.back().analysisState != 0) return; // Nothing new
list<LoadGuard>::iterator startIter = loadGuard.end();
vector<Varnode *> sinks;
vector<PcodeOp *> reads;
while(startIter != loadGuard.begin()) {
--startIter;
LoadGuard &guard( *startIter );
if (guard.isAnalyzed) break;
if (guard.analysisState != 0) break;
reads.push_back(guard.op);
sinks.push_back(guard.op->getIn(1)); // The CPUI_LOAD pointer
}
@ -676,7 +673,7 @@ void Heritage::analyzeNewLoadGuards(void)
for(iter=startIter;iter!=loadGuard.end(); ++iter) {
LoadGuard &guard( *iter );
guard.establishRange(vsSolver.getValueSetRead(guard.op->getSeqNum()));
if (!guard.isAnalyzed)
if (guard.analysisState == 0)
runFullAnalysis = true;
}
if (runFullAnalysis) {
@ -700,13 +697,7 @@ void Heritage::generateLoadGuard(StackNode &node,PcodeOp *op,AddrSpace *spc)
{
loadGuard.push_back(LoadGuard());
LoadGuard &guard( loadGuard.back() );
guard.op = op;
guard.spc = spc;
guard.pointerBase = node.offset;
guard.minimumOffset = 0; // Initially we guard everything
guard.maximumOffset = spc->getHighest();
guard.isAnalyzed = false;
loadGuard.back().set(op,spc,node.offset);
}
/// \brief Trace input stackpointer to any indexed loads

View file

@ -95,6 +95,39 @@ class HeritageInfo {
deadremoved = 0; deadcodedelay = delay; warningissued = false; loadGuardSearch = false; } ///< Reset
};
/// \brief Description of a LOAD operation that needs to be guarded
///
/// Heritage maintains a list of CPUI_LOAD ops that reference the stack dynamically. These
/// can potentially alias stack Varnodes, so we maintain what (possibly limited) information
/// we known about the range of stack addresses that can be referenced.
class LoadGuard {
friend class Heritage;
PcodeOp *op; ///< The LOAD op
AddrSpace *spc; ///< The stack space being loaded from
uintb pointerBase; ///< Base offset of the pointer
uintb minimumOffset; ///< Minimum offset of the LOAD
uintb maximumOffset; ///< Maximum offset of the LOAD
int4 step; ///< Step of any access into this range (0=unknown)
int4 analysisState; ///< 0=unanalyzed, 1=analyzed(partial result), 2=analyzed(full result)
void establishRange(const ValueSetRead &valueSet); ///< Convert partial value set analysis into guard range
void finalizeRange(const ValueSetRead &valueSet); ///< Convert value set analysis to final guard range
/// \brief Set a new unanalyzed LOAD guard that initially guards everything
///
/// \param o is the LOAD op
/// \param s is the (stack) space it is loading from
/// \param off is the base offset that is indexed from
void set(PcodeOp *o,AddrSpace *s,uintb off) {
op = o; spc = s; pointerBase=off; minimumOffset=0; maximumOffset=s->getHighest(); step=0; analysisState=0;
}
public:
PcodeOp *getOp(void) const { return op; } ///< Get the PcodeOp being guarded
uintb getMinimum(void) const { return minimumOffset; } ///< Get minimum offset of the guarded range
uintb getMaximum(void) const { return maximumOffset; } ///< Get maximum offset of the guarded range
int4 getStep(void) const { return step; } ///< Get the calculated step associated with the range (or 0)
bool isRangeLocked(void) const { return (analysisState == 2); } ///< Return \b true if the range is fully determined
};
/// \brief Manage the construction of Static Single Assignment (SSA) form
///
/// With a specific function (Funcdata), this class links the Varnode and
@ -156,20 +189,6 @@ class Heritage {
}
};
/// \brief Description of a LOAD operation that needs to be guarded
class LoadGuard {
friend class Heritage;
PcodeOp *op; ///< The LOAD op
AddrSpace *spc; ///< The stack space being loaded from
uintb pointerBase; ///< Base offset of the pointer
uintb minimumOffset; ///< Minimum offset of the LOAD
uintb maximumOffset; ///< Maximum offset of the LOAD
int4 step; ///< Step of any access into this range
bool isAnalyzed; ///< Has a range analysis been performed on \b this
void establishRange(const ValueSetRead &valueSet); ///< Convert partial value set analysis into guard range
void finalizeRange(const ValueSetRead &valueSet); ///< Convert value set analysis to final guard range
};
Funcdata *fd; ///< The function \b this is controlling SSA construction
LocationMap globaldisjoint; ///< Disjoint cover of every heritaged memory location
LocationMap disjoint; ///< Disjoint cover of memory locations currently being heritaged
@ -229,6 +248,8 @@ class Heritage {
void calcMultiequals(const vector<Varnode *> &write);
void renameRecurse(BlockBasic *bl,VariableStack &varstack);
void bumpDeadcodeDelay(Varnode *vn);
void placeMultiequals(void);
void rename(void);
public:
Heritage(Funcdata *data); ///< Constructor
@ -246,9 +267,8 @@ public:
void buildInfoList(void); ///< Initialize information for each space
void forceRestructure(void) { maxdepth = -1; } ///< Force regeneration of basic block structures
void clear(void); ///< Reset all analysis of heritage
void placeMultiequals(void);
void rename(void);
void heritage(void); ///< Perform one pass of heritage
const list<LoadGuard> &getLoadGuards(void) const { return loadGuard; } ///< Get list of LOAD ops that are guarded
};
#endif