mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
MapState reconcileDatatypes
This commit is contained in:
parent
40d840085f
commit
5fbbef38ac
2 changed files with 61 additions and 16 deletions
|
@ -273,23 +273,26 @@ bool RangeHint::merge(RangeHint *b,AddrSpace *space,TypeFactory *typeFactory)
|
||||||
return overlapProblems;
|
return overlapProblems;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Order the two ranges by the signed version of their offset, then by size,
|
/// Compare (signed) offset, size, RangeType, type lock, and high index, in that order.
|
||||||
/// then by data-type
|
/// Datatype is \e not compared.
|
||||||
/// \param a is the first range to compare
|
/// \param op2 is the other RangeHint to compare with \b this
|
||||||
/// \param b is the second range
|
/// \return -1, 0, or 1 depending on if \b this comes before, is equal to, or comes after
|
||||||
/// \return \b true if the first range is ordered before the second
|
int4 RangeHint::compare(const RangeHint &op2) const
|
||||||
bool RangeHint::compareRanges(const RangeHint *a,const RangeHint *b)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
if (a->sstart != b->sstart)
|
if (sstart != op2.sstart)
|
||||||
return (a->sstart < b->sstart);
|
return (sstart < op2.sstart) ? -1 : 1;
|
||||||
if (a->size != b->size)
|
if (size != op2.size)
|
||||||
return (a->size < b->size); // Small sizes come first
|
return (size < op2.size) ? -1 : 1; // Small sizes come first
|
||||||
type_metatype ameta = a->type->getMetatype();
|
if (rangeType != op2.rangeType)
|
||||||
type_metatype bmeta = b->type->getMetatype();
|
return (rangeType < op2.rangeType) ? -1 : 1;
|
||||||
if (ameta != bmeta)
|
uint4 thisLock = flags & Varnode::typelock;
|
||||||
return (ameta < bmeta); // Order more specific types first
|
uint4 op2Lock = op2.flags & Varnode::typelock;
|
||||||
return false; //comp(x, x) must be false for strict weak ordering
|
if (thisLock != op2Lock)
|
||||||
|
return (thisLock < op2Lock) ? -1 : 1;
|
||||||
|
if (highind != op2.highind)
|
||||||
|
return (highind < op2.highind) ? -1 : 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param spc is the (stack) address space associated with this function's local variables
|
/// \param spc is the (stack) address space associated with this function's local variables
|
||||||
|
@ -799,6 +802,44 @@ void MapState::addRange(uintb st,Datatype *ct,uint4 fl,RangeHint::RangeType rt,i
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assuming a sorted list, from among a sequence of RangeHints with the same start and size, select
|
||||||
|
/// the most specific data-type. Set all elements to use this data-type, and eliminate duplicates.
|
||||||
|
void MapState::reconcileDatatypes(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
vector<RangeHint *> newList;
|
||||||
|
newList.reserve(maplist.size());
|
||||||
|
int4 startPos = 0;
|
||||||
|
RangeHint *startHint = maplist[0];
|
||||||
|
Datatype *startDatatype = startHint->type;
|
||||||
|
newList.push_back(startHint);
|
||||||
|
int4 curPos = 1;
|
||||||
|
while(curPos < maplist.size()) {
|
||||||
|
RangeHint *curHint = maplist[curPos++];
|
||||||
|
if (curHint->start == startHint->start && curHint->size == startHint->size) {
|
||||||
|
Datatype *curDatatype = curHint->type;
|
||||||
|
if (curDatatype->typeOrder(*startDatatype) < 0) // Take the most specific variant of data-type
|
||||||
|
startDatatype = curDatatype;
|
||||||
|
if (curHint->compare(*startHint) != 0)
|
||||||
|
newList.push_back(curHint); // Keep the current hint if it is otherwise different
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while(startPos < newList.size()) {
|
||||||
|
newList[startPos]->type = startDatatype;
|
||||||
|
startPos += 1;
|
||||||
|
}
|
||||||
|
startHint = curHint;
|
||||||
|
startDatatype = startHint->type;
|
||||||
|
newList.push_back(startHint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(startPos < newList.size()) {
|
||||||
|
newList[startPos]->type = startDatatype;
|
||||||
|
startPos += 1;
|
||||||
|
}
|
||||||
|
maplist.swap(newList);
|
||||||
|
}
|
||||||
|
|
||||||
/// The given LoadGuard, which may be a LOAD or STORE is converted into an appropriate
|
/// The given LoadGuard, which may be a LOAD or STORE is converted into an appropriate
|
||||||
/// RangeHint, attempting to make use of any data-type or index information.
|
/// RangeHint, attempting to make use of any data-type or index information.
|
||||||
/// \param guard is the given LoadGuard
|
/// \param guard is the given LoadGuard
|
||||||
|
@ -879,6 +920,7 @@ bool MapState::initialize(void)
|
||||||
maplist.push_back(range);
|
maplist.push_back(range);
|
||||||
|
|
||||||
stable_sort(maplist.begin(),maplist.end(),RangeHint::compareRanges);
|
stable_sort(maplist.begin(),maplist.end(),RangeHint::compareRanges);
|
||||||
|
reconcileDatatypes();
|
||||||
iter = maplist.begin();
|
iter = maplist.begin();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ public:
|
||||||
/// where the data-type starts, what data-type it might be, and how far it extends
|
/// where the data-type starts, what data-type it might be, and how far it extends
|
||||||
/// from the start point (possibly as an array).
|
/// from the start point (possibly as an array).
|
||||||
class RangeHint {
|
class RangeHint {
|
||||||
|
friend class MapState;
|
||||||
friend class ScopeLocal;
|
friend class ScopeLocal;
|
||||||
public:
|
public:
|
||||||
/// \brief The basic categorization of the range
|
/// \brief The basic categorization of the range
|
||||||
|
@ -91,7 +92,8 @@ public:
|
||||||
bool preferred(const RangeHint *b,bool reconcile) const;
|
bool preferred(const RangeHint *b,bool reconcile) const;
|
||||||
bool absorb(RangeHint *b); ///< Try to absorb the other RangeHint into \b this
|
bool absorb(RangeHint *b); ///< Try to absorb the other RangeHint into \b this
|
||||||
bool merge(RangeHint *b,AddrSpace *space,TypeFactory *typeFactory); ///< Try to form the union of \b this with another RangeHint
|
bool merge(RangeHint *b,AddrSpace *space,TypeFactory *typeFactory); ///< Try to form the union of \b this with another RangeHint
|
||||||
static bool compareRanges(const RangeHint *a,const RangeHint *b); ///< Compare to RangeHint pointers
|
int4 compare(const RangeHint &op2) const; ///< Order \b this with another RangeHint
|
||||||
|
static bool compareRanges(const RangeHint *a,const RangeHint *b) { return (a->compare(*b) < 0); } ///< Compare two RangeHint pointers
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProtoModel;
|
class ProtoModel;
|
||||||
|
@ -148,6 +150,7 @@ class MapState {
|
||||||
AliasChecker checker; ///< A collection of pointer Varnodes into our address space
|
AliasChecker checker; ///< A collection of pointer Varnodes into our address space
|
||||||
void addGuard(const LoadGuard &guard,OpCode opc,TypeFactory *typeFactory); ///< Add LoadGuard record as a hint to the collection
|
void addGuard(const LoadGuard &guard,OpCode opc,TypeFactory *typeFactory); ///< Add LoadGuard record as a hint to the collection
|
||||||
void addRange(uintb st,Datatype *ct,uint4 fl,RangeHint::RangeType rt,int4 hi); ///< Add a hint to the collection
|
void addRange(uintb st,Datatype *ct,uint4 fl,RangeHint::RangeType rt,int4 hi); ///< Add a hint to the collection
|
||||||
|
void reconcileDatatypes(void); ///< Decide on data-type for RangeHints at the same address
|
||||||
public:
|
public:
|
||||||
#ifdef OPACTION_DEBUG
|
#ifdef OPACTION_DEBUG
|
||||||
mutable bool debugon;
|
mutable bool debugon;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue