Refactor ParamEntry look-up allowing "contained by" discovery

This commit is contained in:
caheckman 2019-07-08 13:54:03 -04:00
parent ef12c20829
commit 12d3da029b
13 changed files with 690 additions and 286 deletions

View file

@ -20,6 +20,7 @@
#define __CPUI_FSPEC__
#include "op.hh"
#include "rangemap.hh"
class JoinRecord;
@ -85,6 +86,7 @@ public:
bool isExclusion(void) const { return (alignment==0); } ///< Return \b true if this holds a single parameter exclusively
bool isReverseStack(void) const { return ((flags & reverse_stack)!=0); } ///< Return \b true if parameters are allocated in reverse order
bool contains(const ParamEntry &op2) const; ///< Does \b this contain the indicated entry.
bool containedBy(const Address &addr,int4 sz) const; ///< Is this entry contained by the given range
int4 justifiedContain(const Address &addr,int4 sz) const; ///< Calculate endian aware containment
bool getContainer(const Address &addr,int4 sz,VarnodeData &res) const;
OpCode assumedExtension(const Address &addr,int4 sz,VarnodeData &res) const;
@ -93,11 +95,51 @@ public:
uintb getBase(void) const { return addressbase; } ///< Get the starting offset of \b this entry
Address getAddrBySlot(int4 &slot,int4 sz) const;
void restoreXml(const Element *el,const AddrSpaceManager *manage,bool normalstack);
void extraChecks(vector<ParamEntry> &entry);
void extraChecks(list<ParamEntry> &entry);
bool isParamCheckHigh(void) const { return ((flags & extracheck_high)!=0); } ///< Return \b true if there is a high overlap
bool isParamCheckLow(void) const { return ((flags & extracheck_low)!=0); } ///< Return \b true if there is a low overlap
};
/// \brief Class for storing ParamEntry objects in an interval range (rangemap)
class ParamEntryRange {
uintb first; ///< Starting offset of the ParamEntry's range
uintb last; ///< Ending offset of the ParamEntry's range
int4 position; ///< Position of the ParamEntry within the entire prototype list
ParamEntry *entry; ///< Pointer to the actual ParamEntry
/// \brief Helper class for initializing ParamEntryRange in a range map
class InitData {
friend class ParamEntryRange;
int4 position; ///< Position (within the full list) being assigned to the ParamEntryRange
ParamEntry *entry; ///< Underlying ParamEntry being assigned to the ParamEntryRange
public:
InitData(int4 pos,ParamEntry *e) { position = pos; entry = e; } ///< Constructor
};
/// \brief Helper class for subsorting on position
class SubsortPosition {
int4 position; ///< The position value
public:
SubsortPosition(void) {} ///< Constructor for use with rangemap
SubsortPosition(int4 pos) { position = pos; } ///< Construct given position
SubsortPosition(bool val) { position = val ? 1000000 : 0; } ///< Constructor minimal/maximal subsort
bool operator<(const SubsortPosition &op2) { return position < op2.position; } ///< Compare operation
};
public:
typedef uintb linetype; ///< The linear element for a rangemap
typedef SubsortPosition subsorttype; ///< The sub-sort object for a rangemap
typedef InitData inittype; ///< Initialization data for a ScopeMapper
ParamEntryRange(void) {} ///< Constructor for use with rangemap
void initialize(const inittype &data,uintb f,uintb l) {
first = f; last = l; position = data.position; entry = data.entry; } ///< Initialize the range
uintb getFirst(void) const { return first; } ///< Get the first address in the range
uintb getLast(void) const { return last; } ///< Get the last address in the range
subsorttype getSubsort(void) const { return SubsortPosition(position); } ///< Get the sub-subsort object
ParamEntry *getParamEntry(void) const { return entry; } ///< Get pointer to actual ParamEntry
};
typedef rangemap<ParamEntryRange> ParamEntryResolver; ///< A map from offset to ParamEntry
/// \brief A register or memory register that may be used to pass a parameter or return value
///
/// The parameter recovery utilities (see ParamActive) use this to denote a putative
@ -344,6 +386,18 @@ public:
/// \return \b true if the storage location can be split
virtual bool checkSplit(const Address &loc,int4 size,int4 splitpoint) const=0;
/// \brief Characterize whether the given range overlaps parameter storage
///
/// Does the range naturally fit inside a potential parameter entry from this list or does
/// it contain a parameter entry. Return one of three values indicating this characterization:
/// - 0 means there is no intersection between the range and any parameter in this list
/// - 1 means that at least one parameter contains the range in a properly justified manner
/// - 2 means no parameter contains the range, but the range contains at least one ParamEntry
/// \param loc is the starting address of the given range
/// \param size is the number of bytes in the given range
/// \return the characterization code
virtual int4 characterizeAsParam(const Address &loc,int4 size) const=0;
/// \brief Does the given storage location make sense as a parameter
///
/// Within \b this model, decide if the storage location can be considered a parameter.
@ -363,6 +417,14 @@ public:
/// \return \b true if the location can be a parameter
virtual bool possibleParamWithSlot(const Address &loc,int4 size,int4 &slot,int4 &slotsize) const=0;
/// \brief Pass-back the biggest parameter contained within the given range
///
/// \param loc is the starting address of the given range
/// \param size is the number of bytes in the range
/// \param res will hold the parameter storage description being passed back
/// \return \b true if there is at least one parameter contained in the range
virtual bool getBiggestContainedParam(const Address &loc,int4 size,VarnodeData &res) const=0;
/// \brief Check if the given storage location looks like an \e unjustified parameter
///
/// The storage for a value may be contained in a normal parameter location but be
@ -433,9 +495,10 @@ protected:
int4 pointermax; ///< If non-zero, maximum size of a data-type before converting to a pointer
bool thisbeforeret; ///< Does a \b this parameter come before a hidden return parameter
int4 nonfloatgroup; ///< Group of first entry which is not marked float
vector<ParamEntry> entry; ///< The ordered list of parameter entries
list<ParamEntry> entry; ///< The ordered list of parameter entries
vector<ParamEntryResolver *> resolverMap; ///< Map from space id to resolver
AddrSpace *spacebase; ///< Address space containing relative offset parameters
int4 findEntry(const Address &loc,int4 size) const; ///< Given storage location find matching ParamEntry
const ParamEntry *findEntry(const Address &loc,int4 size) const; ///< Given storage location find matching ParamEntry
Address assignAddress(const Datatype *tp,vector<int4> &status) const; ///< Assign storage for given parameter data-type
void buildTrialMap(ParamActive *active) const; ///< Build map from parameter trials to model ParamEntrys
void separateFloat(ParamActive *active,int4 &floatstart,int4 &floatstop,int4 &start,int4 &stop) const;
@ -443,18 +506,22 @@ protected:
void forceNoUse(ParamActive *active,int4 start,int4 stop) const;
void forceInactiveChain(ParamActive *active,int4 maxchain,int4 start,int4 stop) const;
void calcDelay(void); ///< Calculate the maximum heritage delay for any potential parameter in this list
void populateResolver(void); ///< Build the ParamEntry resolver maps
public:
ParamListStandard(void) {} ///< Construct for use with restoreXml()
ParamListStandard(const ParamListStandard &op2); ///< Copy constructor
const vector<ParamEntry> &getEntry(void) const { return entry; } ///< Get the list of parameter entries
virtual ~ParamListStandard(void);
const list<ParamEntry> &getEntry(void) const { return entry; } ///< Get the list of parameter entries
virtual uint4 getType(void) const { return p_standard; }
virtual void assignMap(const vector<Datatype *> &proto,bool isinput,
TypeFactory &typefactory,vector<ParameterPieces> &res) const;
virtual void fillinMap(ParamActive *active) const;
virtual bool checkJoin(const Address &hiaddr,int4 hisize,const Address &loaddr,int4 losize) const;
virtual bool checkSplit(const Address &loc,int4 size,int4 splitpoint) const;
virtual int4 characterizeAsParam(const Address &loc,int4 size) const;
virtual bool possibleParam(const Address &loc,int4 size) const;
virtual bool possibleParamWithSlot(const Address &loc,int4 size,int4 &slot,int4 &slotsize) const;
virtual bool getBiggestContainedParam(const Address &loc,int4 size,VarnodeData &res) const;
virtual bool unjustifiedContainer(const Address &loc,int4 size,VarnodeData &res) const;
virtual OpCode assumedExtension(const Address &addr,int4 size,VarnodeData &res) const;
virtual AddrSpace *getSpacebase(void) const { return spacebase; }
@ -513,6 +580,7 @@ public:
ParamListMerged(void) : ParamListStandard() {} ///< Constructor for use with restoreXml
ParamListMerged(const ParamListMerged &op2) : ParamListStandard(op2) {} ///< Copy constructor
void foldIn(const ParamListStandard &op2); ///< Add another model to the union
void finalize(void) { populateResolver(); } ///< Fold-ins are finished, finalize \b this
virtual uint4 getType(void) const { return p_merged; }
virtual void assignMap(const vector<Datatype *> &proto,bool isinput,
TypeFactory &typefactory,vector<ParameterPieces> &res) const {
@ -636,6 +704,20 @@ public:
int4 numLikelyTrash(void) const { return likelytrash.size(); } ///< Get the number of \e likelytrash locations
const VarnodeData &getLikelyTrash(int4 i) const { return likelytrash[i]; } ///< Get the i-th \e likelytrashh location
/// \brief Characterize whether the given range overlaps parameter storage
///
/// Does the range naturally fit inside a potential parameter entry from this model or does
/// it contain a parameter entry. Return one of three values indicating this characterization:
/// - 0 means there is no intersection between the range and any ParamEntry
/// - 1 means that at least one ParamEntry contains the range in a properly justified manner
/// - 2 means no ParamEntry contains the range, but the range contains at least one ParamEntry
/// \param loc is the starting address of the given range
/// \param size is the number of bytes in the given range
/// \return the characterization code
int4 characterizeAsInputParam(const Address &loc,int4 size) const {
return input->characterizeAsParam(loc, size);
}
/// \brief Does the given storage location make sense as an input parameter
///
/// Within \b this model, decide if the storage location can be considered an input parameter.
@ -716,6 +798,16 @@ public:
OpCode assumedOutputExtension(const Address &addr,int4 size,VarnodeData &res) const {
return output->assumedExtension(addr,size,res); }
/// \brief Pass-back the biggest input parameter contained within the given range
///
/// \param loc is the starting address of the given range
/// \param size is the number of bytes in the range
/// \param res will hold the parameter storage description being passed back
/// \return \b true if there is at least one parameter contained in the range
bool getBiggestContainedInputParam(const Address &loc,int4 size,VarnodeData &res) const {
return input->getBiggestContainedParam(loc, size, res);
}
AddrSpace *getSpacebase(void) const { return input->getSpacebase(); } ///< Get the stack space associated with \b this model
bool isStackGrowsNegative(void) const { return stackgrowsnegative; } ///< Return \b true if the stack \e grows toward smaller addresses
bool hasThisPointer(void) const { return hasThis; } ///< Is \b this a model for (non-static) class methods
@ -1245,6 +1337,7 @@ public:
vector<EffectRecord>::const_iterator effectEnd(void) const; ///< Get iterator to end of EffectRecord list
int4 numLikelyTrash(void) const; ///< Get the number of \e likely-trash locations
const VarnodeData &getLikelyTrash(int4 i) const; ///< Get the i-th \e likely-trash location
int4 characterizeAsInputParam(const Address &addr,int4 size) const;
bool possibleInputParam(const Address &addr,int4 size) const;
bool possibleOutputParam(const Address &addr,int4 size) const;
@ -1292,6 +1385,9 @@ public:
OpCode assumedOutputExtension(const Address &addr,int4 size,VarnodeData &res) const {
return model->assumedOutputExtension(addr,size,res); }
/// \brief Pass-back the biggest potential input parameter contained within the given range
bool getBiggestContainedInputParam(const Address &loc,int4 size,VarnodeData &res) const;
bool isCompatible(const FuncProto &op2) const;
AddrSpace *getSpacebase(void) const { return model->getSpacebase(); } ///< Get the \e stack address space
void printRaw(const string &funcname,ostream &s) const;