#ifndef __CPUI_TRANSLATE__
#define __CPUI_TRANSLATE__
#include "pcoderaw.hh"
#include "float.hh"
struct UnimplError : public LowlevelError {
int4 instruction_length; UnimplError(const string &s,int4 l) : LowlevelError(s) { instruction_length = l; }
};
struct BadDataError : public LowlevelError {
BadDataError(const string &s) : LowlevelError(s) {}
};
class Translate;
class TruncationTag {
string spaceName; uint4 size; public:
void restoreXml(const Element *el); const string &getName(void) const { return spaceName; } uint4 getSize(void) const { return size; } };
class PcodeEmit {
public:
virtual ~PcodeEmit(void) {}
virtual void dump(const Address &addr,OpCode opc,VarnodeData *outvar,VarnodeData *vars,int4 isize)=0;
void restoreXmlOp(const Element *el,const AddrSpaceManager *trans);
enum { unimpl_tag = 0x20,
inst_tag = 0x21,
op_tag = 0x22,
void_tag = 0x23,
spaceid_tag = 0x24,
addrsz_tag = 0x25,
end_tag = 0x60
};
static const uint1 *unpackOffset(const uint1 *ptr,uintb &off);
static const uint1 *unpackVarnodeData(const uint1 *ptr,VarnodeData &v,const AddrSpaceManager *trans);
const uint1 *restorePackedOp(const Address &addr,const uint1 *ptr,const AddrSpaceManager *trans);
};
class AssemblyEmit {
public:
virtual ~AssemblyEmit(void) {}
virtual void dump(const Address &addr,const string &mnem,const string &body)=0;
};
class AddressResolver {
public:
virtual ~AddressResolver(void) {}
virtual Address resolve(uintb val,int4 sz,const Address &point,uintb &fullEncoding)=0;
};
class SpacebaseSpace : public AddrSpace {
friend class AddrSpaceManager;
AddrSpace *contain; bool hasbaseregister; bool isNegativeStack; VarnodeData baseloc; VarnodeData baseOrig; void setBaseRegister(const VarnodeData &data,int4 origSize,bool stackGrowth); public:
SpacebaseSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,int4 sz,AddrSpace *base,int4 dl);
SpacebaseSpace(AddrSpaceManager *m,const Translate *t); virtual int4 numSpacebase(void) const;
virtual const VarnodeData &getSpacebase(int4 i) const;
virtual const VarnodeData &getSpacebaseFull(int4 i) const;
virtual bool stackGrowsNegative(void) const { return isNegativeStack; }
virtual AddrSpace *getContain(void) const { return contain; } virtual void saveXml(ostream &s) const;
virtual void restoreXml(const Element *el);
};
class JoinRecord {
friend class AddrSpaceManager;
vector<VarnodeData> pieces; VarnodeData unified; public:
int4 numPieces(void) const { return pieces.size(); } bool isFloatExtension(void) const { return (pieces.size() == 1); } const VarnodeData &getPiece(int4 i) const { return pieces[i]; } const VarnodeData &getUnified(void) const { return unified; } Address getEquivalentAddress(uintb offset,int4 &pos) const; bool operator<(const JoinRecord &op2) const; };
struct JoinRecordCompare {
bool operator()(const JoinRecord *a,const JoinRecord *b) const {
return *a < *b; } };
class AddrSpaceManager {
vector<AddrSpace *> baselist; vector<AddressResolver *> resolvelist; map<string,AddrSpace *> name2Space; map<int4,AddrSpace *> shortcut2Space; AddrSpace *constantspace; AddrSpace *defaultcodespace; AddrSpace *defaultdataspace; AddrSpace *iopspace; AddrSpace *fspecspace; AddrSpace *joinspace; AddrSpace *stackspace; AddrSpace *uniqspace; uintb joinallocate; set<JoinRecord *,JoinRecordCompare> splitset; vector<JoinRecord *> splitlist; protected:
AddrSpace *restoreXmlSpace(const Element *el,const Translate *trans); void restoreXmlSpaces(const Element *el,const Translate *trans); void setDefaultCodeSpace(int4 index); void setDefaultDataSpace(int4 index); void setReverseJustified(AddrSpace *spc); void assignShortcut(AddrSpace *spc); void markNearPointers(AddrSpace *spc,int4 size); void insertSpace(AddrSpace *spc); void copySpaces(const AddrSpaceManager *op2); void addSpacebasePointer(SpacebaseSpace *basespace,const VarnodeData &ptrdata,int4 truncSize,bool stackGrowth); void insertResolver(AddrSpace *spc,AddressResolver *rsolv); void setInferPtrBounds(const Range &range); JoinRecord *findJoinInternal(uintb offset) const; public:
AddrSpaceManager(void); virtual ~AddrSpaceManager(void); int4 getDefaultSize(void) const; AddrSpace *getSpaceByName(const string &nm) const; AddrSpace *getSpaceByShortcut(char sc) const; AddrSpace *getIopSpace(void) const; AddrSpace *getFspecSpace(void) const; AddrSpace *getJoinSpace(void) const; AddrSpace *getStackSpace(void) const; AddrSpace *getUniqueSpace(void) const; AddrSpace *getDefaultCodeSpace(void) const; AddrSpace *getDefaultDataSpace(void) const; AddrSpace *getConstantSpace(void) const; Address getConstant(uintb val) const; Address createConstFromSpace(AddrSpace *spc) const; Address resolveConstant(AddrSpace *spc,uintb val,int4 sz,const Address &point,uintb &fullEncoding) const;
int4 numSpaces(void) const; AddrSpace *getSpace(int4 i) const; AddrSpace *getNextSpaceInOrder(AddrSpace *spc) const; JoinRecord *findAddJoin(const vector<VarnodeData> &pieces,uint4 logicalsize); JoinRecord *findJoin(uintb offset) const; void setDeadcodeDelay(AddrSpace *spc,int4 delaydelta); void truncateSpace(const TruncationTag &tag);
Address constructFloatExtensionAddress(const Address &realaddr,int4 realsize,int4 logicalsize);
Address constructJoinAddress(const Translate *translate,const Address &hiaddr,int4 hisz,const Address &loaddr,int4 losz);
void renormalizeJoinAddress(Address &addr,int4 size);
};
class Translate : public AddrSpaceManager {
public:
enum UniqueLayout {
RUNTIME_BOOLEAN_INVERT=0, RUNTIME_RETURN_LOCATION=0x80, RUNTIME_BITRANGE_EA=0x100, INJECT=0x200, ANALYSIS=0x10000000 };
private:
bool target_isbigendian; uint4 unique_base; protected:
int4 alignment; vector<FloatFormat> floatformats;
void setBigEndian(bool val); void setUniqueBase(uint4 val); public:
Translate(void); void setDefaultFloatFormats(void); bool isBigEndian(void) const; const FloatFormat *getFloatFormat(int4 size) const; int4 getAlignment(void) const; uint4 getUniqueBase(void) const; uint4 getUniqueStart(UniqueLayout layout) const;
virtual void initialize(DocumentStorage &store)=0;
virtual void registerContext(const string &name,int4 sbit,int4 ebit) {}
virtual void setContextDefault(const string &name,uintm val) {}
virtual void allowContextSet(bool val) const {}
virtual const VarnodeData &getRegister(const string &nm) const=0;
virtual string getRegisterName(AddrSpace *base,uintb off,int4 size) const=0;
virtual void getAllRegisters(map<VarnodeData,string> ®list) const=0;
virtual void getUserOpNames(vector<string> &res) const=0;
virtual int4 instructionLength(const Address &baseaddr) const=0;
virtual int4 oneInstruction(PcodeEmit &emit,const Address &baseaddr) const=0;
virtual int4 printAssembly(AssemblyEmit &emit,const Address &baseaddr) const=0;
};
inline int4 AddrSpaceManager::getDefaultSize(void) const {
return defaultcodespace->getAddrSize();
}
inline AddrSpace *AddrSpaceManager::getIopSpace(void) const {
return iopspace;
}
inline AddrSpace *AddrSpaceManager::getFspecSpace(void) const {
return fspecspace;
}
inline AddrSpace *AddrSpaceManager::getJoinSpace(void) const {
return joinspace;
}
inline AddrSpace *AddrSpaceManager::getStackSpace(void) const {
return stackspace;
}
inline AddrSpace *AddrSpaceManager::getUniqueSpace(void) const {
return uniqspace;
}
inline AddrSpace *AddrSpaceManager::getDefaultCodeSpace(void) const {
return defaultcodespace;
}
inline AddrSpace *AddrSpaceManager::getDefaultDataSpace(void) const {
return defaultdataspace;
}
inline AddrSpace *AddrSpaceManager::getConstantSpace(void) const {
return constantspace;
}
inline Address AddrSpaceManager::getConstant(uintb val) const {
return Address(constantspace,val);
}
inline Address AddrSpaceManager::createConstFromSpace(AddrSpace *spc) const {
return Address(constantspace,(uintb)(uintp)spc);
}
inline int4 AddrSpaceManager::numSpaces(void) const {
return baselist.size();
}
inline AddrSpace *AddrSpaceManager::getSpace(int4 i) const {
return baselist[i];
}
inline void Translate::setBigEndian(bool val) {
target_isbigendian = val;
}
inline void Translate::setUniqueBase(uint4 val) {
if (val>unique_base) unique_base = val;
}
inline bool Translate::isBigEndian(void) const {
return target_isbigendian;
}
inline int4 Translate::getAlignment(void) const {
return alignment;
}
inline uint4 Translate::getUniqueBase(void) const {
return unique_base;
}
inline uint4 Translate::getUniqueStart(UniqueLayout layout) const {
return (layout != ANALYSIS) ? layout + unique_base : layout;
}
#endif