#ifndef __CPUI_FSPEC__
#define __CPUI_FSPEC__
#include "op.hh"
#include "rangemap.hh"
class JoinRecord;
struct ParamUnassignedError : public LowlevelError {
ParamUnassignedError(const string &s) : LowlevelError(s) {} };
class ParamEntry {
public:
enum {
force_left_justify = 1, reverse_stack = 2, smallsize_zext = 4, smallsize_sext = 8, smallsize_inttype = 32, smallsize_floatext = 64, extracheck_high = 128, extracheck_low = 256, is_grouped = 512 };
private:
uint4 flags; type_metatype type; int4 group; int4 groupsize; AddrSpace *spaceid; uintb addressbase; int4 size; int4 minsize; int4 alignment; int4 numslots; JoinRecord *joinrec; static const ParamEntry *findEntryByStorage(const list<ParamEntry> &entryList,const VarnodeData &vn);
void resolveJoin(list<ParamEntry> &curList);
bool isLeftJustified(void) const { return (((flags&force_left_justify)!=0)||(!spaceid->isBigEndian())); }
public:
ParamEntry(int4 grp) { group=grp; } int4 getGroup(void) const { return group; } int4 getGroupSize(void) const { return groupsize; } int4 getSize(void) const { return size; } int4 getMinSize(void) const { return minsize; } int4 getAlign(void) const { return alignment; } type_metatype getType(void) const { return type; } bool isExclusion(void) const { return (alignment==0); } bool isReverseStack(void) const { return ((flags & reverse_stack)!=0); } bool isGrouped(void) const { return ((flags & is_grouped)!=0); } bool isNonOverlappingJoin(void) const; bool contains(const ParamEntry &op2) const; bool containedBy(const Address &addr,int4 sz) const; int4 justifiedContain(const Address &addr,int4 sz) const; bool getContainer(const Address &addr,int4 sz,VarnodeData &res) const;
OpCode assumedExtension(const Address &addr,int4 sz,VarnodeData &res) const;
int4 getSlot(const Address &addr,int4 skip) const;
AddrSpace *getSpace(void) const { return spaceid; } uintb getBase(void) const { return addressbase; } Address getAddrBySlot(int4 &slot,int4 sz) const;
void restoreXml(const Element *el,const AddrSpaceManager *manage,bool normalstack,bool grouped,list<ParamEntry> &curList);
void extraChecks(list<ParamEntry> &entry);
bool isParamCheckHigh(void) const { return ((flags & extracheck_high)!=0); } bool isParamCheckLow(void) const { return ((flags & extracheck_low)!=0); } int4 countJoinOverlap(const list<ParamEntry> &curList) const; static void orderWithinGroup(const ParamEntry &entry1,const ParamEntry &entry2); };
class ParamEntryRange {
uintb first; uintb last; int4 position; ParamEntry *entry;
class InitData {
friend class ParamEntryRange;
int4 position; ParamEntry *entry; public:
InitData(int4 pos,ParamEntry *e) { position = pos; entry = e; } };
class SubsortPosition {
int4 position; public:
SubsortPosition(void) {} SubsortPosition(int4 pos) { position = pos; } SubsortPosition(bool val) { position = val ? 1000000 : 0; } bool operator<(const SubsortPosition &op2) { return position < op2.position; } };
public:
typedef uintb linetype; typedef SubsortPosition subsorttype; typedef InitData inittype;
ParamEntryRange(const inittype &data,uintb f,uintb l) {
first = f; last = l; position = data.position; entry = data.entry; } uintb getFirst(void) const { return first; } uintb getLast(void) const { return last; } subsorttype getSubsort(void) const { return SubsortPosition(position); } ParamEntry *getParamEntry(void) const { return entry; } };
typedef rangemap<ParamEntryRange> ParamEntryResolver;
class ParamTrial {
public:
enum {
checked = 1, used = 2, defnouse = 4, active = 8, unref = 16, killedbycall = 32, rem_formed = 64, indcreate_formed = 128, condexe_effect = 256 };
private:
uint4 flags; Address addr; int4 size; int4 slot; const ParamEntry *entry; int4 offset; public:
ParamTrial(const Address &ad,int4 sz,int4 sl) { addr = ad; size = sz; slot = sl; flags=0; entry=(ParamEntry *)0; offset=-1; }
const Address &getAddress(void) const { return addr; } int4 getSize(void) const { return size; } int4 getSlot(void) const { return slot; } void setSlot(int4 val) { slot = val; } const ParamEntry *getEntry(void) const { return entry; } int4 getOffset(void) const { return offset; } void setEntry(const ParamEntry *ent,int4 off) { entry=ent; offset=off; } void markUsed(void) { flags |= used; } void markActive(void) { flags |= (active|checked); } void markInactive(void) { flags &= ~((uint4)active); flags |= checked; } void markNoUse(void) { flags &= ~((uint4)(active|used)); flags |= (checked|defnouse); } void markUnref(void) { flags |= (unref|checked); slot = -1; } void markKilledByCall(void) { flags |= killedbycall; } bool isChecked(void) const { return ((flags & checked)!=0); } bool isActive(void) const { return ((flags & active)!=0); } bool isDefinitelyNotUsed(void) const { return ((flags & defnouse)!=0); } bool isUsed(void) const { return ((flags & used)!=0); } bool isUnref(void) const { return ((flags & unref)!=0); } bool isKilledByCall(void) const { return ((flags & killedbycall)!=0); } void setRemFormed(void) { flags |= rem_formed; } bool isRemFormed(void) const { return ((flags & rem_formed)!=0); } void setIndCreateFormed(void) { flags |= indcreate_formed; } bool isIndCreateFormed(void) const { return ((flags & indcreate_formed)!=0); } void setCondExeEffect(void) { flags |= condexe_effect; } bool hasCondExeEffect(void) const { return ((flags & condexe_effect)!=0); } int4 slotGroup(void) const { return entry->getSlot(addr,size-1); } void setAddress(const Address &ad,int4 sz) { addr=ad; size=sz; } ParamTrial splitHi(int4 sz) const; ParamTrial splitLo(int4 sz) const; bool testShrink(const Address &newaddr,int4 sz) const; bool operator<(const ParamTrial &b) const; };
class ParamActive {
vector<ParamTrial> trial; int4 slotbase; int4 stackplaceholder; int4 numpasses; int4 maxpass; bool isfullychecked; bool needsfinalcheck; bool recoversubcall; public:
ParamActive(bool recoversub); void clear(void); void registerTrial(const Address &addr,int4 sz); int4 getNumTrials(void) const { return trial.size(); } ParamTrial &getTrial(int4 i) { return trial[i]; } const ParamTrial &getTrialForInputVarnode(int4 slot) const; int4 whichTrial(const Address &addr,int4 sz) const; bool needsFinalCheck(void) const { return needsfinalcheck; } void markNeedsFinalCheck(void) { needsfinalcheck = true; } bool isRecoverSubcall(void) const { return recoversubcall; } bool isFullyChecked(void) const { return isfullychecked; } void markFullyChecked(void) { isfullychecked = true; } void setPlaceholderSlot(void) { stackplaceholder = slotbase; slotbase += 1; } void freePlaceholderSlot(void); int4 getNumPasses(void) const { return numpasses; } int4 getMaxPass(void) const { return maxpass; } void setMaxPass(int4 val) { maxpass = val; } void finishPass(void) { numpasses += 1; } void sortTrials(void) { sort(trial.begin(),trial.end()); } void deleteUnusedTrials(void); void splitTrial(int4 i,int4 sz); void joinTrial(int4 slot,const Address &addr,int4 sz); int4 getNumUsed(void) const;
bool testShrink(int4 i,const Address &addr,int4 sz) const { return trial[i].testShrink(addr,sz); }
void shrink(int4 i,const Address &addr,int4 sz) { trial[i].setAddress(addr,sz); }
};
class FspecSpace : public AddrSpace {
public:
FspecSpace(AddrSpaceManager *m,const Translate *t,int4 ind); virtual void saveXmlAttributes(ostream &s,uintb offset) const;
virtual void saveXmlAttributes(ostream &s,uintb offset,int4 size) const;
virtual void printRaw(ostream &s,uintb offset) const;
virtual void saveXml(ostream &s) const;
virtual void restoreXml(const Element *el);
static const string NAME; };
struct ParameterPieces {
enum {
isthis = 1, hiddenretparm = 2, indirectstorage = 4, namelock = 8, typelock = 16, sizelock = 32 };
Address addr; Datatype *type; uint4 flags; };
class EffectRecord {
public:
enum {
unaffected = 1, killedbycall = 2, return_address = 3, unknown_effect = 4 };
private:
VarnodeData range; uint4 type; public:
EffectRecord(void) {} EffectRecord(const EffectRecord &op2) { range = op2.range; type = op2.type; } EffectRecord(const Address &addr,int4 size); EffectRecord(const ParamEntry &entry,uint4 t); EffectRecord(const VarnodeData &addr,uint4 t); uint4 getType(void) const { return type; } Address getAddress(void) const { return Address(range.space,range.offset); } int4 getSize(void) const { return range.size; } bool operator==(const EffectRecord &op2) const; bool operator!=(const EffectRecord &op2) const; void saveXml(ostream &s) const; void restoreXml(uint4 grouptype,const Element *el,const AddrSpaceManager *manage); static bool compareByAddress(const EffectRecord &op1,const EffectRecord &op2);
};
class ParamList {
public:
enum {
p_standard, p_standard_out, p_register, p_register_out, p_merged };
virtual ~ParamList(void) {} virtual uint4 getType(void) const=0;
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const=0;
virtual void fillinMap(ParamActive *active) const=0;
virtual bool checkJoin(const Address &hiaddr,int4 hisize,const Address &loaddr,int4 losize) const=0;
virtual bool checkSplit(const Address &loc,int4 size,int4 splitpoint) const=0;
virtual int4 characterizeAsParam(const Address &loc,int4 size) const=0;
virtual bool possibleParam(const Address &loc,int4 size) const=0;
virtual bool possibleParamWithSlot(const Address &loc,int4 size,int4 &slot,int4 &slotsize) const=0;
virtual bool getBiggestContainedParam(const Address &loc,int4 size,VarnodeData &res) const=0;
virtual bool unjustifiedContainer(const Address &loc,int4 size,VarnodeData &res) const=0;
virtual OpCode assumedExtension(const Address &addr,int4 size,VarnodeData &res) const=0;
virtual AddrSpace *getSpacebase(void) const=0;
virtual void getRangeList(AddrSpace *spc,RangeList &res) const=0;
virtual int4 getMaxDelay(void) const=0;
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack)=0;
virtual ParamList *clone(void) const=0; };
class ParamListStandard : public ParamList {
protected:
int4 numgroup; int4 maxdelay; int4 pointermax; bool thisbeforeret; int4 resourceTwoStart; list<ParamEntry> entry; vector<ParamEntryResolver *> resolverMap; AddrSpace *spacebase; const ParamEntry *findEntry(const Address &loc,int4 size) const; Address assignAddress(const Datatype *tp,vector<int4> &status) const; void buildTrialMap(ParamActive *active) const; void separateSections(ParamActive *active,int4 &oneStart,int4 &oneStop,int4 &twoStart,int4 &twoStop) const;
void forceExclusionGroup(ParamActive *active) const;
void forceNoUse(ParamActive *active,int4 start,int4 stop) const;
void forceInactiveChain(ParamActive *active,int4 maxchain,int4 start,int4 stop,int4 groupstart) const;
void calcDelay(void); void populateResolver(void); void parsePentry(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,
int4 groupid,bool normalstack,bool autokill,bool splitFloat,bool grouped);
void parseGroup(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,
int4 groupid,bool normalstack,bool autokill,bool splitFloat);
public:
ParamListStandard(void) {} ParamListStandard(const ParamListStandard &op2); virtual ~ParamListStandard(void);
const list<ParamEntry> &getEntry(void) const { return entry; } virtual uint4 getType(void) const { return p_standard; }
virtual void assignMap(const vector<Datatype *> &proto,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; }
virtual void getRangeList(AddrSpace *spc,RangeList &res) const;
virtual int4 getMaxDelay(void) const { return maxdelay; }
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
virtual ParamList *clone(void) const;
};
class ParamListRegisterOut : public ParamListStandard {
public:
ParamListRegisterOut(void) : ParamListStandard() {} ParamListRegisterOut(const ParamListRegisterOut &op2) : ParamListStandard(op2) {} virtual uint4 getType(void) const { return p_register_out; }
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
virtual void fillinMap(ParamActive *active) const;
virtual bool possibleParam(const Address &loc,int4 size) const;
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
virtual ParamList *clone(void) const;
};
class ParamListRegister : public ParamListStandard {
public:
ParamListRegister(void) : ParamListStandard() {} ParamListRegister(const ParamListRegister &op2) : ParamListStandard(op2) {} virtual uint4 getType(void) const { return p_register; }
virtual void fillinMap(ParamActive *active) const;
virtual ParamList *clone(void) const;
};
class ParamListStandardOut : public ParamListRegisterOut {
public:
ParamListStandardOut(void) : ParamListRegisterOut() {} ParamListStandardOut(const ParamListStandardOut &op2) : ParamListRegisterOut(op2) {} virtual uint4 getType(void) const { return p_standard_out; }
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
virtual ParamList *clone(void) const;
};
class ParamListMerged : public ParamListStandard {
public:
ParamListMerged(void) : ParamListStandard() {} ParamListMerged(const ParamListMerged &op2) : ParamListStandard(op2) {} void foldIn(const ParamListStandard &op2); void finalize(void) { populateResolver(); } virtual uint4 getType(void) const { return p_merged; }
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const {
throw LowlevelError("Cannot assign prototype before model has been resolved"); }
virtual void fillinMap(ParamActive *active) const {
throw LowlevelError("Cannot determine prototype before model has been resolved"); }
virtual ParamList *clone(void) const;
};
class ProtoModel {
friend class ProtoModelMerged;
Architecture *glb; string name; int4 extrapop; ParamList *input; ParamList *output; const ProtoModel *compatModel; vector<EffectRecord> effectlist; vector<VarnodeData> likelytrash; int4 injectUponEntry; int4 injectUponReturn; RangeList localrange; RangeList paramrange; bool stackgrowsnegative; bool hasThis; bool isConstruct; void defaultLocalRange(void); void defaultParamRange(void); void buildParamList(const string &strategy); public:
enum {
extrapop_unknown = 0x8000 };
ProtoModel(Architecture *g); ProtoModel(const string &nm,const ProtoModel &op2); virtual ~ProtoModel(void); const string &getName(void) const { return name; } Architecture *getArch(void) const { return glb; } uint4 hasEffect(const Address &addr,int4 size) const; int4 getExtraPop(void) const { return extrapop; } void setExtraPop(int4 ep) { extrapop = ep; } int4 getInjectUponEntry(void) const { return injectUponEntry; } int4 getInjectUponReturn(void) const { return injectUponReturn; } bool isCompatible(const ProtoModel *op2) const;
void deriveInputMap(ParamActive *active) const {
input->fillinMap(active); }
void deriveOutputMap(ParamActive *active) const {
output->fillinMap(active); }
void assignParameterStorage(const vector<Datatype *> &typelist,vector<ParameterPieces> &res,bool ignoreOutputError);
bool checkInputJoin(const Address &hiaddr,int4 hisize,const Address &loaddr,int4 losize) const {
return input->checkJoin(hiaddr,hisize,loaddr,losize); }
bool checkOutputJoin(const Address &hiaddr,int4 hisize,const Address &loaddr,int4 losize) const {
return output->checkJoin(hiaddr,hisize,loaddr,losize); }
bool checkInputSplit(const Address &loc,int4 size,int4 splitpoint) const {
return input->checkSplit(loc,size,splitpoint); }
const RangeList &getLocalRange(void) const { return localrange; } const RangeList &getParamRange(void) const { return paramrange; } vector<EffectRecord>::const_iterator effectBegin(void) const { return effectlist.begin(); } vector<EffectRecord>::const_iterator effectEnd(void) const { return effectlist.end(); } vector<VarnodeData>::const_iterator trashBegin(void) const { return likelytrash.begin(); } vector<VarnodeData>::const_iterator trashEnd(void) const { return likelytrash.end(); } int4 characterizeAsInputParam(const Address &loc,int4 size) const {
return input->characterizeAsParam(loc, size);
}
bool possibleInputParam(const Address &loc,int4 size) const {
return input->possibleParam(loc,size); }
bool possibleOutputParam(const Address &loc,int4 size) const {
return output->possibleParam(loc,size); }
bool possibleInputParamWithSlot(const Address &loc,int4 size,int4 &slot,int4 &slotsize) const {
return input->possibleParamWithSlot(loc,size,slot,slotsize); }
bool possibleOutputParamWithSlot(const Address &loc,int4 size,int4 &slot,int4 &slotsize) const {
return output->possibleParamWithSlot(loc,size,slot,slotsize); }
bool unjustifiedInputParam(const Address &loc,int4 size,VarnodeData &res) const {
return input->unjustifiedContainer(loc,size,res); }
OpCode assumedInputExtension(const Address &addr,int4 size,VarnodeData &res) const {
return input->assumedExtension(addr,size,res); }
OpCode assumedOutputExtension(const Address &addr,int4 size,VarnodeData &res) const {
return output->assumedExtension(addr,size,res); }
bool getBiggestContainedInputParam(const Address &loc,int4 size,VarnodeData &res) const {
return input->getBiggestContainedParam(loc, size, res);
}
AddrSpace *getSpacebase(void) const { return input->getSpacebase(); } bool isStackGrowsNegative(void) const { return stackgrowsnegative; } bool hasThisPointer(void) const { return hasThis; } bool isConstructor(void) const { return isConstruct; }
int4 getMaxInputDelay(void) const { return input->getMaxDelay(); }
int4 getMaxOutputDelay(void) const { return output->getMaxDelay(); }
virtual bool isMerged(void) const { return false; } virtual void restoreXml(const Element *el); static uint4 lookupEffect(const vector<EffectRecord> &efflist,const Address &addr,int4 size);
static int4 lookupRecord(const vector<EffectRecord> &efflist,int4 listSize,const Address &addr,int4 size);
};
class ScoreProtoModel {
class PEntry {
public:
int4 origIndex; int4 slot; int4 size; bool operator<(const PEntry &op2) const { return (slot < op2.slot); }
};
bool isinputscore; vector<PEntry> entry; const ProtoModel *model; int4 finalscore; int4 mismatch; public:
ScoreProtoModel(bool isinput,const ProtoModel *mod,int4 numparam); void addParameter(const Address &addr,int4 sz); void doScore(void); int4 getScore(void) const { return finalscore; } int4 getNumMismatch(void) const { return mismatch; } };
class ProtoModelMerged : public ProtoModel {
vector<ProtoModel *> modellist; void intersectEffects(const vector<EffectRecord> &efflist); void intersectLikelyTrash(const vector<VarnodeData> &trashlist); public:
ProtoModelMerged(Architecture *g) : ProtoModel(g) {} virtual ~ProtoModelMerged(void) {} int4 numModels(void) const { return modellist.size(); } ProtoModel *getModel(int4 i) const { return modellist[i]; } void foldIn(ProtoModel *model); ProtoModel *selectModel(ParamActive *active) const; virtual bool isMerged(void) const { return true; }
virtual void restoreXml(const Element *el);
};
class Symbol;
class AliasChecker;
class ProtoParameter {
public:
ProtoParameter(void) {} virtual ~ProtoParameter(void) {} virtual const string &getName(void) const=0; virtual Datatype *getType(void) const=0; virtual Address getAddress(void) const=0; virtual int4 getSize(void) const=0; virtual bool isTypeLocked(void) const=0; virtual bool isNameLocked(void) const=0; virtual bool isSizeTypeLocked(void) const=0; virtual bool isThisPointer(void) const=0; virtual bool isIndirectStorage(void) const=0; virtual bool isHiddenReturn(void) const=0; virtual bool isNameUndefined(void) const=0; virtual void setTypeLock(bool val)=0; virtual void setNameLock(bool val)=0; virtual void setThisPointer(bool val)=0;
virtual void overrideSizeLockType(Datatype *ct)=0;
virtual void resetSizeLockType(TypeFactory *factory)=0;
virtual ProtoParameter *clone(void) const=0;
virtual Symbol *getSymbol(void) const=0;
bool operator==(const ProtoParameter &op2) const {
if (getAddress() != op2.getAddress()) return false;
if (getType() != op2.getType()) return false;
return true;
}
bool operator!=(const ProtoParameter &op2) const {
return !(*this==op2); }
};
class ParameterBasic : public ProtoParameter {
string name; Address addr; Datatype *type; uint4 flags; public:
ParameterBasic(const string &nm,const Address &ad,Datatype *tp,uint4 fl) {
name = nm; addr = ad; type = tp; flags=fl; } ParameterBasic(Datatype *tp) {
type = tp; flags = 0; } virtual const string &getName(void) const { return name; }
virtual Datatype *getType(void) const { return type; }
virtual Address getAddress(void) const { return addr; }
virtual int4 getSize(void) const { return type->getSize(); }
virtual bool isTypeLocked(void) const { return ((flags&ParameterPieces::typelock)!=0); }
virtual bool isNameLocked(void) const { return ((flags&ParameterPieces::namelock)!=0); }
virtual bool isSizeTypeLocked(void) const { return ((flags&ParameterPieces::sizelock)!=0); }
virtual bool isThisPointer(void) const { return ((flags&ParameterPieces::isthis)!=0); }
virtual bool isIndirectStorage(void) const { return ((flags&ParameterPieces::indirectstorage)!=0); }
virtual bool isHiddenReturn(void) const { return ((flags&ParameterPieces::hiddenretparm)!=0); }
virtual bool isNameUndefined(void) const { return (name.size()==0); }
virtual void setTypeLock(bool val);
virtual void setNameLock(bool val);
virtual void setThisPointer(bool val);
virtual void overrideSizeLockType(Datatype *ct);
virtual void resetSizeLockType(TypeFactory *factory);
virtual ProtoParameter *clone(void) const;
virtual Symbol *getSymbol(void) const { throw LowlevelError("Parameter is not a real symbol"); }
};
class ProtoStore {
public:
virtual ~ProtoStore(void) {}
virtual ProtoParameter *setInput(int4 i,const string &nm,const ParameterPieces &pieces)=0;
virtual void clearInput(int4 i)=0;
virtual void clearAllInputs(void)=0; virtual int4 getNumInputs(void) const=0; virtual ProtoParameter *getInput(int4 i)=0;
virtual ProtoParameter *setOutput(const ParameterPieces &piece)=0;
virtual void clearOutput(void)=0; virtual ProtoParameter *getOutput(void)=0; virtual ProtoStore *clone(void) const=0;
virtual void saveXml(ostream &s) const=0;
virtual void restoreXml(const Element *el,ProtoModel *model)=0;
};
class ParameterSymbol : public ProtoParameter {
friend class ProtoStoreSymbol;
Symbol *sym; public:
ParameterSymbol(void) { sym = (Symbol *)0; } virtual const string &getName(void) const;
virtual Datatype *getType(void) const;
virtual Address getAddress(void) const;
virtual int4 getSize(void) const;
virtual bool isTypeLocked(void) const;
virtual bool isNameLocked(void) const;
virtual bool isSizeTypeLocked(void) const;
virtual bool isThisPointer(void) const;
virtual bool isIndirectStorage(void) const;
virtual bool isHiddenReturn(void) const;
virtual bool isNameUndefined(void) const;
virtual void setTypeLock(bool val);
virtual void setNameLock(bool val);
virtual void setThisPointer(bool val);
virtual void overrideSizeLockType(Datatype *ct);
virtual void resetSizeLockType(TypeFactory *factory);
virtual ProtoParameter *clone(void) const;
virtual Symbol *getSymbol(void) const;
};
class ProtoStoreSymbol : public ProtoStore {
Scope *scope; Address restricted_usepoint; vector<ProtoParameter *> inparam; ProtoParameter *outparam; ParameterSymbol *getSymbolBacked(int4 i); public:
ProtoStoreSymbol(Scope *sc,const Address &usepoint); virtual ~ProtoStoreSymbol(void);
virtual ProtoParameter *setInput(int4 i,const string &nm,const ParameterPieces &pieces);
virtual void clearInput(int4 i);
virtual void clearAllInputs(void);
virtual int4 getNumInputs(void) const;
virtual ProtoParameter *getInput(int4 i);
virtual ProtoParameter *setOutput(const ParameterPieces &piece);
virtual void clearOutput(void);
virtual ProtoParameter *getOutput(void);
virtual ProtoStore *clone(void) const;
virtual void saveXml(ostream &s) const;
virtual void restoreXml(const Element *el,ProtoModel *model);
};
class ProtoStoreInternal : public ProtoStore {
Datatype *voidtype; vector<ProtoParameter *> inparam; ProtoParameter *outparam; public:
ProtoStoreInternal(Datatype *vt); virtual ~ProtoStoreInternal(void);
virtual ProtoParameter *setInput(int4 i,const string &nm,const ParameterPieces &pieces);
virtual void clearInput(int4 i);
virtual void clearAllInputs(void);
virtual int4 getNumInputs(void) const;
virtual ProtoParameter *getInput(int4 i);
virtual ProtoParameter *setOutput(const ParameterPieces &piece);
virtual void clearOutput(void);
virtual ProtoParameter *getOutput(void);
virtual ProtoStore *clone(void) const;
virtual void saveXml(ostream &s) const;
virtual void restoreXml(const Element *el,ProtoModel *model);
};
struct PrototypePieces {
ProtoModel *model; string name; Datatype *outtype; vector<Datatype *> intypes; vector<string> innames; bool dotdotdot; };
class FuncProto {
enum {
dotdotdot = 1, voidinputlock = 2, modellock = 4, is_inline = 8, no_return = 16, paramshift_applied = 32, error_inputparam = 64, error_outputparam = 128, custom_storage = 256, unknown_model = 512, is_constructor = 0x400, is_destructor = 0x800, has_thisptr= 0x1000, is_override = 0x2000 };
ProtoModel *model; ProtoStore *store; int4 extrapop; uint4 flags; vector<EffectRecord> effectlist; vector<VarnodeData> likelytrash; int4 injectid; int4 returnBytesConsumed; void updateThisPointer(void); void saveEffectXml(ostream &s) const; void saveLikelyTrashXml(ostream &s) const; void restoreEffectXml(void); void restoreLikelyTrashXml(void); protected:
void paramShift(int4 paramshift); bool isParamshiftApplied(void) const { return ((flags¶mshift_applied)!=0); } void setParamshiftApplied(bool val) { flags = val ? (flags|paramshift_applied) : (flags & ~((uint4)paramshift_applied)); }
public:
FuncProto(void); ~FuncProto(void); Architecture *getArch(void) const { return model->getArch(); } void copy(const FuncProto &op2); void copyFlowEffects(const FuncProto &op2); void getPieces(PrototypePieces &pieces) const; void setPieces(const PrototypePieces &pieces); void setScope(Scope *s,const Address &startpoint); void setInternal(ProtoModel *m,Datatype *vt); void setModel(ProtoModel *m); bool hasModel(void) const { return (model != (ProtoModel *)0); }
bool hasMatchingModel(const FuncProto *op2) const { return (model == op2->model); } bool hasMatchingModel(const ProtoModel *op2) const { return (model == op2); } const string &getModelName(void) const { return model->getName(); } int4 getModelExtraPop(void) const { return model->getExtraPop(); }
bool isInputLocked(void) const; bool isOutputLocked(void) const { return store->getOutput()->isTypeLocked(); } bool isModelLocked(void) const { return ((flags&modellock)!=0); } bool isUnknownModel(void) const { return ((flags&unknown_model)!=0); } bool hasCustomStorage(void) const { return ((flags&custom_storage)!=0); } void setInputLock(bool val); void setOutputLock(bool val);
void setModelLock(bool val) { flags = val ? (flags|modellock) : (flags & ~((uint4)modellock)); }
bool isInline(void) const { return ((flags & is_inline)!=0); }
void setInline(bool val) { flags = val ? (flags|is_inline) : (flags & ~((uint4)is_inline)); }
int4 getInjectId(void) const { return injectid; }
int4 getReturnBytesConsumed(void) const { return returnBytesConsumed; }
bool setReturnBytesConsumed(int4 val);
bool isNoReturn(void) const { return ((flags & no_return)!=0); }
void setNoReturn(bool val) { flags = val ? (flags|no_return) : (flags & ~((uint4)no_return)); }
bool hasThisPointer(void) const { return ((flags & has_thisptr)!=0); }
bool isConstructor(void) const { return ((flags & is_constructor)!=0); }
void setConstructor(bool val) { flags = val ? (flags|is_constructor) : (flags & ~((uint4)is_constructor)); }
bool isDestructor(void) const { return ((flags & is_destructor)!=0); }
void setDestructor(bool val) { flags = val ? (flags|is_destructor) : (flags & ~((uint4)is_destructor)); }
bool hasInputErrors(void) const { return ((flags&error_inputparam)!=0); }
bool hasOutputErrors(void) const { return ((flags&error_outputparam)!=0); }
void setInputErrors(bool val) { flags = val ? (flags|error_inputparam) : (flags & ~((uint4)error_inputparam)); }
void setOutputErrors(bool val) { flags = val ? (flags|error_outputparam) : (flags & ~((uint4)error_outputparam)); }
int4 getExtraPop(void) const { return extrapop; } void setExtraPop(int4 ep) { extrapop = ep; } int4 getInjectUponEntry(void) const { return model->getInjectUponEntry(); } int4 getInjectUponReturn(void) const { return model->getInjectUponReturn(); } void resolveExtraPop(void);
void clearUnlockedInput(void); void clearUnlockedOutput(void); void clearInput(void); void cancelInjectId(void);
void resolveModel(ParamActive *active);
void deriveInputMap(ParamActive *active) const {
model->deriveInputMap(active); }
void deriveOutputMap(ParamActive *active) const {
model->deriveOutputMap(active); }
bool checkInputJoin(const Address &hiaddr,int4 hisz,const Address &loaddr,int4 losz) const {
return model->checkInputJoin(hiaddr,hisz,loaddr,losz); }
bool checkInputSplit(const Address &loc,int4 size,int4 splitpoint) const {
return model->checkInputSplit(loc,size,splitpoint); }
void updateInputTypes(Funcdata &data,const vector<Varnode *> &triallist,ParamActive *activeinput);
void updateInputNoTypes(Funcdata &data,const vector<Varnode *> &triallist,ParamActive *activeinput);
void updateOutputTypes(const vector<Varnode *> &triallist);
void updateOutputNoTypes(const vector<Varnode *> &triallist,TypeFactory *factory);
void updateAllTypes(const vector<string> &namelist,const vector<Datatype *> &typelist,bool dtdtdt);
ProtoParameter *getParam(int4 i) const { return store->getInput(i); } void removeParam(int4 i) { store->clearInput(i); } int4 numParams(void) const { return store->getNumInputs(); } ProtoParameter *getOutput(void) const { return store->getOutput(); } Datatype *getOutputType(void) const { return store->getOutput()->getType(); } const RangeList &getLocalRange(void) const { return model->getLocalRange(); } const RangeList &getParamRange(void) const { return model->getParamRange(); } bool isStackGrowsNegative(void) const { return model->isStackGrowsNegative(); } bool isDotdotdot(void) const { return ((flags&dotdotdot)!=0); } void setDotdotdot(bool val) { flags = val ? (flags|dotdotdot) : (flags & ~((uint4)dotdotdot)); } bool isOverride(void) const { return ((flags&is_override)!=0); } void setOverride(bool val) { flags = val ? (flags|is_override) : (flags & ~((uint4)is_override)); } uint4 hasEffect(const Address &addr,int4 size) const;
vector<EffectRecord>::const_iterator effectBegin(void) const; vector<EffectRecord>::const_iterator effectEnd(void) const; vector<VarnodeData>::const_iterator trashBegin(void) const; vector<VarnodeData>::const_iterator trashEnd(void) const; int4 characterizeAsInputParam(const Address &addr,int4 size) const;
bool possibleInputParam(const Address &addr,int4 size) const;
bool possibleOutputParam(const Address &addr,int4 size) const;
int4 getMaxInputDelay(void) const { return model->getMaxInputDelay(); }
int4 getMaxOutputDelay(void) const { return model->getMaxOutputDelay(); }
bool unjustifiedInputParam(const Address &addr,int4 size,VarnodeData &res) const;
OpCode assumedInputExtension(const Address &addr,int4 size,VarnodeData &res) const {
return model->assumedInputExtension(addr,size,res); }
OpCode assumedOutputExtension(const Address &addr,int4 size,VarnodeData &res) const {
return model->assumedOutputExtension(addr,size,res); }
bool getBiggestContainedInputParam(const Address &loc,int4 size,VarnodeData &res) const;
bool isCompatible(const FuncProto &op2) const;
AddrSpace *getSpacebase(void) const { return model->getSpacebase(); } void printRaw(const string &funcname,ostream &s) const;
uint4 getComparableFlags(void) const { return (flags & (dotdotdot | is_constructor | is_destructor | has_thisptr )); }
void saveXml(ostream &s) const;
void restoreXml(const Element *el,Architecture *glb);
};
class Funcdata;
class FuncCallSpecs : public FuncProto {
PcodeOp *op; string name; Address entryaddress; Funcdata *fd; int4 effective_extrapop; uintb stackoffset; int4 stackPlaceholderSlot; int4 paramshift; int4 matchCallCount; ParamActive activeinput; ParamActive activeoutput; mutable vector<int4> inputConsume; bool isinputactive; bool isoutputactive; bool isbadjumptable; Varnode *getSpacebaseRelative(void) const; Varnode *buildParam(Funcdata &data,Varnode *vn,ProtoParameter *param,Varnode *stackref);
int4 transferLockedInputParam(ProtoParameter *param);
PcodeOp *transferLockedOutputParam(ProtoParameter *param);
bool transferLockedInput(vector<Varnode *> &newinput);
bool transferLockedOutput(Varnode *&newoutput);
void commitNewInputs(Funcdata &data,vector<Varnode *> &newinput);
void commitNewOutputs(Funcdata &data,Varnode *newout);
void collectOutputTrialVarnodes(vector<Varnode *> &trialvn);
public:
enum {
offset_unknown = 0xBADBEEF };
FuncCallSpecs(PcodeOp *call_op); void setAddress(const Address &addr) { entryaddress = addr; } PcodeOp *getOp(void) const { return op; } Funcdata *getFuncdata(void) const { return fd; } void setFuncdata(Funcdata *f); FuncCallSpecs *clone(PcodeOp *newop) const; const string &getName(void) const { return name; } const Address &getEntryAddress(void) const { return entryaddress; } void setEffectiveExtraPop(int4 epop) { effective_extrapop = epop; } int4 getEffectiveExtraPop(void) const { return effective_extrapop; } uintb getSpacebaseOffset(void) const { return stackoffset; } void setParamshift(int4 val) { paramshift = val; } int4 getParamshift(void) const { return paramshift; } int4 getMatchCallCount(void) const { return matchCallCount; } int4 getStackPlaceholderSlot(void) const { return stackPlaceholderSlot; } void setStackPlaceholderSlot(int4 slot) { stackPlaceholderSlot = slot;
if (isinputactive) activeinput.setPlaceholderSlot(); } void clearStackPlaceholderSlot(void) {
stackPlaceholderSlot = -1; if (isinputactive) activeinput.freePlaceholderSlot(); }
void initActiveInput(void); void clearActiveInput(void) { isinputactive = false; } void initActiveOutput(void) { isoutputactive = true; } void clearActiveOutput(void) { isoutputactive = false; } bool isInputActive(void) const { return isinputactive; } bool isOutputActive(void) const { return isoutputactive; } void setBadJumpTable(bool val) { isbadjumptable = val; } bool isBadJumpTable(void) const { return isbadjumptable; } ParamActive *getActiveInput(void) { return &activeinput; } ParamActive *getActiveOutput(void) { return &activeoutput; }
bool checkInputJoin(int4 slot1,bool ishislot,Varnode *vn1,Varnode *vn2) const;
void doInputJoin(int4 slot1,bool ishislot);
bool lateRestriction(const FuncProto &restrictedProto,vector<Varnode *> &newinput,Varnode *&newoutput);
void deindirect(Funcdata &data,Funcdata *newfd);
void forceSet(Funcdata &data,const FuncProto &fp);
void insertPcode(Funcdata &data);
void resolveSpacebaseRelative(Funcdata &data,Varnode *phvn);
void abortSpacebaseRelative(Funcdata &data);
void finalInputCheck(void);
void checkInputTrialUse(Funcdata &data,AliasChecker &aliascheck);
void checkOutputTrialUse(Funcdata &data,vector<Varnode *> &trialvn);
void buildInputFromTrials(Funcdata &data);
void buildOutputFromTrials(Funcdata &data,vector<Varnode *> &trialvn);
int4 getInputBytesConsumed(int4 slot) const;
bool setInputBytesConsumed(int4 slot,int4 val) const;
void paramshiftModifyStart(void);
bool paramshiftModifyStop(Funcdata &data);
uint4 hasEffectTranslate(const Address &addr,int4 size) const;
static Varnode *findPreexistingWhole(Varnode *vn1,Varnode *vn2);
static FuncCallSpecs *getFspecFromConst(const Address &addr) { return (FuncCallSpecs *)(uintp)addr.getOffset(); }
static bool compareByEntryAddress(const FuncCallSpecs *a,const FuncCallSpecs *b) { return a->entryaddress < b->entryaddress; }
static void countMatchingCalls(const vector<FuncCallSpecs *> &qlst);
};
inline const ParamTrial &ParamActive::getTrialForInputVarnode(int4 slot) const
{
slot -= ((stackplaceholder<0)||(slot<stackplaceholder)) ? 1 : 2;
return trial[slot];
}
inline bool EffectRecord::compareByAddress(const EffectRecord &op1,const EffectRecord &op2)
{
if (op1.range.space != op2.range.space)
return (op1.range.space->getIndex() < op2.range.space->getIndex());
return (op1.range.offset < op2.range.offset);
}
inline bool EffectRecord::operator==(const EffectRecord &op2) const
{
if (range != op2.range) return false;
return (type == op2.type);
}
inline bool EffectRecord::operator!=(const EffectRecord &op2) const
{
if (range != op2.range) return true;
return (type != op2.type);
}
#endif