mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
finalizing HighVariable from symbols
This commit is contained in:
parent
cbbfc9ca18
commit
cfc1177ac1
5 changed files with 30 additions and 14 deletions
|
@ -1874,7 +1874,7 @@ int4 ActionRestructureVarnode::apply(Funcdata &data)
|
||||||
bool aliasyes = data.isJumptableRecoveryOn() ? false : (numpass != 0);
|
bool aliasyes = data.isJumptableRecoveryOn() ? false : (numpass != 0);
|
||||||
l1->restructureVarnode(aliasyes);
|
l1->restructureVarnode(aliasyes);
|
||||||
// Note the alias calculation, may not be very good on the first pass
|
// Note the alias calculation, may not be very good on the first pass
|
||||||
if (data.updateFlags(l1,false))
|
if (data.syncVarnodesWithSymbols(l1,false))
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
numpass += 1;
|
numpass += 1;
|
||||||
|
@ -1899,7 +1899,7 @@ int4 ActionRestructureHigh::apply(Funcdata &data)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
l1->restructureHigh();
|
l1->restructureHigh();
|
||||||
if (data.updateFlags(l1,true))
|
if (data.syncVarnodesWithSymbols(l1,true))
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
#ifdef OPACTION_DEBUG
|
#ifdef OPACTION_DEBUG
|
||||||
|
|
|
@ -84,7 +84,7 @@ class Funcdata {
|
||||||
// Low level Varnode functions
|
// Low level Varnode functions
|
||||||
void setVarnodeProperties(Varnode *vn) const; ///< Look-up boolean properties and data-type information
|
void setVarnodeProperties(Varnode *vn) const; ///< Look-up boolean properties and data-type information
|
||||||
HighVariable *assignHigh(Varnode *vn); ///< Assign a new HighVariable to a Varnode
|
HighVariable *assignHigh(Varnode *vn); ///< Assign a new HighVariable to a Varnode
|
||||||
bool updateFlags(VarnodeLocSet::const_iterator &iter,uint4 flags,Datatype *ct);
|
bool syncVarnodesWithSymbol(VarnodeLocSet::const_iterator &iter,uint4 flags,Datatype *ct);
|
||||||
bool descend2Undef(Varnode *vn); ///< Transform all reads of the given Varnode to a special \b undefined constant
|
bool descend2Undef(Varnode *vn); ///< Transform all reads of the given Varnode to a special \b undefined constant
|
||||||
|
|
||||||
void splitUses(Varnode *vn); ///< Make all reads of the given Varnode unique
|
void splitUses(Varnode *vn); ///< Make all reads of the given Varnode unique
|
||||||
|
@ -351,7 +351,7 @@ public:
|
||||||
bool checkCallDoubleUse(const PcodeOp *opmatch,const PcodeOp *op,const Varnode *vn,const ParamTrial &trial) const;
|
bool checkCallDoubleUse(const PcodeOp *opmatch,const PcodeOp *op,const Varnode *vn,const ParamTrial &trial) const;
|
||||||
bool onlyOpUse(const Varnode *invn,const PcodeOp *opmatch,const ParamTrial &trial) const;
|
bool onlyOpUse(const Varnode *invn,const PcodeOp *opmatch,const ParamTrial &trial) const;
|
||||||
bool ancestorOpUse(int4 maxlevel,const Varnode *invn,const PcodeOp *op,ParamTrial &trial) const;
|
bool ancestorOpUse(int4 maxlevel,const Varnode *invn,const PcodeOp *op,ParamTrial &trial) const;
|
||||||
bool updateFlags(const ScopeLocal *lm,bool typesyes);
|
bool syncVarnodesWithSymbols(const ScopeLocal *lm,bool typesyes);
|
||||||
void splitVarnode(Varnode *vn,int4 lowsize,Varnode *&vnlo,Varnode *& vnhi);
|
void splitVarnode(Varnode *vn,int4 lowsize,Varnode *&vnlo,Varnode *& vnhi);
|
||||||
bool fillinReadOnly(Varnode *vn); ///< Replace the given Varnode with its (constant) value in the load image
|
bool fillinReadOnly(Varnode *vn); ///< Replace the given Varnode with its (constant) value in the load image
|
||||||
bool replaceVolatile(Varnode *vn); ///< Replace accesses of the given Varnode with \e volatile operations
|
bool replaceVolatile(Varnode *vn); ///< Replace accesses of the given Varnode with \e volatile operations
|
||||||
|
|
|
@ -803,15 +803,16 @@ void Funcdata::calcNZMask(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Update Varnode boolean properties based on (new) Symbol information
|
/// \brief Update Varnode properties based on (new) Symbol information
|
||||||
///
|
///
|
||||||
/// Boolean properties \b addrtied, \b addrforce, \b auto_live, and \b nolocalalias
|
/// Boolean properties \b addrtied, \b addrforce, \b auto_live, and \b nolocalalias
|
||||||
/// for Varnodes are updated based on new Symbol information they map to.
|
/// for Varnodes are updated based on new Symbol information they map to.
|
||||||
/// The caller can elect to update data-type information as well.
|
/// The caller can elect to update data-type information as well, where Varnodes
|
||||||
|
/// and their associated HighVariables have their data-type finalized based symbols.
|
||||||
/// \param lm is the Symbol scope within which to search for mapped Varnodes
|
/// \param lm is the Symbol scope within which to search for mapped Varnodes
|
||||||
/// \param typesyes is \b true if the caller wants to update data-types
|
/// \param typesyes is \b true if the caller wants to update data-types
|
||||||
/// \return \b true if any Varnode was updated
|
/// \return \b true if any Varnode was updated
|
||||||
bool Funcdata::updateFlags(const ScopeLocal *lm,bool typesyes)
|
bool Funcdata::syncVarnodesWithSymbols(const ScopeLocal *lm,bool typesyes)
|
||||||
|
|
||||||
{
|
{
|
||||||
bool updateoccurred = false;
|
bool updateoccurred = false;
|
||||||
|
@ -859,13 +860,13 @@ bool Funcdata::updateFlags(const ScopeLocal *lm,bool typesyes)
|
||||||
else
|
else
|
||||||
flags = 0;
|
flags = 0;
|
||||||
}
|
}
|
||||||
if (updateFlags(iter,flags,ct))
|
if (syncVarnodesWithSymbol(iter,flags,ct))
|
||||||
updateoccurred = true;
|
updateoccurred = true;
|
||||||
}
|
}
|
||||||
return updateoccurred;
|
return updateoccurred;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Update boolean properties (and the data-type) for a set of Varnodes
|
/// \brief Update properties (and the data-type) for a set of Varnodes associated with one Symbol
|
||||||
///
|
///
|
||||||
/// The set of Varnodes with the same size and address all have their boolean properties
|
/// The set of Varnodes with the same size and address all have their boolean properties
|
||||||
/// updated to the given values. The set is specified by providing an iterator reference
|
/// updated to the given values. The set is specified by providing an iterator reference
|
||||||
|
@ -882,7 +883,7 @@ bool Funcdata::updateFlags(const ScopeLocal *lm,bool typesyes)
|
||||||
/// \param flags holds the new set of boolean properties
|
/// \param flags holds the new set of boolean properties
|
||||||
/// \param ct is the given data-type to set (or NULL)
|
/// \param ct is the given data-type to set (or NULL)
|
||||||
/// \return \b true if at least one Varnode was modified
|
/// \return \b true if at least one Varnode was modified
|
||||||
bool Funcdata::updateFlags(VarnodeLocSet::const_iterator &iter,uint4 flags,Datatype *ct)
|
bool Funcdata::syncVarnodesWithSymbol(VarnodeLocSet::const_iterator &iter,uint4 flags,Datatype *ct)
|
||||||
|
|
||||||
{
|
{
|
||||||
VarnodeLocSet::const_iterator enditer;
|
VarnodeLocSet::const_iterator enditer;
|
||||||
|
@ -914,9 +915,11 @@ bool Funcdata::updateFlags(VarnodeLocSet::const_iterator &iter,uint4 flags,Datat
|
||||||
vn->setFlags(flags);
|
vn->setFlags(flags);
|
||||||
vn->clearFlags((~flags)&mask);
|
vn->clearFlags((~flags)&mask);
|
||||||
}
|
}
|
||||||
if (ct != (Datatype *)0)
|
if (ct != (Datatype *)0) {
|
||||||
if (vn->updateType(ct,false,false))
|
if (vn->updateType(ct,false,false))
|
||||||
updateoccurred = true;
|
updateoccurred = true;
|
||||||
|
vn->getHigh()->finalizeDatatype(ct); // Permanently set the data-type on the HighVariable
|
||||||
|
}
|
||||||
} while(iter != enditer);
|
} while(iter != enditer);
|
||||||
return updateoccurred;
|
return updateoccurred;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,8 @@ void HighVariable::updateType(void) const
|
||||||
Varnode *vn;
|
Varnode *vn;
|
||||||
|
|
||||||
if ((highflags&HighVariable::typedirty)==0) return; // Type is up to date
|
if ((highflags&HighVariable::typedirty)==0) return; // Type is up to date
|
||||||
|
highflags &= ~HighVariable::typedirty; // Mark type as clean
|
||||||
|
if ((highflags & type_finalized)!=0) return; // Type has been finalized
|
||||||
vn = getTypeRepresentative();
|
vn = getTypeRepresentative();
|
||||||
|
|
||||||
type = vn->getType();
|
type = vn->getType();
|
||||||
|
@ -106,7 +108,6 @@ void HighVariable::updateType(void) const
|
||||||
flags &= ~Varnode::typelock;
|
flags &= ~Varnode::typelock;
|
||||||
if (vn->isTypeLock())
|
if (vn->isTypeLock())
|
||||||
flags |= Varnode::typelock;
|
flags |= Varnode::typelock;
|
||||||
highflags &= ~HighVariable::typedirty; // Mark type as clean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare two Varnode objects based just on their storage address
|
/// Compare two Varnode objects based just on their storage address
|
||||||
|
@ -198,6 +199,16 @@ void HighVariable::remove(Varnode *vn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The data-type its dirtying mechanism is disabled. The data-type will not change, unless
|
||||||
|
/// this method is called again.
|
||||||
|
/// \param tp is the data-type to set
|
||||||
|
void HighVariable::finalizeDatatype(Datatype *tp)
|
||||||
|
|
||||||
|
{
|
||||||
|
type = tp;
|
||||||
|
highflags |= type_finalized;
|
||||||
|
}
|
||||||
|
|
||||||
/// The lists of members are merged and the other HighVariable is deleted.
|
/// The lists of members are merged and the other HighVariable is deleted.
|
||||||
/// \param tv2 is the other HighVariable to merge into \b this
|
/// \param tv2 is the other HighVariable to merge into \b this
|
||||||
/// \param isspeculative is \b true to keep the new members in separate \e merge classes
|
/// \param isspeculative is \b true to keep the new members in separate \e merge classes
|
||||||
|
|
|
@ -47,7 +47,8 @@ public:
|
||||||
typedirty = 2, ///< The data-type for the HighVariable is dirty
|
typedirty = 2, ///< The data-type for the HighVariable is dirty
|
||||||
coverdirty = 4, ///< The cover for the HighVariable is dirty
|
coverdirty = 4, ///< The cover for the HighVariable is dirty
|
||||||
copy_in1 = 8, ///< There exists at least 1 COPY into \b this HighVariable from other HighVariables
|
copy_in1 = 8, ///< There exists at least 1 COPY into \b this HighVariable from other HighVariables
|
||||||
copy_in2 = 16 ///< There exists at least 2 COPYs into \b this HighVariable from other HighVariables
|
copy_in2 = 16, ///< There exists at least 2 COPYs into \b this HighVariable from other HighVariables
|
||||||
|
type_finalized = 32 ///< Set if a final data-type is locked in and dirtying is disabled
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
friend class Merge;
|
friend class Merge;
|
||||||
|
@ -68,6 +69,7 @@ private:
|
||||||
void clearCopyIns(void) const { highflags &= ~(copy_in1 | copy_in2); } ///< Clear marks indicating COPYs into \b this
|
void clearCopyIns(void) const { highflags &= ~(copy_in1 | copy_in2); } ///< Clear marks indicating COPYs into \b this
|
||||||
bool hasCopyIn1(void) const { return ((highflags©_in1)!=0); } ///< Is there at least one COPY into \b this
|
bool hasCopyIn1(void) const { return ((highflags©_in1)!=0); } ///< Is there at least one COPY into \b this
|
||||||
bool hasCopyIn2(void) const { return ((highflags©_in2)!=0); } ///< Is there at least two COPYs into \b this
|
bool hasCopyIn2(void) const { return ((highflags©_in2)!=0); } ///< Is there at least two COPYs into \b this
|
||||||
|
void merge(HighVariable *tv2,bool isspeculative); ///< Merge another HighVariable into \b this
|
||||||
public:
|
public:
|
||||||
HighVariable(Varnode *vn); ///< Construct a HighVariable with a single member Varnode
|
HighVariable(Varnode *vn); ///< Construct a HighVariable with a single member Varnode
|
||||||
Datatype *getType(void) const { updateType(); return type; } ///< Get the data-type
|
Datatype *getType(void) const { updateType(); return type; } ///< Get the data-type
|
||||||
|
@ -90,6 +92,7 @@ public:
|
||||||
void coverDirty(void) const { highflags |= HighVariable::coverdirty; } ///< Mark the cover as \e dirty
|
void coverDirty(void) const { highflags |= HighVariable::coverdirty; } ///< Mark the cover as \e dirty
|
||||||
void typeDirty(void) const { highflags |= HighVariable::typedirty; } ///< Mark the data-type as \e dirty
|
void typeDirty(void) const { highflags |= HighVariable::typedirty; } ///< Mark the data-type as \e dirty
|
||||||
void remove(Varnode *vn); ///< Remove a member Varnode from \b this
|
void remove(Varnode *vn); ///< Remove a member Varnode from \b this
|
||||||
|
void finalizeDatatype(Datatype *tp); ///< Set a final datatype for \b this variable
|
||||||
|
|
||||||
/// \brief Print details of the cover for \b this (for debug purposes)
|
/// \brief Print details of the cover for \b this (for debug purposes)
|
||||||
///
|
///
|
||||||
|
@ -102,7 +105,6 @@ public:
|
||||||
Varnode *getInputVarnode(void) const; ///< Find (the) input member Varnode
|
Varnode *getInputVarnode(void) const; ///< Find (the) input member Varnode
|
||||||
Varnode *getTypeRepresentative(void) const; ///< Get a member Varnode with the strongest data-type
|
Varnode *getTypeRepresentative(void) const; ///< Get a member Varnode with the strongest data-type
|
||||||
Varnode *getNameRepresentative(void) const; ///< Get a member Varnode that dictates the naming of \b this HighVariable
|
Varnode *getNameRepresentative(void) const; ///< Get a member Varnode that dictates the naming of \b this HighVariable
|
||||||
void merge(HighVariable *tv2,bool isspeculative); ///< Merge another HighVariable into \b this
|
|
||||||
bool isMapped(void) const { updateFlags(); return ((flags&Varnode::mapped)!=0); } ///< Return \b true if \b this is mapped
|
bool isMapped(void) const { updateFlags(); return ((flags&Varnode::mapped)!=0); } ///< Return \b true if \b this is mapped
|
||||||
bool isPersist(void) const { updateFlags(); return ((flags&Varnode::persist)!=0); } ///< Return \b true if \b this is a global variable
|
bool isPersist(void) const { updateFlags(); return ((flags&Varnode::persist)!=0); } ///< Return \b true if \b this is a global variable
|
||||||
bool isAddrTied(void) const { updateFlags(); return ((flags&Varnode::addrtied)!=0); } ///< Return \b true if \b this is \e address \e ties
|
bool isAddrTied(void) const { updateFlags(); return ((flags&Varnode::addrtied)!=0); } ///< Return \b true if \b this is \e address \e ties
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue