Better triggering for ActionLaneDivide

This commit is contained in:
caheckman 2020-03-23 10:06:50 -04:00
parent b3bd637d99
commit 791f16101e
5 changed files with 28 additions and 39 deletions

View file

@ -607,6 +607,7 @@ int4 ActionLaneDivide::apply(Funcdata &data)
if (allStorageProcessed) break; if (allStorageProcessed) break;
} }
data.clearLanedAccessMap(); data.clearLanedAccessMap();
data.setLanedRegGenerated();
return 0; return 0;
} }
@ -1209,31 +1210,11 @@ int4 ActionDeindirect::apply(Funcdata &data)
return 0; return 0;
} }
/// Check if the given Varnode has a matching LanedRegister record. If so, add its
/// storage location to the given function's laned access list.
/// \param data is the given function
/// \param vn is the given Varnode
void ActionVarnodeProps::markLanedVarnode(Funcdata &data,Varnode *vn)
{
if (vn->isConstant()) return;
Architecture *glb = data.getArch();
const LanedRegister *lanedRegister = glb->getLanedRegister(vn->getAddr(),vn->getSize());
if (lanedRegister != (const LanedRegister *)0)
data.markLanedVarnode(vn,lanedRegister);
}
int4 ActionVarnodeProps::apply(Funcdata &data) int4 ActionVarnodeProps::apply(Funcdata &data)
{ {
Architecture *glb = data.getArch(); Architecture *glb = data.getArch();
bool cachereadonly = glb->readonlypropagate; bool cachereadonly = glb->readonlypropagate;
int4 minLanedSize = 1000000; // Default size meant to filter no Varnodes
if (!data.isLanedRegComplete()) {
int4 sz = glb->getMinimumLanedRegisterSize();
if (sz > 0)
minLanedSize = sz;
}
VarnodeLocSet::const_iterator iter; VarnodeLocSet::const_iterator iter;
Varnode *vn; Varnode *vn;
@ -1242,8 +1223,6 @@ int4 ActionVarnodeProps::apply(Funcdata &data)
vn = *iter++; // Advance iterator in case vn is deleted vn = *iter++; // Advance iterator in case vn is deleted
if (vn->isAnnotation()) continue; if (vn->isAnnotation()) continue;
int4 vnSize = vn->getSize(); int4 vnSize = vn->getSize();
if (vnSize >= minLanedSize)
markLanedVarnode(data, vn);
if (vn->hasActionProperty()) { if (vn->hasActionProperty()) {
if (cachereadonly&&vn->isReadOnly()) { if (cachereadonly&&vn->isReadOnly()) {
if (data.fillinReadOnly(vn)) // Try to replace vn with its lookup in LoadImage if (data.fillinReadOnly(vn)) // Try to replace vn with its lookup in LoadImage

View file

@ -211,9 +211,7 @@ public:
/// - Read-only Varnodes are converted to the underlying constant /// - Read-only Varnodes are converted to the underlying constant
/// - Volatile Varnodes are converted read/write functions /// - Volatile Varnodes are converted read/write functions
/// - Varnodes whose values are not consumed are replaced with constant 0 Varnodes /// - Varnodes whose values are not consumed are replaced with constant 0 Varnodes
/// - Large Varnodes are flagged for lane analysis
class ActionVarnodeProps : public Action { class ActionVarnodeProps : public Action {
void markLanedVarnode(Funcdata &data,Varnode *vn); ///< Mark possible laned register storage
public: public:
ActionVarnodeProps(const string &g) : Action(0,"varnodeprops",g) {} ///< Constructor ActionVarnodeProps(const string &g) : Action(0,"varnodeprops",g) {} ///< Constructor
virtual Action *clone(const ActionGroupList &grouplist) const { virtual Action *clone(const ActionGroupList &grouplist) const {

View file

@ -36,6 +36,7 @@ Funcdata::Funcdata(const string &nm,Scope *scope,const Address &addr,int4 sz)
high_level_index = 0; high_level_index = 0;
cast_phase_index = 0; cast_phase_index = 0;
glb = scope->getArch(); glb = scope->getArch();
minLanedSize = glb->getMinimumLanedRegisterSize();
name = nm; name = nm;
size = sz; size = sz;
@ -69,6 +70,7 @@ void Funcdata::clear(void)
clean_up_index = 0; clean_up_index = 0;
high_level_index = 0; high_level_index = 0;
cast_phase_index = 0; cast_phase_index = 0;
minLanedSize = glb->getMinimumLanedRegisterSize();
localmap->clearUnlocked(); // Clear non-permanent stuff localmap->clearUnlocked(); // Clear non-permanent stuff
localmap->resetLocalWindow(); localmap->resetLocalWindow();

View file

@ -56,13 +56,13 @@ class Funcdata {
restart_pending = 0x200, ///< Analysis must be restarted (because of new override info) restart_pending = 0x200, ///< Analysis must be restarted (because of new override info)
unimplemented_present = 0x400, ///< Set if function contains unimplemented instructions unimplemented_present = 0x400, ///< Set if function contains unimplemented instructions
baddata_present = 0x800, ///< Set if function flowed into bad data baddata_present = 0x800, ///< Set if function flowed into bad data
double_precis_on = 0x1000, ///< Set if we are performing double precision recovery double_precis_on = 0x1000 ///< Set if we are performing double precision recovery
big_varnodes_generated = 0x2000 ///< Set when search for laned registers is complete
}; };
uint4 flags; ///< Boolean properties associated with \b this function uint4 flags; ///< Boolean properties associated with \b this function
uint4 clean_up_index; ///< Creation index of first Varnode created after start of cleanup uint4 clean_up_index; ///< Creation index of first Varnode created after start of cleanup
uint4 high_level_index; ///< Creation index of first Varnode created after HighVariables are created uint4 high_level_index; ///< Creation index of first Varnode created after HighVariables are created
uint4 cast_phase_index; ///< Creation index of first Varnode created after ActionSetCasts uint4 cast_phase_index; ///< Creation index of first Varnode created after ActionSetCasts
uint4 minLanedSize; ///< Minimum Varnode size to check as LanedRegister
Architecture *glb; ///< Global configuration data Architecture *glb; ///< Global configuration data
string name; ///< Name of function string name; ///< Name of function
int4 size; ///< Number of bytes of binary data in function body int4 size; ///< Number of bytes of binary data in function body
@ -132,8 +132,7 @@ public:
bool isTypeRecoveryOn(void) const { return ((flags&typerecovery_on)!=0); } ///< Has data-type recovery processes started bool isTypeRecoveryOn(void) const { return ((flags&typerecovery_on)!=0); } ///< Has data-type recovery processes started
bool hasNoCode(void) const { return ((flags & no_code)!=0); } ///< Return \b true if \b this function has no code body bool hasNoCode(void) const { return ((flags & no_code)!=0); } ///< Return \b true if \b this function has no code body
void setNoCode(bool val) { if (val) flags |= no_code; else flags &= ~no_code; } ///< Toggle whether \b this has a body void setNoCode(bool val) { if (val) flags |= no_code; else flags &= ~no_code; } ///< Toggle whether \b this has a body
bool isLanedRegComplete(void) const { return ((flags&big_varnodes_generated)!=0); } ///< Have potential laned registers been generated void setLanedRegGenerated(void) { minLanedSize = 1000000; } ///< Mark that laned registers have been collected
void setLanedRegGenerated(void) { flags |= big_varnodes_generated; } ///< Mark that laned registers have been collected
/// \brief Toggle whether \b this is being used for jump-table recovery /// \brief Toggle whether \b this is being used for jump-table recovery
/// ///
@ -350,7 +349,7 @@ public:
/// \brief End of (input or free) Varnodes at a given storage address /// \brief End of (input or free) Varnodes at a given storage address
VarnodeDefSet::const_iterator endDef(uint4 fl,const Address &addr) const { return vbank.endDef(fl,addr); } VarnodeDefSet::const_iterator endDef(uint4 fl,const Address &addr) const { return vbank.endDef(fl,addr); }
void markLanedVarnode(Varnode *vn,const LanedRegister *lanedReg); ///< Mark Varnode as potential laned register void checkForLanedRegister(int4 size,const Address &addr); ///< Check for a potential laned register
map<VarnodeData,const LanedRegister *>::const_iterator beginLaneAccess(void) const { return lanedMap.begin(); } ///< Beginning iterator over laned accesses map<VarnodeData,const LanedRegister *>::const_iterator beginLaneAccess(void) const { return lanedMap.begin(); } ///< Beginning iterator over laned accesses
map<VarnodeData,const LanedRegister *>::const_iterator endLaneAccess(void) const { return lanedMap.end(); } ///< Ending iterator over laned accesses map<VarnodeData,const LanedRegister *>::const_iterator endLaneAccess(void) const { return lanedMap.end(); } ///< Ending iterator over laned accesses
void clearLanedAccessMap(void) { lanedMap.clear(); } ///< Clear records from the laned access list void clearLanedAccessMap(void) { lanedMap.clear(); } ///< Clear records from the laned access list

View file

@ -85,6 +85,9 @@ Varnode *Funcdata::newUnique(int4 s,Datatype *ct)
ct = glb->types->getBase(s,TYPE_UNKNOWN); ct = glb->types->getBase(s,TYPE_UNKNOWN);
Varnode *vn = vbank.createUnique(s,ct); Varnode *vn = vbank.createUnique(s,ct);
assignHigh(vn); assignHigh(vn);
if (s >= minLanedSize)
checkForLanedRegister(s, vn->getAddr());
// No chance of matching localmap // No chance of matching localmap
return vn; return vn;
} }
@ -104,6 +107,8 @@ Varnode *Funcdata::newVarnodeOut(int4 s,const Address &m,PcodeOp *op)
op->setOutput(vn); op->setOutput(vn);
assignHigh(vn); assignHigh(vn);
if (s >= minLanedSize)
checkForLanedRegister(s,m);
uint4 vflags = 0; uint4 vflags = 0;
SymbolEntry *entry = localmap->queryProperties(m,s,op->getAddr(),vflags); SymbolEntry *entry = localmap->queryProperties(m,s,op->getAddr(),vflags);
if (entry != (SymbolEntry *)0) if (entry != (SymbolEntry *)0)
@ -126,6 +131,8 @@ Varnode *Funcdata::newUniqueOut(int4 s,PcodeOp *op)
Varnode *vn = vbank.createDefUnique(s,ct,op); Varnode *vn = vbank.createDefUnique(s,ct,op);
op->setOutput(vn); op->setOutput(vn);
assignHigh(vn); assignHigh(vn);
if (s >= minLanedSize)
checkForLanedRegister(s, vn->getAddr());
// No chance of matching localmap // No chance of matching localmap
return vn; return vn;
} }
@ -147,6 +154,8 @@ Varnode *Funcdata::newVarnode(int4 s,const Address &m,Datatype *ct)
vn = vbank.create(s,m,ct); vn = vbank.create(s,m,ct);
assignHigh(vn); assignHigh(vn);
if (s >= minLanedSize)
checkForLanedRegister(s,m);
uint4 vflags=0; uint4 vflags=0;
SymbolEntry *entry = localmap->queryProperties(vn->getAddr(),vn->getSize(),Address(),vflags); SymbolEntry *entry = localmap->queryProperties(vn->getAddr(),vn->getSize(),Address(),vflags);
if (entry != (SymbolEntry *)0) // Let entry try to force type if (entry != (SymbolEntry *)0) // Let entry try to force type
@ -280,19 +289,21 @@ void Funcdata::destroyVarnode(Varnode *vn)
vbank.destroy(vn); vbank.destroy(vn);
} }
/// Record the given Varnode as a potential laned register access. /// Check if the given storage range is a potential laned register.
/// The address and size of the Varnode is recorded, anticipating that new /// If so, record the storage with the matching laned register record.
/// Varnodes at the same storage location may be created /// \param s is the size of the storage range in bytes
/// \param vn is the given Varnode to mark /// \param addr is the starting address of the storage range
/// \param lanedReg is the laned register record to associate with the Varnode void Funcdata::checkForLanedRegister(int4 size,const Address &addr)
void Funcdata::markLanedVarnode(Varnode *vn,const LanedRegister *lanedReg)
{ {
const LanedRegister *lanedRegister = glb->getLanedRegister(addr,size);
if (lanedRegister == (const LanedRegister *)0)
return;
VarnodeData storage; VarnodeData storage;
storage.space = vn->getSpace(); storage.space = addr.getSpace();
storage.offset = vn->getOffset(); storage.offset = addr.getOffset();
storage.size = vn->getSize(); storage.size = size;
lanedMap[storage] = lanedReg; lanedMap[storage] = lanedRegister;
} }
/// Look up the Symbol visible in \b this function's Scope and return the HighVariable /// Look up the Symbol visible in \b this function's Scope and return the HighVariable