name to address space map

shortcut to address space map
more adjustments to shortcuts
allow null AddrSpace pointer in raw baselist
holes in the space indices
almost working
GT-2873 decompiler, other, and overlays
GT-2873 added OTHER space to java sleigh compiler, fixed decompiler
exception
isOtherSpace method
isOtherSpace java, addressing code review comments
GT-2873 added null check in decompiler reset
GT-2873 code review changes
Read and write space_other tag in SLA files
Version number for .sla file
GT-2873 fixups after merge
GT-2873 renamed Sparc registers: OTHER->OTHERWIN, WINWSTATE->WSTATE
GT-2873 added option in AddressInput to control OTHER space visibility
GT-2873 OTHER space now global
GT-2873 fixing comments refering to decompiler code in BasicCompilerSpec
This commit is contained in:
caheckman 2019-05-24 17:47:04 -04:00 committed by James
parent cf47a2ee57
commit 612c0d6f3e
40 changed files with 545 additions and 213 deletions

View file

@ -206,6 +206,7 @@ AddrSpace *Architecture::getSpaceBySpacebase(const Address &loc,int4 size) const
int4 sz = numSpaces();
for(int4 i=0;i<sz;++i) {
id = getSpace(i);
if (id == (AddrSpace *)0) continue;
int4 numspace = id->numSpacebase();
for(int4 j=0;j<numspace;++j) {
const VarnodeData &point(id->getSpacebase(j));
@ -337,6 +338,7 @@ void Architecture::globalify(void)
for(int4 i=0;i<nm;++i) {
AddrSpace *spc = getSpace(i);
if (spc == (AddrSpace *)0) continue;
if ((spc->getType() != IPTR_PROCESSOR)&&(spc->getType() != IPTR_SPACEBASE)) continue;
symboltab->addRange(scope,spc,(uintb)0,spc->getHighest());
}
@ -707,7 +709,7 @@ void Architecture::parseGlobal(const Element *el)
Scope *scope = buildGlobalScope();
const List &list(el->getChildren());
List::const_iterator iter;
for(iter=list.begin();iter!=list.end();++iter) {
Range range;
range.restoreXml(*iter,this);
@ -716,15 +718,33 @@ void Architecture::parseGlobal(const Element *el)
// We need to duplicate the range being marked as global into the overlay space(s)
int4 num = numSpaces();
for(int4 i=0;i<num;++i) {
OverlaySpace *ospc = (OverlaySpace *)getSpace(i);
if (!ospc->isOverlay()) continue;
if (ospc->getBaseSpace() != range.getSpace()) continue;
symboltab->addRange(scope,ospc,range.getFirst(),range.getLast());
OverlaySpace *ospc = (OverlaySpace *)getSpace(i);
if (ospc == (AddrSpace *)0 || !ospc->isOverlay()) continue;
if (ospc->getBaseSpace() != range.getSpace()) continue;
symboltab->addRange(scope,ospc,range.getFirst(),range.getLast());
}
}
}
}
//explictly add the OTHER space and any overlays to the global scope
void Architecture::addOtherSpace(void)
{
Scope *scope = buildGlobalScope();
AddrSpace *otherSpace = getSpaceByName("OTHER");
symboltab->addRange(scope,otherSpace,0,otherSpace->getHighest());
if (otherSpace->isOverlayBase()) {
int4 num = numSpaces();
for(int4 i=0;i<num;++i){
OverlaySpace *ospc = (OverlaySpace *)getSpace(i);
if (ospc->getBaseSpace() != otherSpace) continue;
if (ospc->getBaseSpace() != otherSpace) continue;
symboltab->addRange(scope,ospc,0,otherSpace->getHighest());
}
}
}
/// This applies info from a \<readonly> tag marking a specific region
/// of the executable as \e read-only.
/// \param el is the XML element
@ -835,7 +855,7 @@ void Architecture::parseDeadcodeDelay(const Element *el)
int4 delay = -1;
s >> delay;
if (delay >= 0)
setDeadcodeDelay(spc->getIndex(),delay);
setDeadcodeDelay(spc,delay);
else
throw LowlevelError("Bad <deadcodedelay> tag");
}
@ -1031,11 +1051,13 @@ void Architecture::parseCompilerConfig(DocumentStorage &store)
else if (elname == "deadcodedelay")
parseDeadcodeDelay(*iter);
}
// <global> tags instantiate the base symbol table
// They need to know about all spaces, so it must come
// after parsing of <stackpointer> and <spacebase>
// <global> tags instantiate the base symbol table
// They need to know about all spaces, so it must come
// after parsing of <stackpointer> and <spacebase>
for(int4 i=0;i<globaltags.size();++i)
parseGlobal(globaltags[i]);
addOtherSpace();
if (defaultfp == (ProtoModel *)0) {
if (protoModels.size() == 1)

View file

@ -255,6 +255,7 @@ protected:
void parseProtoEval(const Element *el); ///< Apply prototype evaluation configuration
void parseDefaultProto(const Element *el); ///< Apply default prototype model configuration
void parseGlobal(const Element *el); ///< Apply global space configuration
void addOtherSpace(void); ////add OTHER space and all of its overlays to the symboltab
void parseReadOnly(const Element *el); ///< Apply read-only region configuration
void parseVolatile(const Element *el); ///< Apply volatile region configuration
void parseReturnAddress(const Element *el); ///< Apply return address configuration

View file

@ -367,10 +367,11 @@ void ConditionalExecution::buildHeritageArray(void)
{
heritageyes.clear();
Architecture *glb = fd->getArch();
heritageyes.resize(glb->numSpaces(),false);
for(int4 i=0;i<glb->numSpaces();++i) {
AddrSpace *spc = glb->getSpace(i);
if (spc == (AddrSpace *)0) continue;
int4 index = spc->getIndex();
heritageyes.push_back(false);
if (!spc->isHeritaged()) continue;
if (fd->numHeritagePasses(spc) > 0)
heritageyes[index] = true; // At least one pass has been performed on the space

View file

@ -2239,6 +2239,7 @@ int4 ActionNameVars::apply(Funcdata &data)
for(int4 i=0;i<manage->numSpaces();++i) { // Build a list of nameable highs
spc = manage->getSpace(i);
if (spc == (AddrSpace *)0) continue;
enditer = data.endLoc(spc);
for(iter=data.beginLoc(spc);iter!=enditer;++iter) {
Varnode *curvn = *iter;
@ -3094,7 +3095,7 @@ int4 ActionDeadCode::apply(Funcdata &data)
// Set pre-live registers
for(i=0;i<manage->numSpaces();++i) {
spc = manage->getSpace(i);
if (!spc->doesDeadcode()) continue;
if (spc == (AddrSpace *)0 || !spc->doesDeadcode()) continue;
if (data.deadRemovalAllowed(spc)) continue; // Mark consumed if we have NOT heritaged
viter = data.beginLoc(spc);
endviter = data.endLoc(spc);
@ -3138,7 +3139,7 @@ int4 ActionDeadCode::apply(Funcdata &data)
for(i=0;i<manage->numSpaces();++i) {
spc = manage->getSpace(i);
if (!spc->doesDeadcode()) continue;
if (spc == (AddrSpace *)0 || !spc->doesDeadcode()) continue;
if (!data.deadRemovalAllowed(spc)) continue; // Don't eliminate if we haven't heritaged
viter = data.beginLoc(spc);
endviter = data.endLoc(spc);

View file

@ -208,6 +208,7 @@ void Funcdata::spacebase(void)
for(j=0;j<glb->numSpaces();++j) {
spc = glb->getSpace(j);
if (spc == (AddrSpace *)0) continue;
numspace = spc->numSpacebase();
for(i=0;i<numspace;++i) {
const VarnodeData &point(spc->getSpacebase(i));
@ -617,7 +618,7 @@ void Funcdata::saveXmlTree(ostream &s) const
s << "<varnodes>\n";
for(int4 i=0;i<glb->numSpaces();++i) {
AddrSpace *base = glb->getSpace(i);
if (base->getType()==IPTR_IOP) continue;
if (base == (AddrSpace *)0 || base->getType()==IPTR_IOP) continue;
VarnodeLocSet::const_iterator iter = vbank.beginLoc(base);
VarnodeLocSet::const_iterator enditer = vbank.endLoc(base);
saveVarnodeXml(s,iter,enditer);

View file

@ -2212,11 +2212,16 @@ void Heritage::buildInfoList(void)
{
if (!infolist.empty()) return;
AddrSpace *spc;
const AddrSpaceManager *manage = fd->getArch();
infolist.resize(manage->numSpaces());
for(int4 i=0;i<manage->numSpaces();++i) {
spc = manage->getSpace(i);
infolist.push_back(HeritageInfo(spc,spc->getDelay(),spc->getDeadcodeDelay()));
AddrSpace *spc = manage->getSpace(i);
if (spc == (AddrSpace *)0)
infolist[i].set((AddrSpace *)0,0,0);
else if (!spc->isHeritaged())
infolist[i].set((AddrSpace *)0,spc->getDelay(),spc->getDeadcodeDelay());
else
infolist[i].set(spc,spc->getDelay(),spc->getDeadcodeDelay());
}
}
@ -2227,7 +2232,6 @@ void Heritage::heritage(void)
{
VarnodeLocSet::const_iterator iter,enditer;
AddrSpace *space;
HeritageInfo *info;
Varnode *vn;
bool needwarning;
@ -2235,7 +2239,6 @@ void Heritage::heritage(void)
int4 reprocessStackCount = 0;
AddrSpace *stackSpace = (AddrSpace *)0;
vector<PcodeOp *> freeStores;
const AddrSpaceManager *manage = fd->getArch();
PreferSplitManager splitmanage;
if (maxdepth == -1) // Has a restructure been forced
@ -2246,21 +2249,20 @@ void Heritage::heritage(void)
splitmanage.init(fd,&fd->getArch()->splitrecords);
splitmanage.split();
}
for(int4 i=0;i<manage->numSpaces();++i) {
space = manage->getSpace(i);
if (!space->isHeritaged()) continue;
info = getInfo(space);
for(int4 i=0;i<infolist.size();++i) {
info = &infolist[i];
if (!info->isHeritaged()) continue;
if (pass < info->delay) continue; // It is too soon to heritage this space
if (!info->loadGuardSearch) {
info->loadGuardSearch = true;
if (discoverIndexedStackPointers(info->space,freeStores,true)) {
reprocessStackCount += 1;
stackSpace = space;
reprocessStackCount += 1;
stackSpace = info->space;
}
}
needwarning = false;
iter = fd->beginLoc(space);
enditer = fd->endLoc(space);
iter = fd->beginLoc(info->space);
enditer = fd->endLoc(info->space);
while(iter != enditer) {
vn = *iter++;
@ -2343,7 +2345,7 @@ int4 Heritage::numHeritagePasses(AddrSpace *spc) const
{
const HeritageInfo *info = getInfo(spc);
if (info == (const HeritageInfo *)0)
if (!info->isHeritaged())
throw LowlevelError("Trying to calculate passes for non-heritaged space");
return (info->delay - pass);
}
@ -2355,8 +2357,6 @@ void Heritage::seenDeadCode(AddrSpace *spc)
{
HeritageInfo *info = getInfo(spc);
if (info == (HeritageInfo *)0)
throw LowlevelError("Informed of deadcode removal for non-heritaged space");
info->deadremoved = 1;
}
@ -2369,8 +2369,6 @@ int4 Heritage::getDeadCodeDelay(AddrSpace *spc) const
{
const HeritageInfo *info = getInfo(spc);
if (info == (const HeritageInfo *)0)
throw LowlevelError("Could not get heritage delay for space: "+spc->getName());
return info->deadcodedelay;
}
@ -2383,8 +2381,6 @@ void Heritage::setDeadCodeDelay(AddrSpace *spc,int4 delay)
{
HeritageInfo *info = getInfo(spc);
if (info == (HeritageInfo *)0)
throw LowlevelError("Setting heritage delay for non-heritaged space");
if (delay < info->delay)
throw LowlevelError("Illegal deadcode delay setting");
info->deadcodedelay = delay;
@ -2399,8 +2395,6 @@ bool Heritage::deadRemovalAllowed(AddrSpace *spc) const
{
const HeritageInfo *info = getInfo(spc);
if (info == (HeritageInfo *)0)
throw LowlevelError("Heritage query for non-heritaged space");
return (pass > info->deadcodedelay);
}
@ -2415,8 +2409,6 @@ bool Heritage::deadRemovalAllowedSeen(AddrSpace *spc)
{
HeritageInfo *info = getInfo(spc);
if (info == (HeritageInfo *)0)
throw LowlevelError("Heritage query for non-heritaged space");
bool res = (pass > info->deadcodedelay);
if (res)
info->deadremoved = 1;

View file

@ -90,8 +90,9 @@ class HeritageInfo {
int4 deadremoved; ///< >0 if Varnodes in this space have been eliminated
bool loadGuardSearch; ///< \b true if the search for LOAD ops to guard has been performed
bool warningissued; ///< \b true if warning issued previously
HeritageInfo(AddrSpace *spc,int4 dl,int4 dcdl) {
space=spc; delay=dl; deadcodedelay=dcdl; deadremoved=0; loadGuardSearch=false; warningissued=false; } ///< Constructor
void set(AddrSpace *spc,int4 dl,int4 dcdl) {
space=spc; delay=dl; deadcodedelay=dcdl; deadremoved=0; warningissued=false; loadGuardSearch = false; } ///< Set all fields
bool isHeritaged(void) const { return (space != (AddrSpace *)0); }
void reset(void) {
deadremoved = 0; deadcodedelay = delay; warningissued = false; loadGuardSearch = false; } ///< Reset
};

View file

@ -895,6 +895,7 @@ void IfcPrintSpaces::execute(istream &s)
int4 num = manage->numSpaces();
for(int4 i=0;i<num;++i) {
AddrSpace *spc = manage->getSpace(i);
if (spc == (AddrSpace *)0) continue;
*status->fileoptr << dec << spc->getIndex() << " : '" << spc->getShortcut() << "' " << spc->getName();
if (spc->getType() == IPTR_CONSTANT)
*status->fileoptr << " constant ";
@ -1468,7 +1469,7 @@ void IfcDeadcodedelay::execute(istream &s)
*status->optr << "Successfully overrided deadcode delay for single function" << endl;
}
else {
dcp->conf->setDeadcodeDelay(spc->getIndex(),delay);
dcp->conf->setDeadcodeDelay(spc,delay);
*status->optr << "Successfully overrided deadcode delay for all functions" << endl;
}
}

View file

@ -15,6 +15,8 @@
*/
#include "sleighbase.hh"
const int4 SleighBase::SLA_FORMAT_VERSION = 2;
SleighBase::SleighBase(void)
{
@ -146,6 +148,7 @@ void SleighBase::saveXml(ostream &s) const
{
s << "<sleigh";
a_v_i(s,"version",SLA_FORMAT_VERSION);
a_v_b(s,"bigendian",isBigEndian());
a_v_i(s,"align",alignment);
a_v_u(s,"uniqbase",getUniqueBase());
@ -162,6 +165,7 @@ void SleighBase::saveXml(ostream &s) const
s << ">\n";
for(int4 i=0;i<numSpaces();++i) {
AddrSpace *spc = getSpace(i);
if (spc == (AddrSpace *)0) continue;
if ((spc->getType()==IPTR_CONSTANT) ||
(spc->getType()==IPTR_FSPEC)||
(spc->getType()==IPTR_IOP)||
@ -183,6 +187,7 @@ void SleighBase::restoreXml(const Element *el)
maxdelayslotbytes = 0;
unique_allocatemask = 0;
numSections = 0;
int4 version = 0;
setBigEndian(xml_readbool(el->getAttributeValue("bigendian")));
{
istringstream s(el->getAttributeValue("align"));
@ -214,7 +219,14 @@ void SleighBase::restoreXml(const Element *el)
s3.unsetf(ios::dec | ios::hex | ios::oct);
s3 >> numSections;
}
else if (attrname == "version") {
istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> version;
}
}
if (version != SLA_FORMAT_VERSION)
throw LowlevelError(".sla file has wrong format");
const List &list(el->getChildren());
List::const_iterator iter;
iter = list.begin();

View file

@ -27,6 +27,7 @@
/// - Reading the various SLEIGH specification files
/// - Building and writing out SLEIGH specification files
class SleighBase : public Translate {
static const int4 SLA_FORMAT_VERSION; ///< Current version of the .sla file read/written by SleighBash
vector<string> userop; ///< Names of user-define p-code ops for \b this Translate object
map<VarnodeData,string> varnode_xref; ///< A map from Varnodes in the \e register space to register names
protected:

View file

@ -1476,9 +1476,13 @@ void SleighCompile::predefinedSymbols(void)
// Some predefined symbols
root = new SubtableSymbol("instruction"); // Base constructors
symtab.addSymbol(root);
insertSpace(new ConstantSpace(this,this,"const",0));
insertSpace(new ConstantSpace(this,this,"const",AddrSpace::constant_space_index));
SpaceSymbol *spacesym = new SpaceSymbol(getConstantSpace()); // Constant space
symtab.addSymbol(spacesym);
OtherSpace *otherSpace = new OtherSpace(this,this,"OTHER",AddrSpace::other_space_index);
insertSpace(otherSpace);
spacesym = new SpaceSymbol(otherSpace);
symtab.addSymbol(spacesym);
insertSpace(new UniqueSpace(this,this,"unique",numSpaces(),0));
spacesym = new SpaceSymbol(getUniqueSpace()); // Temporary register space
symtab.addSymbol(spacesym);

View file

@ -24,14 +24,6 @@ void AddrSpace::calcScaleMask(void)
highest = highest * wordsize + (wordsize-1); // Maximum byte address
}
/// Called once during initialization to assign a single character shortcut for the space
/// The character is used as a shorthand when typing addresses on the console command line
void AddrSpace::assignShortcut(void)
{
shortcut = manage->assignShortcut(type);
}
/// Initialize an address space with its basic attributes
/// \param m is the space manager associated with the new space
/// \param t is the processor translator associated with the new space
@ -55,6 +47,7 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp,const s
index = ind;
delay = dl;
deadcodedelay = dl; // Deadcode delay initially starts the same as heritage delay
shortcut = ' '; // Placeholder meaning shortcut is unassigned
// These are the flags we allow to be set from constructor
flags = (fl & hasphysical);
@ -63,7 +56,6 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp,const s
flags |= (heritaged | does_deadcode); // Always on unless explicitly turned off in derived constructor
calcScaleMask();
assignShortcut();
}
/// This is a partial constructor, for initializing a space
@ -80,6 +72,7 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp)
type = tp;
flags = (heritaged | does_deadcode); // Always on unless explicitly turned off in derived constructor
wordsize = 1;
shortcut = ' ';
// We let big_endian get set by attribute
}
@ -349,7 +342,6 @@ void AddrSpace::restoreXml(const Element *el)
if (deadcodedelay == -1)
deadcodedelay = delay; // If deadcodedelay attribute not present, set it to delay
calcScaleMask();
assignShortcut();
}
/// This constructs the unique constant space
@ -392,6 +384,42 @@ void ConstantSpace::restoreXml(const Element *el)
throw LowlevelError("Should never restore the constant space from XML");
}
/// Construct the \b other space, which is automatically constructed
/// by the compiler, and is only constructed once. The name should
/// always by \b OTHER.
/// \param m is the associated address space manager
/// \param t is the associated processor translator
/// \param nm is the name of the space
/// \param ind is the integer identifier
OtherSpace::OtherSpace(AddrSpaceManager *m,const Translate *t,
const string &nm,int4 ind)
: AddrSpace(m,t,IPTR_PROCESSOR,nm,sizeof(uintb),1,ind,0,0)
{
clearFlags(heritaged|does_deadcode);
setFlags(is_otherspace);
}
OtherSpace::OtherSpace(AddrSpaceManager *m,const Translate *t)
: AddrSpace(m,t,IPTR_PROCESSOR)
{
clearFlags(heritaged|does_deadcode);
setFlags(is_otherspace);
}
void OtherSpace::printRaw(ostream &s,uintb offset) const
{
s << "0x" << hex << offset;
}
void OtherSpace::saveXml(ostream &s) const
{
s << "<space_other";
saveBasicAttributes(s);
s << "/>\n";
}
/// This is the constructor for the \b unique space, which is
/// automatically constructed by the analysis engine, and
/// constructed only once. The name should always be \b unique.
@ -653,7 +681,6 @@ void OverlaySpace::restoreXml(const Element *el)
delay = baseSpace->getDelay();
deadcodedelay = baseSpace->getDeadcodeDelay();
calcScaleMask();
assignShortcut();
if (baseSpace->isBigEndian())
setFlags(big_endian);

View file

@ -82,7 +82,12 @@ public:
overlay = 32, ///< This space is an overlay of another space
overlaybase = 64, ///< This is the base space for overlay space(s)
truncated = 128, ///< Space is truncated from its original size, expect pointers larger than this size
hasphysical = 256 ///< Has physical memory associated with it
hasphysical = 256, ///< Has physical memory associated with it
is_otherspace = 512 ///< Quick check for the OtherSpace derived class
};
enum {
constant_space_index = 0, ///< Reserved index for the constant space
other_space_index = 1 ///< Reserved index for the other space
};
private:
spacetype type; ///< Type of space (PROCESSOR, CONSTANT, INTERNAL, ...)
@ -100,7 +105,6 @@ protected:
int4 delay; ///< Delay in heritaging this space
int4 deadcodedelay; ///< Delay before deadcode removal is allowed on this space
void calcScaleMask(void); ///< Calculate scale and mask
void assignShortcut(void); ///< Assign a shortcut character to the space
void setFlags(uint4 fl); ///< Set a cached attribute
void clearFlags(uint4 fl); ///< Clear a cached attribute
void saveBasicAttributes(ostream &s) const; ///< Write the XML attributes of this space
@ -128,6 +132,7 @@ public:
bool isReverseJustified(void) const; ///< Return \b true if alignment justification does not match endianness
bool isOverlay(void) const; ///< Return \b true if this is an overlay space
bool isOverlayBase(void) const; ///< Return \b true if other spaces overlay this space
bool isOtherSpace(void) const; ///< Return \b true if \b this is the \e other address space
bool isTruncated(void) const; ///< Return \b true if this space is truncated from its original size
void printOffset(ostream &s,uintb offset) const; ///< Write an address offset to a stream
@ -170,6 +175,15 @@ public:
virtual void restoreXml(const Element *el);
};
/// \brief Special AddrSpace for special/user-defined address spaces
class OtherSpace : public AddrSpace {
public:
OtherSpace(AddrSpaceManager *m, const Translate *t, const string &nm, int4 ind); ///< Constructor
OtherSpace(AddrSpaceManager *m, const Translate *t); ///< For use with restoreXml
virtual void printRaw(ostream &s, uintb offset) const;
virtual void saveXml(ostream &s) const;
};
/// \brief The pool of temporary storage registers
///
/// It is convenient both for modelling processor instructions
@ -181,7 +195,7 @@ public:
/// \b unique.
class UniqueSpace : public AddrSpace {
public:
UniqueSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,uint4 fl);
UniqueSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,uint4 fl); ///< Constructor
UniqueSpace(AddrSpaceManager *m,const Translate *t); ///< For use with restoreXml
virtual void saveXml(ostream &s) const;
};
@ -392,6 +406,10 @@ inline bool AddrSpace::isOverlayBase(void) const {
return ((flags&overlaybase)!=0);
}
inline bool AddrSpace::isOtherSpace(void) const {
return ((flags&is_otherspace)!=0);
}
/// If this method returns \b true, the logical form of this space is truncated from its actual size
/// Pointers may refer to this original size put the most significant bytes are ignored
inline bool AddrSpace::isTruncated(void) const {

View file

@ -170,6 +170,8 @@ AddrSpace *AddrSpaceManager::restoreXmlSpace(const Element *el,const Translate *
res = new SpacebaseSpace(this,trans);
else if (tp == "space_unique")
res = new UniqueSpace(this,trans);
else if (tp == "space_other")
res = new OtherSpace(this,trans);
else if (tp == "space_overlay")
res = new OverlaySpace(this,trans);
else
@ -191,7 +193,7 @@ void AddrSpaceManager::restoreXmlSpaces(const Element *el,const Translate *trans
{
// The first space should always be the constant space
insertSpace(new ConstantSpace(this,trans,"const",0));
insertSpace(new ConstantSpace(this,trans,"const",AddrSpace::constant_space_index));
string defname(el->getAttributeValue("defaultspace"));
const List &list(el->getChildren());
@ -203,6 +205,8 @@ void AddrSpaceManager::restoreXmlSpaces(const Element *el,const Translate *trans
++iter;
}
AddrSpace *spc = getSpaceByName(defname);
if (spc == (AddrSpace *)0)
throw LowlevelError("Bad 'defaultspace' attribute: "+defname);
setDefaultSpace(spc->getIndex());
}
@ -217,7 +221,7 @@ void AddrSpaceManager::setDefaultSpace(int4 index)
{
if (defaultspace != (AddrSpace *)0)
throw LowlevelError("Default space set multiple times");
if (baselist.size()<=index)
if (baselist.size()<=index || baselist[index] == (AddrSpace *)0)
throw LowlevelError("Bad index for default space");
defaultspace = baselist[index];
}
@ -244,48 +248,49 @@ void AddrSpaceManager::setReverseJustified(AddrSpace *spc)
void AddrSpaceManager::insertSpace(AddrSpace *spc)
{
bool nametype_mismatch = false;
bool duplicatedefine = false;
bool nameTypeMismatch = false;
bool duplicateName = false;
bool duplicateId = false;
switch(spc->getType()) {
case IPTR_CONSTANT:
if (spc->getName() != "const")
nametype_mismatch = true;
if (baselist.size()!=0)
throw LowlevelError("const space must be initialized first");
nameTypeMismatch = true;
if (spc->index != AddrSpace::constant_space_index)
throw LowlevelError("const space must be assigned index 0");
constantspace = spc;
break;
case IPTR_INTERNAL:
if (spc->getName() != "unique")
nametype_mismatch = true;
nameTypeMismatch = true;
if (uniqspace != (AddrSpace *)0)
duplicatedefine = true;
duplicateName = true;
uniqspace = spc;
break;
case IPTR_FSPEC:
if (spc->getName() != "fspec")
nametype_mismatch = true;
nameTypeMismatch = true;
if (fspecspace != (AddrSpace *)0)
duplicatedefine = true;
duplicateName = true;
fspecspace = spc;
break;
case IPTR_JOIN:
if (spc->getName() != "join")
nametype_mismatch = true;
nameTypeMismatch = true;
if (joinspace != (AddrSpace *)0)
duplicatedefine = true;
duplicateName = true;
joinspace = spc;
break;
case IPTR_IOP:
if (spc->getName() != "iop")
nametype_mismatch = true;
nameTypeMismatch = true;
if (iopspace != (AddrSpace *)0)
duplicatedefine = true;
duplicateName = true;
iopspace = spc;
break;
case IPTR_SPACEBASE:
if (spc->getName() == "stack") {
if (stackspace != (AddrSpace *)0)
duplicatedefine = true;
duplicateName = true;
stackspace = spc;
}
// fallthru
@ -294,19 +299,36 @@ void AddrSpaceManager::insertSpace(AddrSpace *spc)
OverlaySpace *ospc = (OverlaySpace *)spc;
ospc->getBaseSpace()->setFlags(AddrSpace::overlaybase); // Mark the base as being overlayed
}
for(uint4 i=0;i<baselist.size();++i)
if (baselist[i]->getName() == spc->getName())
duplicatedefine = true;
else if (spc->isOtherSpace()) {
if (spc->index != AddrSpace::other_space_index)
throw LowlevelError("OTHER space must be assigned index 1");
}
break;
}
if (nametype_mismatch)
if (baselist.size() <= spc->index)
baselist.resize(spc->index+1, (AddrSpace *)0);
duplicateId = baselist[spc->index] != (AddrSpace *)0;
if (!nameTypeMismatch && !duplicateName && !duplicateId) {
duplicateName = !name2Space.insert(pair<string,AddrSpace *>(spc->getName(),spc)).second;
}
if (nameTypeMismatch || duplicateName || duplicateId) {
if (spc->refcount == 0)
delete spc;
spc = (AddrSpace *)0;
}
if (nameTypeMismatch)
throw LowlevelError("Space "+spc->getName()+" was initialized with wrong type");
if (duplicatedefine)
if (duplicateName)
throw LowlevelError("Space "+spc->getName()+" was initialized more than once");
if (baselist.size() != spc->getIndex())
throw LowlevelError("Space "+spc->getName()+" was initialized with a bad id");
baselist.push_back(spc);
if (duplicateId)
throw LowlevelError("Space "+spc->getName()+" was assigned as id duplicating: "+baselist[spc->index]->getName());
baselist[spc->index] = spc;
spc->refcount += 1;
assignShortcut(spc);
}
/// Different managers may need to share the same spaces. I.e. if different programs being
@ -316,8 +338,11 @@ void AddrSpaceManager::insertSpace(AddrSpace *spc)
void AddrSpaceManager::copySpaces(const AddrSpaceManager *op2)
{ // Insert every space in -op2- into -this- manager
for(int4 i=0;i<op2->baselist.size();++i)
insertSpace(op2->baselist[i]);
for(int4 i=0;i<op2->baselist.size();++i) {
AddrSpace *spc = op2->baselist[i];
if (spc != (AddrSpace *)0)
insertSpace(spc);
}
setDefaultSpace(op2->getDefaultSpace()->getIndex());
}
@ -353,6 +378,7 @@ AddrSpaceManager::~AddrSpaceManager(void)
{
for(vector<AddrSpace *>::iterator iter=baselist.begin();iter!=baselist.end();++iter) {
AddrSpace *spc = *iter;
if (spc == (AddrSpace *)0) continue;
if (spc->refcount > 1)
spc->refcount -= 1;
else
@ -366,24 +392,29 @@ AddrSpaceManager::~AddrSpaceManager(void)
delete splitlist[i]; // Delete any join records
}
/// Assign a \e shortcut character to an address space
/// Assign a \e shortcut character to the given address space.
/// This routine makes use of the desired type of the new space
/// and info about shortcuts for spaces that already exist to
/// pick a unique and consistent character.
/// This is currently invoked by the AddrSpace initialization
/// process.
/// \param tp is the type of the new space
/// \return the shortcut character
char AddrSpaceManager::assignShortcut(spacetype tp) const
/// pick a unique and consistent character. This method also builds
/// up a map from short to AddrSpace object.
/// \param spc is the given AddrSpace
void AddrSpaceManager::assignShortcut(AddrSpace *spc)
{
char shortcut = 'x';
switch(tp) {
if (spc->shortcut != ' ') { // If the shortcut is already assigned
shortcut2Space.insert(pair<int4,AddrSpace *>(spc->shortcut,spc));
return;
}
char shortcut;
switch(spc->getType()) {
case IPTR_CONSTANT:
shortcut = '#';
break;
case IPTR_PROCESSOR:
shortcut = 'r';
if (spc->getName() == "register")
shortcut = '%';
else
shortcut = spc->getName()[0];
break;
case IPTR_SPACEBASE:
shortcut = 's';
@ -400,25 +431,29 @@ char AddrSpaceManager::assignShortcut(spacetype tp) const
case IPTR_IOP:
shortcut = 'i';
break;
default:
shortcut = 'x';
break;
}
// if ((shortcut >= 'A') && (shortcut <= 'R'))
// shortcut |= 0x20;
for(int4 i=0x61;i<0x7a;++i) {
int4 j;
for(j=0;j<baselist.size();++j) {
if (baselist[j]->getShortcut() == shortcut)
break;
if (shortcut >= 'A' && shortcut <= 'Z')
shortcut += 0x20;
int4 collisionCount = 0;
while(!shortcut2Space.insert(pair<int4,AddrSpace *>(shortcut,spc)).second) {
collisionCount += 1;
if (collisionCount >26) {
// Could not find a unique shortcut, but we just re-use 'z' as we
// can always use the long form to specify the address if there are really so many
// spaces that need to be distinguishable (in the console mode)
spc->shortcut = 'z';
return;
}
if (j == baselist.size()) return shortcut; // Found an open shortcut
shortcut = (char) i;
if (shortcut == 'a')
shortcut = '%'; // Second processor space is usually the register space
shortcut += 1;
if (shortcut < 'a' || shortcut > 'z')
shortcut = 'a';
}
// Could not find a unique shortcut, but we just re-use 'z' as we
// can always use the long form to specify the address if there are really so many
// spaces that need to be distinguishable (in the console mode)
return shortcut;
spc->shortcut = (char)shortcut;
}
/// All address spaces have a unique name associated with them.
@ -429,10 +464,10 @@ char AddrSpaceManager::assignShortcut(spacetype tp) const
AddrSpace *AddrSpaceManager::getSpaceByName(const string &nm) const
{
for(int4 i=0;i<baselist.size();++i)
if (baselist[i]->getName() == nm)
return baselist[i];
return (AddrSpace *)0;
map<string,AddrSpace *>::const_iterator iter = name2Space.find(nm);
if (iter == name2Space.end())
return (AddrSpace *)0;
return (*iter).second;
}
/// All address spaces have a unique shortcut (ASCII) character
@ -443,10 +478,11 @@ AddrSpace *AddrSpaceManager::getSpaceByName(const string &nm) const
AddrSpace *AddrSpaceManager::getSpaceByShortcut(char sc) const
{
for(int4 i=0;i<baselist.size();++i)
if (baselist[i]->getShortcut() == sc)
return baselist[i];
return (AddrSpace *)0;
map<int4,AddrSpace *>::const_iterator iter;
iter = shortcut2Space.find(sc);
if (iter == shortcut2Space.end())
return (AddrSpace *)0;
return (*iter).second;
}
Address AddrSpaceManager::resolveConstant(AddrSpace *spc,uintb val,int4 sz,const Address &point) const
@ -475,9 +511,12 @@ AddrSpace *AddrSpaceManager::getNextSpaceInOrder(AddrSpace *spc) const
if (spc == (AddrSpace *) ~((uintp)0)) {
return (AddrSpace *)0;
}
int4 index = spc->getIndex();
if (index < baselist.size()-1) {
return baselist[index+1];
int4 index = spc->getIndex() + 1;
while (index < baselist.size()) {
AddrSpace *res = baselist[index];
if (res != (AddrSpace *)0)
return res;
index += 1;
}
return (AddrSpace *) ~((uintp)0);
}
@ -558,12 +597,12 @@ JoinRecord *AddrSpaceManager::findJoin(uintb offset) const
/// Set the number of passes for a specific AddrSpace before deadcode removal is allowed
/// for that space.
/// \param spcnum is the index of the AddrSpace to change
/// \param spc is the AddrSpace to change
/// \param delaydelta is the number of rounds to the delay should be set to
void AddrSpaceManager::setDeadcodeDelay(int4 spcnum,int4 delaydelta)
void AddrSpaceManager::setDeadcodeDelay(AddrSpace *spc,int4 delaydelta)
{
baselist[spcnum]->deadcodedelay = delaydelta;
spc->deadcodedelay = delaydelta;
}
/// Mark the named space as truncated from its original size

View file

@ -212,6 +212,8 @@ struct JoinRecordCompare {
class AddrSpaceManager {
vector<AddrSpace *> baselist; ///< Every space we know about for this architecture
vector<AddressResolver *> resolvelist; ///< Special constant resolvers
map<string,AddrSpace *> name2Space; ///< Map from name -> space
map<int4,AddrSpace *> shortcut2Space; ///< Map from shortcut -> space
AddrSpace *constantspace; ///< Quick reference to constant space
AddrSpace *defaultspace; ///< Generally primary RAM, where assembly pointers point to
AddrSpace *iopspace; ///< Space for internal pcode op pointers
@ -227,6 +229,7 @@ protected:
void restoreXmlSpaces(const Element *el,const Translate *trans); ///< Restore address spaces in the model from an XML tag
void setDefaultSpace(int4 index); ///< Set the default address space
void setReverseJustified(AddrSpace *spc); ///< Set reverse justified property on this space
void assignShortcut(AddrSpace *spc); ///< Select a shortcut character for a new space
void insertSpace(AddrSpace *spc); ///< Add a new address space to the model
void copySpaces(const AddrSpaceManager *op2); ///< Copy spaces from another manager
void addSpacebasePointer(SpacebaseSpace *basespace,const VarnodeData &ptrdata,int4 truncSize,bool stackGrowth); ///< Set the base register of a spacebase space
@ -234,7 +237,6 @@ protected:
public:
AddrSpaceManager(void); ///< Construct an empty address space manager
virtual ~AddrSpaceManager(void); ///< Destroy the manager
char assignShortcut(spacetype tp) const; ///< Select a shortcut character for a new space
int4 getDefaultSize(void) const; ///< Get size of addresses for the default space
AddrSpace *getSpaceByName(const string &nm) const; ///< Get address space by name
AddrSpace *getSpaceByShortcut(char sc) const; ///< Get address space from its shortcut
@ -253,7 +255,7 @@ public:
AddrSpace *getNextSpaceInOrder(AddrSpace *spc) const; ///< Get the next \e contiguous address space
JoinRecord *findAddJoin(const vector<VarnodeData> &pieces,uint4 logicalsize); ///< Get (or create) JoinRecord for \e pieces
JoinRecord *findJoin(uintb offset) const; ///< Find JoinRecord for \e offset in the join space
void setDeadcodeDelay(int4 spcnum,int4 delaydelta); ///< Set the deadcodedelay for a specific space
void setDeadcodeDelay(AddrSpace *spc,int4 delaydelta); ///< Set the deadcodedelay for a specific space
void truncateSpace(const TruncationTag &tag); ///< Mark a space as truncated from its original size
/// \brief Build a logically lower precision storage location for a bigger floating point register