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 /// \return \b true if the Varnode is fully linked
bool isHeritaged(Varnode *vn) { return (heritage.heritagePass(vn->getAddr())>=0); } 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 // Function prototype and call specification routines
int4 numCalls(void) const { return qlst.size(); } ///< Get the number of calls made by \b this function 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 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 /// 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 /// \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() ); const CircleRange &range( valueSet.getRange() );
uintb rangeSize = range.getSize(); uintb rangeSize = range.getSize();
uintb size; uintb size;
if (range.isEmpty()) { if (range.isEmpty()) {
step = 0;
minimumOffset = pointerBase; minimumOffset = pointerBase;
size = 0x1000; size = 0x1000;
} }
else if (range.isFull() || rangeSize > 0xffffff) { else if (range.isFull() || rangeSize > 0xffffff) {
step = 1;
minimumOffset = pointerBase; minimumOffset = pointerBase;
size = 0x1000; size = 0x1000;
isAnalyzed = true; // Don't bother doing more analysis analysisState = 1; // Don't bother doing more analysis
} }
else { else {
step = (rangeSize == 3) ? range.getStep() : 0; // Check for consistent step 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() ); const CircleRange &range( valueSet.getRange() );
uintb rangeSize = range.getSize(); uintb rangeSize = range.getSize();
if (rangeSize > 1 && rangeSize < 0xffffff) { // Did we converge to something reasonable if (rangeSize > 1 && rangeSize < 0xffffff) { // Did we converge to something reasonable
analysisState = 2; // Mark that we got a definitive result
step = range.getStep(); step = range.getStep();
minimumOffset = range.getMin(); minimumOffset = range.getMin();
maximumOffset = range.getMax(); maximumOffset = range.getMax();
if (maximumOffset < minimumOffset) // Values extend into what is usually stack parameters if (maximumOffset < minimumOffset) // Values extend into what is usually stack parameters
maximumOffset = spc->getHighest(); maximumOffset = spc->getHighest();
} }
if (step == 0)
step = 1;
if (minimumOffset > spc->getHighest()) if (minimumOffset > spc->getHighest())
minimumOffset = spc->getHighest(); minimumOffset = spc->getHighest();
if (maximumOffset > spc->getHighest()) if (maximumOffset > spc->getHighest())
@ -652,14 +649,14 @@ void Heritage::analyzeNewLoadGuards(void)
{ {
if (loadGuard.empty()) return; 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(); list<LoadGuard>::iterator startIter = loadGuard.end();
vector<Varnode *> sinks; vector<Varnode *> sinks;
vector<PcodeOp *> reads; vector<PcodeOp *> reads;
while(startIter != loadGuard.begin()) { while(startIter != loadGuard.begin()) {
--startIter; --startIter;
LoadGuard &guard( *startIter ); LoadGuard &guard( *startIter );
if (guard.isAnalyzed) break; if (guard.analysisState != 0) break;
reads.push_back(guard.op); reads.push_back(guard.op);
sinks.push_back(guard.op->getIn(1)); // The CPUI_LOAD pointer 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) { for(iter=startIter;iter!=loadGuard.end(); ++iter) {
LoadGuard &guard( *iter ); LoadGuard &guard( *iter );
guard.establishRange(vsSolver.getValueSetRead(guard.op->getSeqNum())); guard.establishRange(vsSolver.getValueSetRead(guard.op->getSeqNum()));
if (!guard.isAnalyzed) if (guard.analysisState == 0)
runFullAnalysis = true; runFullAnalysis = true;
} }
if (runFullAnalysis) { if (runFullAnalysis) {
@ -700,13 +697,7 @@ void Heritage::generateLoadGuard(StackNode &node,PcodeOp *op,AddrSpace *spc)
{ {
loadGuard.push_back(LoadGuard()); loadGuard.push_back(LoadGuard());
LoadGuard &guard( loadGuard.back() ); loadGuard.back().set(op,spc,node.offset);
guard.op = op;
guard.spc = spc;
guard.pointerBase = node.offset;
guard.minimumOffset = 0; // Initially we guard everything
guard.maximumOffset = spc->getHighest();
guard.isAnalyzed = false;
} }
/// \brief Trace input stackpointer to any indexed loads /// \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 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 /// \brief Manage the construction of Static Single Assignment (SSA) form
/// ///
/// With a specific function (Funcdata), this class links the Varnode and /// 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 Funcdata *fd; ///< The function \b this is controlling SSA construction
LocationMap globaldisjoint; ///< Disjoint cover of every heritaged memory location LocationMap globaldisjoint; ///< Disjoint cover of every heritaged memory location
LocationMap disjoint; ///< Disjoint cover of memory locations currently being heritaged LocationMap disjoint; ///< Disjoint cover of memory locations currently being heritaged
@ -229,6 +248,8 @@ class Heritage {
void calcMultiequals(const vector<Varnode *> &write); void calcMultiequals(const vector<Varnode *> &write);
void renameRecurse(BlockBasic *bl,VariableStack &varstack); void renameRecurse(BlockBasic *bl,VariableStack &varstack);
void bumpDeadcodeDelay(Varnode *vn); void bumpDeadcodeDelay(Varnode *vn);
void placeMultiequals(void);
void rename(void);
public: public:
Heritage(Funcdata *data); ///< Constructor Heritage(Funcdata *data); ///< Constructor
@ -246,9 +267,8 @@ public:
void buildInfoList(void); ///< Initialize information for each space void buildInfoList(void); ///< Initialize information for each space
void forceRestructure(void) { maxdepth = -1; } ///< Force regeneration of basic block structures void forceRestructure(void) { maxdepth = -1; } ///< Force regeneration of basic block structures
void clear(void); ///< Reset all analysis of heritage void clear(void); ///< Reset all analysis of heritage
void placeMultiequals(void);
void rename(void);
void heritage(void); ///< Perform one pass of heritage 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 #endif