diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc index 4f5fc9fee8..75114edf14 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc @@ -607,6 +607,7 @@ int4 ActionLaneDivide::apply(Funcdata &data) if (allStorageProcessed) break; } data.clearLanedAccessMap(); + data.setLanedRegGenerated(); return 0; } @@ -1209,31 +1210,11 @@ int4 ActionDeindirect::apply(Funcdata &data) 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) { Architecture *glb = data.getArch(); 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; Varnode *vn; @@ -1242,8 +1223,6 @@ int4 ActionVarnodeProps::apply(Funcdata &data) vn = *iter++; // Advance iterator in case vn is deleted if (vn->isAnnotation()) continue; int4 vnSize = vn->getSize(); - if (vnSize >= minLanedSize) - markLanedVarnode(data, vn); if (vn->hasActionProperty()) { if (cachereadonly&&vn->isReadOnly()) { if (data.fillinReadOnly(vn)) // Try to replace vn with its lookup in LoadImage diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh index 46dc862ead..fded0da14b 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh @@ -211,9 +211,7 @@ public: /// - Read-only Varnodes are converted to the underlying constant /// - Volatile Varnodes are converted read/write functions /// - Varnodes whose values are not consumed are replaced with constant 0 Varnodes -/// - Large Varnodes are flagged for lane analysis class ActionVarnodeProps : public Action { - void markLanedVarnode(Funcdata &data,Varnode *vn); ///< Mark possible laned register storage public: ActionVarnodeProps(const string &g) : Action(0,"varnodeprops",g) {} ///< Constructor virtual Action *clone(const ActionGroupList &grouplist) const { diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc index f23b39b572..18d1e43e2d 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc @@ -36,6 +36,7 @@ Funcdata::Funcdata(const string &nm,Scope *scope,const Address &addr,int4 sz) high_level_index = 0; cast_phase_index = 0; glb = scope->getArch(); + minLanedSize = glb->getMinimumLanedRegisterSize(); name = nm; size = sz; @@ -69,6 +70,7 @@ void Funcdata::clear(void) clean_up_index = 0; high_level_index = 0; cast_phase_index = 0; + minLanedSize = glb->getMinimumLanedRegisterSize(); localmap->clearUnlocked(); // Clear non-permanent stuff localmap->resetLocalWindow(); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh index e174e5c68f..37c802f9c8 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh @@ -56,13 +56,13 @@ class Funcdata { restart_pending = 0x200, ///< Analysis must be restarted (because of new override info) unimplemented_present = 0x400, ///< Set if function contains unimplemented instructions baddata_present = 0x800, ///< Set if function flowed into bad data - double_precis_on = 0x1000, ///< Set if we are performing double precision recovery - big_varnodes_generated = 0x2000 ///< Set when search for laned registers is complete + double_precis_on = 0x1000 ///< Set if we are performing double precision recovery }; uint4 flags; ///< Boolean properties associated with \b this function 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 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 string name; ///< Name of function 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 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 - bool isLanedRegComplete(void) const { return ((flags&big_varnodes_generated)!=0); } ///< Have potential laned registers been generated - void setLanedRegGenerated(void) { flags |= big_varnodes_generated; } ///< Mark that laned registers have been collected + void setLanedRegGenerated(void) { minLanedSize = 1000000; } ///< Mark that laned registers have been collected /// \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 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::const_iterator beginLaneAccess(void) const { return lanedMap.begin(); } ///< Beginning iterator over laned accesses map::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 diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc index 6b1c863585..dd8385a011 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc @@ -85,6 +85,9 @@ Varnode *Funcdata::newUnique(int4 s,Datatype *ct) ct = glb->types->getBase(s,TYPE_UNKNOWN); Varnode *vn = vbank.createUnique(s,ct); assignHigh(vn); + if (s >= minLanedSize) + checkForLanedRegister(s, vn->getAddr()); + // No chance of matching localmap return vn; } @@ -104,6 +107,8 @@ Varnode *Funcdata::newVarnodeOut(int4 s,const Address &m,PcodeOp *op) op->setOutput(vn); assignHigh(vn); + if (s >= minLanedSize) + checkForLanedRegister(s,m); uint4 vflags = 0; SymbolEntry *entry = localmap->queryProperties(m,s,op->getAddr(),vflags); if (entry != (SymbolEntry *)0) @@ -126,6 +131,8 @@ Varnode *Funcdata::newUniqueOut(int4 s,PcodeOp *op) Varnode *vn = vbank.createDefUnique(s,ct,op); op->setOutput(vn); assignHigh(vn); + if (s >= minLanedSize) + checkForLanedRegister(s, vn->getAddr()); // No chance of matching localmap return vn; } @@ -147,6 +154,8 @@ Varnode *Funcdata::newVarnode(int4 s,const Address &m,Datatype *ct) vn = vbank.create(s,m,ct); assignHigh(vn); + if (s >= minLanedSize) + checkForLanedRegister(s,m); uint4 vflags=0; SymbolEntry *entry = localmap->queryProperties(vn->getAddr(),vn->getSize(),Address(),vflags); if (entry != (SymbolEntry *)0) // Let entry try to force type @@ -280,19 +289,21 @@ void Funcdata::destroyVarnode(Varnode *vn) vbank.destroy(vn); } -/// Record the given Varnode as a potential laned register access. -/// The address and size of the Varnode is recorded, anticipating that new -/// Varnodes at the same storage location may be created -/// \param vn is the given Varnode to mark -/// \param lanedReg is the laned register record to associate with the Varnode -void Funcdata::markLanedVarnode(Varnode *vn,const LanedRegister *lanedReg) +/// Check if the given storage range is a potential laned register. +/// If so, record the storage with the matching laned register record. +/// \param s is the size of the storage range in bytes +/// \param addr is the starting address of the storage range +void Funcdata::checkForLanedRegister(int4 size,const Address &addr) { + const LanedRegister *lanedRegister = glb->getLanedRegister(addr,size); + if (lanedRegister == (const LanedRegister *)0) + return; VarnodeData storage; - storage.space = vn->getSpace(); - storage.offset = vn->getOffset(); - storage.size = vn->getSize(); - lanedMap[storage] = lanedReg; + storage.space = addr.getSpace(); + storage.offset = addr.getOffset(); + storage.size = size; + lanedMap[storage] = lanedRegister; } /// Look up the Symbol visible in \b this function's Scope and return the HighVariable