mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
6b4f9b71b5
4 changed files with 144 additions and 103 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
<patternlist>
|
<patternlist>
|
||||||
<patternpairs totalbits="32" postbits="16"> <!-- AARCH64 -->
|
<patternpairs totalbits="32" postbits="16"> <!-- AARCH64 -->
|
||||||
<prepatterns>
|
<prepatterns>
|
||||||
<data>0xc0 0x03 0x5f 0xd6 </data> <!-- ret -->
|
<data>0xc0 0x03 0x5f 0xd6 </data> <!-- ret -->
|
||||||
<data>0xff 0x0f 0x5f 0xd6 </data> <!-- retab -->
|
<data>0xc0 0x03 0x5f 0xd6 0x1f 0x20 0x03 0xd5 </data> <!-- ret; nop -->
|
||||||
<data> ........ ........ ........ 000101.. </data> <!-- b <xxx> shared jump call -->
|
<data>0xc0 0x03 0x5f 0xd6 0x1f 0x20 0x03 0xd5 0x1f 0x20 0x03 0xd5 </data> <!-- ret; nop; nop -->
|
||||||
<data> 0x20 0x00 0x20 0xd4 </data> <!-- brk #1 -->
|
<data>0xff 0x0f 0x5f 0xd6 </data> <!-- retab -->
|
||||||
|
<data> ........ ........ ........ 000101.. </data> <!-- b <xxx> shared jump call -->
|
||||||
|
<data> 0x20 0x00 0x20 0xd4 </data> <!-- brk #1 -->
|
||||||
</prepatterns>
|
</prepatterns>
|
||||||
|
|
||||||
<postpatterns>
|
<postpatterns>
|
||||||
<data> 0xfd 0x7b 0xbf 0xa9 </data> <!-- stp x29, x30, [sp, #-0x10]! -->
|
<data> 0xfd 0x7b 0xbf 0xa9 </data> <!-- stp x29, x30, [sp, #-0x10]! -->
|
||||||
<data> 0xfe .0001111 0x1. 0xf8 </data> <!-- stp x30, [sp, #-0x..0]! -->
|
<data> 0xfe .0001111 0x1. 0xf8 </data> <!-- stp x30, [sp, #-0x..0]! -->
|
||||||
<data> 111..... .1....11 10...... 0xa9 </data> <!-- stp x, x, [sp, -0x.0]! -->
|
<data> 111..... .1....11 10...... 0xa9 </data> <!-- stp x, x, [sp, -0x.0]! -->
|
||||||
<data> 11101..1 001..011 1011.... 0x6d </data> <!-- stp d, d, [sp, -0x.0]! -->
|
<data> 11101..1 001..011 1011.... 0x6d </data> <!-- stp d, d, [sp, -0x.0]! -->
|
||||||
<data> 0xff ..000011 000..... 0xd1 </data> <!-- sub sp, sp, #... -->
|
<data> 0xff ..000011 000..... 0xd1 </data> <!-- sub sp, sp, #... -->
|
||||||
<data> 0x7f 0x23 0x03 0xd5 </data> <!-- pacibsp -->
|
<data> 0x7f 0x23 0x03 0xd5 </data> <!-- pacibsp -->
|
||||||
|
<data> .1011111 0x24 0x03 0xd5 </data> <!-- bti c|jc -->
|
||||||
<codeboundary/>
|
<codeboundary/>
|
||||||
<possiblefuncstart/>
|
<possiblefuncstart/>
|
||||||
</postpatterns>
|
</postpatterns>
|
||||||
|
@ -52,17 +55,39 @@
|
||||||
</pattern>
|
</pattern>
|
||||||
|
|
||||||
<pattern> <!-- AARCH64 Thunk -->
|
<pattern> <!-- AARCH64 Thunk -->
|
||||||
<data> ...10000 ........ ........ 1..10000
|
<data>
|
||||||
00010001 ........ 01...... 0xf9
|
...10000 ........ ........ 1..10000 <!-- adrp x16, #... -->
|
||||||
0x10 ......10 00...... 0x91
|
00010001 ........ 01...... 0xf9 <!-- ldr x17, xxxx -->
|
||||||
0x20 0x02 0x1f 0xd6 </data>
|
0x10 ......10 00...... 0x91 <!-- add x16, x16 -->
|
||||||
<!-- adrp x16, #...
|
0x20 0x02 0x1f 0xd6 <!-- br x17 -->
|
||||||
ldr x17, xxxx
|
</data>
|
||||||
add x16, x16
|
<codeboundary /> <!-- definitely code -->
|
||||||
br x17
|
|
||||||
-->
|
|
||||||
<funcstart validcode="function" thunk="true"/>
|
<funcstart validcode="function" thunk="true"/>
|
||||||
</pattern>
|
</pattern>
|
||||||
|
|
||||||
</patternlist>
|
<pattern> <!-- AARCH64 Thunk -->
|
||||||
|
<data>
|
||||||
|
.1011111 0x24 0x03 0xd5 <!-- bti c|cj -->
|
||||||
|
...10000 ........ ........ 1..10000 <!-- adrp x16, #... -->
|
||||||
|
00010001 ........ 01...... 0xf9 <!-- ldr x17, xxxx -->
|
||||||
|
0x10 ......10 00...... 0x91 <!-- add x16, x16 -->
|
||||||
|
0x20 0x02 0x1f 0xd6 <!-- br x17 -->
|
||||||
|
</data>
|
||||||
|
<codeboundary /> <!-- definitely code -->
|
||||||
|
<funcstart validcode="function" thunk="true"/>
|
||||||
|
</pattern>
|
||||||
|
|
||||||
|
<pattern> <!-- AARCH64 Thunk -->
|
||||||
|
<data>
|
||||||
|
.1011111 0x24 0x03 0xd5 <!-- bti c|cj -->
|
||||||
|
0xf0 0x7b 0xbf 0xa9 <!-- stp x16,x30,[sp,#-0x10] -->
|
||||||
|
...10000 ........ ........ 1..10000 <!-- adrp x16, #... -->
|
||||||
|
00010001 ........ 01...... 0xf9 <!-- ldr x17, xxxx -->
|
||||||
|
0x10 ......10 00...... 0x91 <!-- add x16, x16 -->
|
||||||
|
0x20 0x02 0x1f 0xd6 <!-- br x17 -->
|
||||||
|
</data>
|
||||||
|
<codeboundary /> <!-- definitely code -->
|
||||||
|
<funcstart validcode="function" thunk="true"/>
|
||||||
|
</pattern>
|
||||||
|
|
||||||
|
</patternlist>
|
|
@ -57,19 +57,19 @@
|
||||||
<pentry minsize="4" maxsize="4" metatype="ptr">
|
<pentry minsize="4" maxsize="4" metatype="ptr">
|
||||||
<register name="a7"/>
|
<register name="a7"/>
|
||||||
</pentry>
|
</pentry>
|
||||||
<pentry minsize="1" maxsize="4"> <!-- This is the first non pointer -->
|
<pentry minsize="1" maxsize="4" extension="inttype"> <!-- This is the first non pointer -->
|
||||||
<register name="d4"/>
|
<register name="d4"/>
|
||||||
</pentry>
|
</pentry>
|
||||||
<pentry minsize="1" maxsize="4">
|
<pentry minsize="1" maxsize="4" extension="inttype">
|
||||||
<register name="d5"/>
|
<register name="d5"/>
|
||||||
</pentry>
|
</pentry>
|
||||||
<pentry minsize="5" maxsize="8"> <!-- This is the first >4 byte non pointer -->
|
<pentry minsize="5" maxsize="8"> <!-- This is the first >4 byte non pointer -->
|
||||||
<register name="e4"/>
|
<register name="e4"/>
|
||||||
</pentry>
|
</pentry>
|
||||||
<pentry minsize="1" maxsize="4">
|
<pentry minsize="1" maxsize="4" extension="inttype">
|
||||||
<register name="d6"/>
|
<register name="d6"/>
|
||||||
</pentry>
|
</pentry>
|
||||||
<pentry minsize="1" maxsize="4">
|
<pentry minsize="1" maxsize="4" extension="inttype">
|
||||||
<register name="d7"/>
|
<register name="d7"/>
|
||||||
</pentry>
|
</pentry>
|
||||||
<pentry minsize="5" maxsize="8">
|
<pentry minsize="5" maxsize="8">
|
||||||
|
@ -88,7 +88,7 @@
|
||||||
<pentry minsize="4" maxsize="4" metatype="ptr">
|
<pentry minsize="4" maxsize="4" metatype="ptr">
|
||||||
<register name="a2"/>
|
<register name="a2"/>
|
||||||
</pentry>
|
</pentry>
|
||||||
<pentry minsize="1" maxsize="4">
|
<pentry minsize="1" maxsize="4" extension="inttype">
|
||||||
<register name="d2"/>
|
<register name="d2"/>
|
||||||
</pentry>
|
</pentry>
|
||||||
<pentry minsize="5" maxsize="8">
|
<pentry minsize="5" maxsize="8">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue