GP-4416 Truncate LoadTable as part of sanity check

This commit is contained in:
caheckman 2024-03-21 23:55:33 +00:00
parent 4356cd33b8
commit 1a573da83d
2 changed files with 94 additions and 78 deletions

View file

@ -53,18 +53,44 @@ void LoadTable::decode(Decoder &decoder)
decoder.closeElement(elemId); decoder.closeElement(elemId);
} }
/// We assume the list of LoadTable entries is sorted and perform an in-place /// Sort the entries and collapse any contiguous sequences into a single LoadTable entry.
/// collapse of any sequences into a single LoadTable entry.
/// \param table is the list of entries to collapse /// \param table is the list of entries to collapse
void LoadTable::collapseTable(vector<LoadTable> &table) void LoadTable::collapseTable(vector<LoadTable> &table)
{ {
if (table.empty()) return; if (table.empty()) return;
vector<LoadTable>::iterator iter,lastiter;
// Test if the table is already sorted and contiguous entries
bool issorted = true;
vector<LoadTable>::iterator iter = table.begin();
int4 num = (*iter).num;
int4 size = (*iter).size;
Address nextaddr = (*iter).addr + size;
++iter;
for(;iter!=table.end();++iter) {
if ( (*iter).addr == nextaddr && (*iter).size == size) {
num += (*iter).num;
nextaddr = (*iter).addr + (*iter).size;
}
else {
issorted = false;
break;
}
}
if (issorted) {
// Table is sorted and contiguous.
table.resize(1); // Truncate everything but the first entry
table.front().num = num;
return;
}
sort(table.begin(),table.end());
int4 count = 1; int4 count = 1;
iter = table.begin(); iter = table.begin();
lastiter = iter; vector<LoadTable>::iterator lastiter = iter;
Address nextaddr = (*iter).addr + (*iter).size * (*iter).num; nextaddr = (*iter).addr + (*iter).size * (*iter).num;
++iter; ++iter;
for(;iter!=table.end();++iter) { for(;iter!=table.end();++iter) {
if (( (*iter).addr == nextaddr ) && ((*iter).size == (*lastiter).size)) { if (( (*iter).addr == nextaddr ) && ((*iter).size == (*lastiter).size)) {
@ -85,12 +111,12 @@ void LoadTable::collapseTable(vector<LoadTable> &table)
void EmulateFunction::executeLoad(void) void EmulateFunction::executeLoad(void)
{ {
if (collectloads) { if (loadpoints != (vector<LoadTable> *)0) {
uintb off = getVarnodeValue(currentOp->getIn(1)); uintb off = getVarnodeValue(currentOp->getIn(1));
AddrSpace *spc = currentOp->getIn(0)->getSpaceFromConst(); AddrSpace *spc = currentOp->getIn(0)->getSpaceFromConst();
off = AddrSpace::addressToByte(off,spc->getWordSize()); off = AddrSpace::addressToByte(off,spc->getWordSize());
int4 sz = currentOp->getOut()->getSize(); int4 sz = currentOp->getOut()->getSize();
loadpoints.push_back(LoadTable(Address(spc,off),sz)); loadpoints->push_back(LoadTable(Address(spc,off),sz));
} }
EmulatePcodeOp::executeLoad(); EmulatePcodeOp::executeLoad();
} }
@ -133,7 +159,7 @@ EmulateFunction::EmulateFunction(Funcdata *f)
: EmulatePcodeOp(f->getArch()) : EmulatePcodeOp(f->getArch())
{ {
fd = f; fd = f;
collectloads = false; loadpoints = (vector<LoadTable> *)0;
} }
void EmulateFunction::setExecuteAddress(const Address &addr) void EmulateFunction::setExecuteAddress(const Address &addr)
@ -225,39 +251,6 @@ uintb EmulateFunction::emulatePath(uintb val,const PathMeld &pathMeld,
return getVarnodeValue(invn); return getVarnodeValue(invn);
} }
/// Pass back any LOAD records collected during emulation. The individual records
/// are sorted and collapsed into concise \e table descriptions.
/// \param res will hold any resulting table descriptions
void EmulateFunction::collectLoadPoints(vector<LoadTable> &res) const
{
if (loadpoints.empty()) return;
bool issorted = true;
vector<LoadTable>::const_iterator iter;
vector<LoadTable>::iterator lastiter;
iter = loadpoints.begin();
res.push_back( *iter ); // Copy the first entry
++iter;
lastiter = res.begin();
Address nextaddr = (*lastiter).addr + (*lastiter).size;
for(;iter!=loadpoints.end();++iter) {
if (issorted && (( (*iter).addr == nextaddr ) && ((*iter).size == (*lastiter).size))) {
(*lastiter).num += (*iter).num;
nextaddr = (*iter).addr + (*iter).size;
}
else {
issorted = false;
res.push_back( *iter );
}
}
if (!issorted) {
sort(res.begin(),res.end());
LoadTable::collapseTable(res);
}
}
/// The starting value for the range and the step is preserved. The /// The starting value for the range and the step is preserved. The
/// ending value is set so there are exactly the given number of elements /// ending value is set so there are exactly the given number of elements
/// in the range. /// in the range.
@ -398,8 +391,8 @@ bool JumpModelTrivial::recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize,
return ((size != 0)&&(size<=matchsize)); return ((size != 0)&&(size<=matchsize));
} }
void JumpModelTrivial::buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,vector<LoadTable> *loadpoints) const void JumpModelTrivial::buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> *loadpoints,vector<int4> *loadcounts) const
{ {
addresstable.clear(); addresstable.clear();
BlockBasic *bl = indop->getParent(); BlockBasic *bl = indop->getParent();
@ -1423,15 +1416,14 @@ bool JumpBasic::recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize,uint4 m
return true; return true;
} }
void JumpBasic::buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,vector<LoadTable> *loadpoints) const void JumpBasic::buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> *loadpoints,vector<int4> *loadcounts) const
{ {
uintb val,addr; uintb val,addr;
addresstable.clear(); // Clear out any partial recoveries addresstable.clear(); // Clear out any partial recoveries
// Build the emulation engine // Build the emulation engine
EmulateFunction emul(fd); EmulateFunction emul(fd);
if (loadpoints != (vector<LoadTable> *)0) emul.setLoadCollect(loadpoints);
emul.setLoadCollect(true);
uintb mask = ~((uintb)0); uintb mask = ~((uintb)0);
int4 bit = fd->getArch()->funcptr_align; int4 bit = fd->getArch()->funcptr_align;
@ -1446,10 +1438,10 @@ void JumpBasic::buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addr
addr = AddrSpace::addressToByte(addr,spc->getWordSize()); addr = AddrSpace::addressToByte(addr,spc->getWordSize());
addr &= mask; addr &= mask;
addresstable.push_back(Address(spc,addr)); addresstable.push_back(Address(spc,addr));
if (loadcounts != (vector<int4> *)0)
loadcounts->push_back(loadpoints->size());
notdone = jrange->next(); notdone = jrange->next();
} }
if (loadpoints != (vector<LoadTable> *)0)
emul.collectLoadPoints(*loadpoints);
} }
void JumpBasic::findUnnormalized(uint4 maxaddsub,uint4 maxleftright,uint4 maxext) void JumpBasic::findUnnormalized(uint4 maxaddsub,uint4 maxleftright,uint4 maxext)
@ -1562,8 +1554,8 @@ bool JumpBasic::foldInGuards(Funcdata *fd,JumpTable *jump)
return change; return change;
} }
bool JumpBasic::sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable) bool JumpBasic::sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> &loadpoints,vector<int4> *loadcounts)
{ {
// Test all the addresses in \b this address table checking // Test all the addresses in \b this address table checking
// that they are reasonable. We cut off at the first unreasonable address. // that they are reasonable. We cut off at the first unreasonable address.
@ -1596,6 +1588,9 @@ bool JumpBasic::sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &address
if (i!=addresstable.size()) { if (i!=addresstable.size()) {
addresstable.resize(i); addresstable.resize(i);
jrange->truncate(i); jrange->truncate(i);
if (loadcounts != (vector<int4> *)0) {
loadpoints.resize((*loadcounts)[i-1]);
}
} }
return true; return true;
} }
@ -1967,8 +1962,8 @@ bool JumpBasicOverride::recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize
return true; return true;
} }
void JumpBasicOverride::buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,vector<LoadTable> *loadpoints) const void JumpBasicOverride::buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> *loadpoints,vector<int4> *loadcounts) const
{ {
addresstable = addrtable; // Addresses are already calculated, just copy them out addresstable = addrtable; // Addresses are already calculated, just copy them out
} }
@ -2116,8 +2111,8 @@ bool JumpAssisted::recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize,uint
return true; return true;
} }
void JumpAssisted::buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,vector<LoadTable> *loadpoints) const void JumpAssisted::buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> *loadpoints,vector<int4> *loadcounts) const
{ {
if (userop->getIndex2Addr() == -1) if (userop->getIndex2Addr() == -1)
throw LowlevelError("Final index2addr calculation outside of jumpassist"); throw LowlevelError("Final index2addr calculation outside of jumpassist");
@ -2249,8 +2244,11 @@ void JumpTable::recoverModel(Funcdata *fd)
/// Check pathological cases when there is only one address in the table, if we find /// Check pathological cases when there is only one address in the table, if we find
/// this, throw the JumptableThunkError. Let the model run its sanity check. /// this, throw the JumptableThunkError. Let the model run its sanity check.
/// Print a warning if the sanity check truncates the original address table. /// Print a warning if the sanity check truncates the original address table.
/// Passing in \b loadcounts indicates that LOADs were collected in \b loadpoints, which may
/// need to be truncated as well.
/// \param fd is the function containing the switch /// \param fd is the function containing the switch
void JumpTable::sanityCheck(Funcdata *fd) /// \param loadcounts (if non-null) associates each switch value with the number of LOADs it needed
void JumpTable::sanityCheck(Funcdata *fd,vector<int4> *loadcounts)
{ {
if (jmodel->isOverride()) if (jmodel->isOverride())
@ -2277,7 +2275,7 @@ void JumpTable::sanityCheck(Funcdata *fd)
throw JumptableThunkError("Likely thunk"); throw JumptableThunkError("Likely thunk");
} }
} }
if (!jmodel->sanityCheck(fd,indirect,addresstable)) { if (!jmodel->sanityCheck(fd,indirect,addresstable,loadpoints,loadcounts)) {
ostringstream err; ostringstream err;
err << "Jumptable at " << opaddress << " did not pass sanity check."; err << "Jumptable at " << opaddress << " did not pass sanity check.";
throw LowlevelError(err.str()); throw LowlevelError(err.str());
@ -2592,11 +2590,16 @@ void JumpTable::recoverAddresses(Funcdata *fd)
} }
// if (sz < 2) // if (sz < 2)
// fd->warning("Jumptable has only one branch",opaddress); // fd->warning("Jumptable has only one branch",opaddress);
if (collectloads) if (collectloads) {
jmodel->buildAddresses(fd,indirect,addresstable,&loadpoints); vector<int4> loadcounts;
else jmodel->buildAddresses(fd,indirect,addresstable,&loadpoints,&loadcounts);
jmodel->buildAddresses(fd,indirect,addresstable,(vector<LoadTable> *)0); sanityCheck(fd,&loadcounts);
sanityCheck(fd); LoadTable::collapseTable(loadpoints);
}
else {
jmodel->buildAddresses(fd,indirect,addresstable,(vector<LoadTable> *)0,(vector<int4> *)0);
sanityCheck(fd,(vector<int4> *)0);
}
} }
/// Do a normal recoverAddresses, but save off the old JumpModel, and if we fail recovery, put back the old model. /// Do a normal recoverAddresses, but save off the old JumpModel, and if we fail recovery, put back the old model.
@ -2683,7 +2686,7 @@ bool JumpTable::recoverLabels(Funcdata *fd)
else { else {
jmodel = new JumpModelTrivial(this); jmodel = new JumpModelTrivial(this);
jmodel->recoverModel(fd,indirect,addresstable.size(),glb->max_jumptable_size); jmodel->recoverModel(fd,indirect,addresstable.size(),glb->max_jumptable_size);
jmodel->buildAddresses(fd,indirect,addresstable,(vector<LoadTable> *)0); jmodel->buildAddresses(fd,indirect,addresstable,(vector<LoadTable> *)0,(vector<int4> *)0);
trivialSwitchOver(); trivialSwitchOver();
jmodel->buildLabels(fd,addresstable,label,origmodel); jmodel->buildLabels(fd,addresstable,label,origmodel);
} }

View file

@ -113,8 +113,7 @@ public:
class EmulateFunction : public EmulatePcodeOp { class EmulateFunction : public EmulatePcodeOp {
Funcdata *fd; ///< The function being emulated Funcdata *fd; ///< The function being emulated
map<Varnode *,uintb> varnodeMap; ///< Light-weight memory state based on Varnodes map<Varnode *,uintb> varnodeMap; ///< Light-weight memory state based on Varnodes
bool collectloads; ///< Set to \b true if the emulator collects individual LOAD addresses vector<LoadTable> *loadpoints; ///< The set of collected LOAD records (if non-null)
vector<LoadTable> loadpoints; ///< The set of collected LOAD records
virtual void executeLoad(void); virtual void executeLoad(void);
virtual void executeBranch(void); virtual void executeBranch(void);
virtual void executeBranchind(void); virtual void executeBranchind(void);
@ -124,12 +123,11 @@ class EmulateFunction : public EmulatePcodeOp {
virtual void fallthruOp(void); virtual void fallthruOp(void);
public: public:
EmulateFunction(Funcdata *f); ///< Constructor EmulateFunction(Funcdata *f); ///< Constructor
void setLoadCollect(bool val) { collectloads = val; } ///< Set whether we collect LOAD information void setLoadCollect(vector<LoadTable> *val) { loadpoints = val; } ///< Set where/if we collect LOAD information
virtual void setExecuteAddress(const Address &addr); virtual void setExecuteAddress(const Address &addr);
virtual uintb getVarnodeValue(Varnode *vn) const; virtual uintb getVarnodeValue(Varnode *vn) const;
virtual void setVarnodeValue(Varnode *vn,uintb val); virtual void setVarnodeValue(Varnode *vn,uintb val);
uintb emulatePath(uintb val,const PathMeld &pathMeld,PcodeOp *startop,Varnode *startvn); uintb emulatePath(uintb val,const PathMeld &pathMeld,PcodeOp *startop,Varnode *startvn);
void collectLoadPoints(vector<LoadTable> &res) const; ///< Recover any LOAD table descriptions
}; };
class FlowInfo; class FlowInfo;
@ -271,7 +269,9 @@ public:
/// \param indop is the root BRANCHIND of the switch /// \param indop is the root BRANCHIND of the switch
/// \param addresstable will hold the list of Addresses /// \param addresstable will hold the list of Addresses
/// \param loadpoints if non-null will hold LOAD table information used by the model /// \param loadpoints if non-null will hold LOAD table information used by the model
virtual void buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,vector<LoadTable> *loadpoints) const=0; /// \param loadcounts if non-null will hold number of LOADs per switch value
virtual void buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> *loadpoints,vector<int4> *loadcounts) const=0;
/// \brief Recover the unnormalized switch variable /// \brief Recover the unnormalized switch variable
/// ///
@ -316,11 +316,16 @@ public:
/// Individual addresses are checked against the function or its program to determine /// Individual addresses are checked against the function or its program to determine
/// if they are reasonable. This method can optionally remove addresses from the table. /// if they are reasonable. This method can optionally remove addresses from the table.
/// If it does so, the underlying model is changed to reflect the removal. /// If it does so, the underlying model is changed to reflect the removal.
/// Passing in \b loadcounts indicates that LOAD addresses were collected in \b loadpoints,
/// which may need to have elements removed as well.
/// \param fd is the function containing the switch /// \param fd is the function containing the switch
/// \param indop is the root BRANCHIND of the switch /// \param indop is the root BRANCHIND of the switch
/// \param addresstable is the list of recovered Addresses, which may be modified /// \param addresstable is the list of recovered Addresses, which may be modified
/// \param loadpoints are any LOAD addresses associated with the table
/// \param loadcounts (if non-null) associates each switch value with the count of LOADs used
/// \return \b true if there are (at least some) reasonable addresses in the table /// \return \b true if there are (at least some) reasonable addresses in the table
virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable)=0; virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> &loadpoints,vector<int4> *loadcounts)=0;
virtual JumpModel *clone(JumpTable *jt) const=0; ///< Clone \b this model virtual JumpModel *clone(JumpTable *jt) const=0; ///< Clone \b this model
@ -351,12 +356,14 @@ public:
virtual bool isOverride(void) const { return false; } virtual bool isOverride(void) const { return false; }
virtual int4 getTableSize(void) const { return size; } virtual int4 getTableSize(void) const { return size; }
virtual bool recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize,uint4 maxtablesize); virtual bool recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize,uint4 maxtablesize);
virtual void buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,vector<LoadTable> *loadpoints) const; virtual void buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> *loadpoints,vector<int4> *loadcounts) const;
virtual void findUnnormalized(uint4 maxaddsub,uint4 maxleftright,uint4 maxext) {} virtual void findUnnormalized(uint4 maxaddsub,uint4 maxleftright,uint4 maxext) {}
virtual void buildLabels(Funcdata *fd,vector<Address> &addresstable,vector<uintb> &label,const JumpModel *orig) const; virtual void buildLabels(Funcdata *fd,vector<Address> &addresstable,vector<uintb> &label,const JumpModel *orig) const;
virtual Varnode *foldInNormalization(Funcdata *fd,PcodeOp *indop) { return (Varnode *)0; } virtual Varnode *foldInNormalization(Funcdata *fd,PcodeOp *indop) { return (Varnode *)0; }
virtual bool foldInGuards(Funcdata *fd,JumpTable *jump) { return false; } virtual bool foldInGuards(Funcdata *fd,JumpTable *jump) { return false; }
virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable) { return true; } virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> &loadpoints,vector<int4> *loadcounts) { return true; }
virtual JumpModel *clone(JumpTable *jt) const; virtual JumpModel *clone(JumpTable *jt) const;
}; };
@ -408,12 +415,14 @@ public:
virtual bool isOverride(void) const { return false; } virtual bool isOverride(void) const { return false; }
virtual int4 getTableSize(void) const { return jrange->getSize(); } virtual int4 getTableSize(void) const { return jrange->getSize(); }
virtual bool recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize,uint4 maxtablesize); virtual bool recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize,uint4 maxtablesize);
virtual void buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,vector<LoadTable> *loadpoints) const; virtual void buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> *loadpoints,vector<int4> *loadcounts) const;
virtual void findUnnormalized(uint4 maxaddsub,uint4 maxleftright,uint4 maxext); virtual void findUnnormalized(uint4 maxaddsub,uint4 maxleftright,uint4 maxext);
virtual void buildLabels(Funcdata *fd,vector<Address> &addresstable,vector<uintb> &label,const JumpModel *orig) const; virtual void buildLabels(Funcdata *fd,vector<Address> &addresstable,vector<uintb> &label,const JumpModel *orig) const;
virtual Varnode *foldInNormalization(Funcdata *fd,PcodeOp *indop); virtual Varnode *foldInNormalization(Funcdata *fd,PcodeOp *indop);
virtual bool foldInGuards(Funcdata *fd,JumpTable *jump); virtual bool foldInGuards(Funcdata *fd,JumpTable *jump);
virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable); virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> &loadpoints,vector<int4> *loadcounts);
virtual JumpModel *clone(JumpTable *jt) const; virtual JumpModel *clone(JumpTable *jt) const;
virtual void clear(void); virtual void clear(void);
}; };
@ -471,12 +480,14 @@ public:
virtual bool isOverride(void) const { return true; } virtual bool isOverride(void) const { return true; }
virtual int4 getTableSize(void) const { return addrtable.size(); } virtual int4 getTableSize(void) const { return addrtable.size(); }
virtual bool recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize,uint4 maxtablesize); virtual bool recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize,uint4 maxtablesize);
virtual void buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,vector<LoadTable> *loadpoints) const; virtual void buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> *loadpoints,vector<int4> *loadcounts) const;
// findUnnormalized inherited from JumpBasic // findUnnormalized inherited from JumpBasic
virtual void buildLabels(Funcdata *fd,vector<Address> &addresstable,vector<uintb> &label,const JumpModel *orig) const; virtual void buildLabels(Funcdata *fd,vector<Address> &addresstable,vector<uintb> &label,const JumpModel *orig) const;
// foldInNormalization inherited from JumpBasic // foldInNormalization inherited from JumpBasic
virtual bool foldInGuards(Funcdata *fd,JumpTable *jump) { return false; } virtual bool foldInGuards(Funcdata *fd,JumpTable *jump) { return false; }
virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable) { return true; } virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> &loadpoints,vector<int4> *loadcounts) { return true; }
virtual JumpModel *clone(JumpTable *jt) const; virtual JumpModel *clone(JumpTable *jt) const;
virtual void clear(void); virtual void clear(void);
virtual void encode(Encoder &encoder) const; virtual void encode(Encoder &encoder) const;
@ -508,12 +519,14 @@ public:
virtual bool isOverride(void) const { return false; } virtual bool isOverride(void) const { return false; }
virtual int4 getTableSize(void) const { return sizeIndices+1; } virtual int4 getTableSize(void) const { return sizeIndices+1; }
virtual bool recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize,uint4 maxtablesize); virtual bool recoverModel(Funcdata *fd,PcodeOp *indop,uint4 matchsize,uint4 maxtablesize);
virtual void buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,vector<LoadTable> *loadpoints) const; virtual void buildAddresses(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> *loadpoints,vector<int4> *loadcounts) const;
virtual void findUnnormalized(uint4 maxaddsub,uint4 maxleftright,uint4 maxext) {} virtual void findUnnormalized(uint4 maxaddsub,uint4 maxleftright,uint4 maxext) {}
virtual void buildLabels(Funcdata *fd,vector<Address> &addresstable,vector<uintb> &label,const JumpModel *orig) const; virtual void buildLabels(Funcdata *fd,vector<Address> &addresstable,vector<uintb> &label,const JumpModel *orig) const;
virtual Varnode *foldInNormalization(Funcdata *fd,PcodeOp *indop); virtual Varnode *foldInNormalization(Funcdata *fd,PcodeOp *indop);
virtual bool foldInGuards(Funcdata *fd,JumpTable *jump); virtual bool foldInGuards(Funcdata *fd,JumpTable *jump);
virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable) { return true; } virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable,
vector<LoadTable> &loadpoints,vector<int4> *loadcounts) { return true; }
virtual JumpModel *clone(JumpTable *jt) const; virtual JumpModel *clone(JumpTable *jt) const;
virtual void clear(void) { assistOp = (PcodeOp *)0; switchvn = (Varnode *)0; } virtual void clear(void) { assistOp = (PcodeOp *)0; switchvn = (Varnode *)0; }
}; };
@ -563,7 +576,7 @@ private:
bool collectloads; ///< Set to \b true if information about in-memory model data is/should be collected bool collectloads; ///< Set to \b true if information about in-memory model data is/should be collected
void recoverModel(Funcdata *fd); ///< Attempt recovery of the jump-table model void recoverModel(Funcdata *fd); ///< Attempt recovery of the jump-table model
void trivialSwitchOver(void); ///< Switch \b this table over to a trivial model void trivialSwitchOver(void); ///< Switch \b this table over to a trivial model
void sanityCheck(Funcdata *fd); ///< Perform sanity check on recovered address targets void sanityCheck(Funcdata *fd,vector<int4> *loadpoints); ///< Perform sanity check on recovered address targets
int4 block2Position(const FlowBlock *bl) const; ///< Convert a basic-block to an out-edge index from the switch. int4 block2Position(const FlowBlock *bl) const; ///< Convert a basic-block to an out-edge index from the switch.
static bool isReachable(PcodeOp *op); ///< Check if the given PcodeOp still seems reachable in its function static bool isReachable(PcodeOp *op); ///< Check if the given PcodeOp still seems reachable in its function
public: public: