mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
rearrange LoadGuard class
This commit is contained in:
parent
e1507d05ec
commit
8cad85e36c
3 changed files with 47 additions and 34 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue