Allow constant pointer inference into multiple address spaces

This commit is contained in:
caheckman 2019-12-19 17:32:07 -05:00
parent b5e2efff77
commit 2e80935edb
12 changed files with 181 additions and 30 deletions

View file

@ -94,7 +94,6 @@ Architecture::Architecture(void)
aggressive_ext_trim = false; aggressive_ext_trim = false;
readonlypropagate = false; readonlypropagate = false;
infer_pointers = true; infer_pointers = true;
pointer_lowerbound = 0x1000;
funcptr_align = 0; funcptr_align = 0;
flowoptions = 0; flowoptions = 0;
defaultfp = (ProtoModel *)0; defaultfp = (ProtoModel *)0;
@ -306,21 +305,19 @@ void Architecture::collectBehaviors(vector<OpBehavior *> &behave) const
} }
} }
/// A \b near pointer is some form of truncated pointer that needs
/// \e segment or other information to fully form an address.
/// This method searches for a user-defined segment op registered /// This method searches for a user-defined segment op registered
/// for the space /// for the given space.
/// \param spc is the address space to check /// \param spc is the address space to check
/// \return true if the space supports a segment operation /// \return the SegmentOp object or null
bool Architecture::hasNearPointers(AddrSpace *spc) const SegmentOp *Architecture::getSegmentOp(AddrSpace *spc) const
{ {
if (spc->getIndex() >= userops.numSegmentOps()) return false; if (spc->getIndex() >= userops.numSegmentOps()) return (SegmentOp *)0;
SegmentOp *segdef = userops.getSegmentOp(spc->getIndex()); SegmentOp *segdef = userops.getSegmentOp(spc->getIndex());
if (segdef == (SegmentOp *)0) return false; if (segdef == (SegmentOp *)0) return (SegmentOp *)0;
if (segdef->getResolve().space != (AddrSpace *)0) if (segdef->getResolve().space != (AddrSpace *)0)
return true; return segdef;
return false; return (SegmentOp *)0;
} }
/// Establish details of the prototype for a given function symbol /// Establish details of the prototype for a given function symbol
@ -601,6 +598,12 @@ void Architecture::buildInstructions(DocumentStorage &store)
TypeOp::registerInstructions(inst,types,translate); TypeOp::registerInstructions(inst,types,translate);
} }
void Architecture::postSpecFile(void)
{
cacheAddrSpaceProperties();
}
/// Once the processor is known, the Translate object can be built and /// Once the processor is known, the Translate object can be built and
/// fully initialized. Processor and compiler specific configuration is performed /// fully initialized. Processor and compiler specific configuration is performed
/// \param store will hold parsed configuration information /// \param store will hold parsed configuration information
@ -615,8 +618,6 @@ void Architecture::restoreFromSpec(DocumentStorage &store)
insertSpace( new FspecSpace(this,translate,"fspec",numSpaces())); insertSpace( new FspecSpace(this,translate,"fspec",numSpaces()));
insertSpace( new IopSpace(this,translate,"iop",numSpaces())); insertSpace( new IopSpace(this,translate,"iop",numSpaces()));
insertSpace( new JoinSpace(this,translate,"join",numSpaces())); insertSpace( new JoinSpace(this,translate,"join",numSpaces()));
if (translate->getDefaultSize() < 3) // For small architectures
pointer_lowerbound = 0x100; // assume constants are pointers starting at a much lower bound
userops.initialize(this); userops.initialize(this);
if (translate->getAlignment() <= 8) if (translate->getAlignment() <= 8)
min_funcsymbol_size = translate->getAlignment(); min_funcsymbol_size = translate->getAlignment();
@ -642,6 +643,48 @@ void Architecture::initializeSegments(void)
} }
} }
/// Determine the minimum pointer size for the space and whether or not there are near pointers.
/// Set up an ordered list of inferable spaces (where constant pointers can be infered).
/// Inferable spaces include the default space and anything explicitly listed
/// in the cspec \<global> tag that is not a register space. An initial list of potential spaces is
/// passed in that needs to be ordered, filtered, and deduplicated.
void Architecture::cacheAddrSpaceProperties(void)
{
vector<AddrSpace *> copyList = inferPtrSpaces;
copyList.push_back(getDefaultSpace()); // Make sure the default space is their
inferPtrSpaces.clear();
sort(copyList.begin(),copyList.end(),AddrSpace::compareByIndex);
AddrSpace *lastSpace = (AddrSpace *)0;
for(int4 i=0;i<copyList.size();++i) {
AddrSpace *spc = copyList[i];
if (spc == lastSpace) continue;
lastSpace = spc;
if (spc->getDelay() == 0) continue; // Don't put in a register space
if (spc->getType() == IPTR_SPACEBASE) continue;
if (spc->isOtherSpace()) continue;
if (spc->isOverlay()) continue;
inferPtrSpaces.push_back(spc);
}
int4 defPos = -1;
for(int4 i=0;i<inferPtrSpaces.size();++i) {
AddrSpace *spc = inferPtrSpaces[i];
if (spc == getDefaultSpace())
defPos = i;
SegmentOp *segOp = getSegmentOp(spc);
if (segOp != (SegmentOp *)0) {
int4 val = segOp->getInnerSize();
markNearPointers(spc, val);
}
}
if (defPos > 0) { // Make sure the default space comes first
AddrSpace *tmp = inferPtrSpaces[0];
inferPtrSpaces[0] = inferPtrSpaces[defPos];
inferPtrSpaces[defPos] = tmp;
}
}
/// Recover information out of a \<rule> tag and build the new Rule object. /// Recover information out of a \<rule> tag and build the new Rule object.
/// \param el is the XML element /// \param el is the XML element
void Architecture::parseDynamicRule(const Element *el) void Architecture::parseDynamicRule(const Element *el)
@ -749,7 +792,9 @@ void Architecture::parseGlobal(const Element *el)
for(iter=list.begin();iter!=list.end();++iter) { for(iter=list.begin();iter!=list.end();++iter) {
Range range; Range range;
range.restoreXml(*iter,this); range.restoreXml(*iter,this);
symboltab->addRange(scope,range.getSpace(),range.getFirst(),range.getLast()); AddrSpace *spc = range.getSpace();
inferPtrSpaces.push_back(spc);
symboltab->addRange(scope,spc,range.getFirst(),range.getLast());
if (range.getSpace()->isOverlayBase()) { // If the address space is overlayed if (range.getSpace()->isOverlayBase()) { // If the address space is overlayed
// We need to duplicate the range being marked as global into the overlay space(s) // We need to duplicate the range being marked as global into the overlay space(s)
int4 num = numSpaces(); int4 num = numSpaces();

View file

@ -127,7 +127,7 @@ public:
bool aggressive_ext_trim; ///< Aggressively trim inputs that look like they are sign extended bool aggressive_ext_trim; ///< Aggressively trim inputs that look like they are sign extended
bool readonlypropagate; ///< true if readonly values should be treated as constants bool readonlypropagate; ///< true if readonly values should be treated as constants
bool infer_pointers; ///< True if we should infer pointers from constants that are likely addresses bool infer_pointers; ///< True if we should infer pointers from constants that are likely addresses
uintb pointer_lowerbound; ///< Zero or lowest value that can be inferred as an address vector<AddrSpace *> inferPtrSpaces; ///< Set of address spaces in which a pointer constant is inferable
int4 funcptr_align; ///< How many bits of alignment a function ptr has int4 funcptr_align; ///< How many bits of alignment a function ptr has
uint4 flowoptions; ///< options passed to flow following engine uint4 flowoptions; ///< options passed to flow following engine
vector<Rule *> extra_pool_rules; ///< Extra rules that go in the main pool (cpu specific, experimental) vector<Rule *> extra_pool_rules; ///< Extra rules that go in the main pool (cpu specific, experimental)
@ -173,7 +173,7 @@ public:
void clearAnalysis(Funcdata *fd); ///< Clear analysis specific to a function void clearAnalysis(Funcdata *fd); ///< Clear analysis specific to a function
void readLoaderSymbols(void); ///< Read any symbols from loader into database void readLoaderSymbols(void); ///< Read any symbols from loader into database
void collectBehaviors(vector<OpBehavior *> &behave) const; ///< Provide a list of OpBehavior objects void collectBehaviors(vector<OpBehavior *> &behave) const; ///< Provide a list of OpBehavior objects
bool hasNearPointers(AddrSpace *spc) const; ///< Does the given address space support \e near pointers SegmentOp *getSegmentOp(AddrSpace *spc) const; ///< Retrieve the \e segment op for the given space if any
void setPrototype(const PrototypePieces &pieces); ///< Set the prototype for a particular function void setPrototype(const PrototypePieces &pieces); ///< Set the prototype for a particular function
void setPrintLanguage(const string &nm); ///< Establish a particular output language void setPrintLanguage(const string &nm); ///< Establish a particular output language
void globalify(void); ///< Mark \e all spaces as global void globalify(void); ///< Mark \e all spaces as global
@ -241,14 +241,14 @@ protected:
/// \param trans is the processor disassembly object /// \param trans is the processor disassembly object
virtual void modifySpaces(Translate *trans)=0; virtual void modifySpaces(Translate *trans)=0;
virtual void postSpecFile(void) {} ///< Let components initialize after Translate is built virtual void postSpecFile(void); ///< Let components initialize after Translate is built
virtual void resolveArchitecture(void)=0; ///< Figure out the processor and compiler of the target executable virtual void resolveArchitecture(void)=0; ///< Figure out the processor and compiler of the target executable
void restoreFromSpec(DocumentStorage &store); ///< Fully initialize the Translate object void restoreFromSpec(DocumentStorage &store); ///< Fully initialize the Translate object
void fillinReadOnlyFromLoader(void); ///< Load info about read-only sections void fillinReadOnlyFromLoader(void); ///< Load info about read-only sections
void initializeSegments(); ///< Set up segment resolvers void initializeSegments(); ///< Set up segment resolvers
void cacheAddrSpaceProperties(void); ///< Calculate some frequently used space properties and cache them
void parseProcessorConfig(DocumentStorage &store); ///< Apply processor specific configuration void parseProcessorConfig(DocumentStorage &store); ///< Apply processor specific configuration
void parseCompilerConfig(DocumentStorage &store); ///< Apply compiler specific configuration void parseCompilerConfig(DocumentStorage &store); ///< Apply compiler specific configuration

View file

@ -111,6 +111,7 @@ void BfdArchitecture::resolveArchitecture(void)
void BfdArchitecture::postSpecFile(void) void BfdArchitecture::postSpecFile(void)
{ // Attach default space to loader { // Attach default space to loader
Architecture::postSpecFile();
((LoadImageBfd *)loader)->attachToSpace(getDefaultSpace()); ((LoadImageBfd *)loader)->attachToSpace(getDefaultSpace());
} }

View file

@ -934,6 +934,66 @@ int4 ActionShadowVar::apply(Funcdata &data)
return 0; return 0;
} }
/// \brief Make a limited search for a LOAD or STORE so we can see the AddrSpace being accessed
///
/// We traverse forward through the given PcodeOp, through INT_ADD, INDIRECT, COPY, and MULTIEQUAL
/// until we hit a LOAD or STORE.
/// \param op is the given PcodeOp to start the search from
/// \return the discovered AddrSpace or null
AddrSpace *ActionConstantPtr::searchForLoadStore(PcodeOp *op)
{
for(int4 i=0;i<3;++i) {
switch(op->code()) {
case CPUI_INT_ADD:
case CPUI_COPY:
case CPUI_INDIRECT:
case CPUI_MULTIEQUAL:
op = op->getOut()->loneDescend();
break;
case CPUI_LOAD:
case CPUI_STORE:
return Address::getSpaceFromConst(op->getIn(0)->getAddr());
default:
return (AddrSpace *)0;
}
if (op == (PcodeOp *)0) break;
}
return (AddrSpace *)0;
}
/// \brief Select the AddrSpace in which we infer with the given constant is a pointer
///
/// The constant must match the AddrSpace address size. If there is more than one possible match,
/// search for more information in the syntax tree.
/// \param vn is the given constant Varnode
/// \param op is the PcodeOp which uses the constant
/// \param spaceList is the list of address spaces to select from
/// \return the selected address space or null
AddrSpace *ActionConstantPtr::selectInferSpace(Varnode *vn,PcodeOp *op,const vector<AddrSpace *> &spaceList)
{
AddrSpace *resSpace = (AddrSpace *)0;
for(int4 i=0;i<spaceList.size();++i) {
AddrSpace *spc = spaceList[i];
int4 minSize = spc->getMinimumPtrSize();
if (minSize == 0) {
if (vn->getSize() != spc->getAddrSize())
continue;
}
else if (vn->getSize() < minSize)
continue;
if (resSpace != (AddrSpace *)0) {
AddrSpace *searchSpc = searchForLoadStore(op);
if (searchSpc != (AddrSpace *)0)
resSpace = searchSpc;
break;
}
resSpace = spc;
}
return resSpace;
}
/// \brief Determine if given Varnode might be a pointer constant. /// \brief Determine if given Varnode might be a pointer constant.
/// ///
/// If it is a pointer, return the symbol it points to, or NULL otherwise. If it is determined /// If it is a pointer, return the symbol it points to, or NULL otherwise. If it is determined
@ -1001,7 +1061,7 @@ SymbolEntry *ActionConstantPtr::isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op
return (SymbolEntry *)0; return (SymbolEntry *)0;
} }
// Make sure the constant is in the expected range for a pointer // Make sure the constant is in the expected range for a pointer
if ((glb->pointer_lowerbound != 0)&&(glb->pointer_lowerbound > vn->getOffset())) if (spc->getPointerLowerBound() > vn->getOffset())
return (SymbolEntry *)0; return (SymbolEntry *)0;
// Check if the constant looks like a single bit or mask // Check if the constant looks like a single bit or mask
if (bit_transitions(vn->getOffset(),vn->getSize()) < 3) if (bit_transitions(vn->getOffset(),vn->getSize()) < 3)
@ -1032,13 +1092,8 @@ int4 ActionConstantPtr::apply(Funcdata &data)
VarnodeLocSet::const_iterator begiter,enditer; VarnodeLocSet::const_iterator begiter,enditer;
Architecture *glb = data.getArch(); Architecture *glb = data.getArch();
AddrSpace *cspc = glb->getConstantSpace(); AddrSpace *cspc = glb->getConstantSpace();
AddrSpace *rspc = glb->getDefaultSpace();
SymbolEntry *entry; SymbolEntry *entry;
Varnode *vn; Varnode *vn;
bool arenearpointers = glb->hasNearPointers(rspc);
int4 minsize = rspc->isTruncated() ? rspc->getAddrSize() : 0;
if (minsize > 0)
arenearpointers = true;
begiter = data.beginLoc(cspc); begiter = data.beginLoc(cspc);
enditer = data.endLoc(cspc); enditer = data.endLoc(cspc);
@ -1054,12 +1109,8 @@ int4 ActionConstantPtr::apply(Funcdata &data)
PcodeOp *op = vn->loneDescend(); PcodeOp *op = vn->loneDescend();
if (op == (PcodeOp *)0) continue; if (op == (PcodeOp *)0) continue;
if (arenearpointers) { AddrSpace *rspc = selectInferSpace(vn, op, glb->inferPtrSpaces);
if (vn->getSize() < minsize) continue; if (rspc == (AddrSpace *)0) continue;
}
else {
if (vn->getSize() != rspc->getAddrSize()) continue;
}
int4 slot = op->getSlot(vn); int4 slot = op->getSlot(vn);
OpCode opc = op->code(); OpCode opc = op->code();
if (opc == CPUI_INT_ADD) { if (opc == CPUI_INT_ADD) {

View file

@ -180,6 +180,8 @@ public:
/// \brief Check for constants, with pointer type, that correspond to global symbols /// \brief Check for constants, with pointer type, that correspond to global symbols
class ActionConstantPtr : public Action { class ActionConstantPtr : public Action {
int4 localcount; ///< Number of passes made for this function int4 localcount; ///< Number of passes made for this function
static AddrSpace *searchForLoadStore(PcodeOp *op);
static AddrSpace *selectInferSpace(Varnode *vn,PcodeOp *op,const vector<AddrSpace *> &spaceList);
static SymbolEntry *isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op,int4 slot, static SymbolEntry *isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op,int4 slot,
Address &rampoint,uintb &fullEncoding,Funcdata &data); Address &rampoint,uintb &fullEncoding,Funcdata &data);
public: public:

View file

@ -273,6 +273,7 @@ void ArchitectureGhidra::buildSpecFile(DocumentStorage &store)
void ArchitectureGhidra::postSpecFile(void) void ArchitectureGhidra::postSpecFile(void)
{ {
Architecture::postSpecFile();
ScopeGhidra *scopeGhidra = (ScopeGhidra *)symboltab->getGlobalScope(); ScopeGhidra *scopeGhidra = (ScopeGhidra *)symboltab->getGlobalScope();
scopeGhidra->lockDefaultProperties(); scopeGhidra->lockDefaultProperties();
} }

View file

@ -71,6 +71,7 @@ void RawBinaryArchitecture::resolveArchitecture(void)
void RawBinaryArchitecture::postSpecFile(void) void RawBinaryArchitecture::postSpecFile(void)
{ {
Architecture::postSpecFile();
((RawLoadImage *)loader)->attachToSpace(getDefaultSpace()); // Attach default space to loader ((RawLoadImage *)loader)->attachToSpace(getDefaultSpace()); // Attach default space to loader
} }

View file

@ -17,9 +17,11 @@
#include "translate.hh" #include "translate.hh"
/// Calculate \e highest based on \e addressSize, and \e wordsize. /// Calculate \e highest based on \e addressSize, and \e wordsize.
/// This also calculates the default pointerLowerBound
void AddrSpace::calcScaleMask(void) void AddrSpace::calcScaleMask(void)
{ {
pointerLowerBound = (addressSize < 3) ? 0x100: 0x1000;
highest = calc_mask(addressSize); // Maximum address highest = calc_mask(addressSize); // Maximum address
highest = highest * wordsize + (wordsize-1); // Maximum byte address highest = highest * wordsize + (wordsize-1); // Maximum byte address
} }
@ -47,6 +49,7 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp,const s
index = ind; index = ind;
delay = dl; delay = dl;
deadcodedelay = dl; // Deadcode delay initially starts the same as heritage delay deadcodedelay = dl; // Deadcode delay initially starts the same as heritage delay
minimumPointerSize = 0; // (initially) assume pointers must match the space size exactly
shortcut = ' '; // Placeholder meaning shortcut is unassigned shortcut = ' '; // Placeholder meaning shortcut is unassigned
// These are the flags we allow to be set from constructor // These are the flags we allow to be set from constructor
@ -72,6 +75,7 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp)
type = tp; type = tp;
flags = (heritaged | does_deadcode); // Always on unless explicitly turned off in derived constructor flags = (heritaged | does_deadcode); // Always on unless explicitly turned off in derived constructor
wordsize = 1; wordsize = 1;
minimumPointerSize = 0;
shortcut = ' '; shortcut = ' ';
// We let big_endian get set by attribute // We let big_endian get set by attribute
} }
@ -102,6 +106,7 @@ void AddrSpace::truncateSpace(uint4 newsize)
{ {
setFlags(truncated); setFlags(truncated);
addressSize = newsize; addressSize = newsize;
minimumPointerSize = newsize;
calcScaleMask(); calcScaleMask();
} }

View file

@ -83,7 +83,8 @@ public:
overlaybase = 64, ///< This is the base space for overlay space(s) 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 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 is_otherspace = 512, ///< Quick check for the OtherSpace derived class
has_nearpointers = 0x400 ///< Does there exist near pointers into this space
}; };
enum { enum {
constant_space_index = 0, ///< Reserved index for the constant space constant_space_index = 0, ///< Reserved index for the constant space
@ -96,11 +97,13 @@ private:
int4 refcount; ///< Number of managers using this space int4 refcount; ///< Number of managers using this space
uint4 flags; ///< Attributes of the space uint4 flags; ///< Attributes of the space
uintb highest; ///< Highest (byte) offset into this space uintb highest; ///< Highest (byte) offset into this space
uintb pointerLowerBound; ///< Offset below which we don't search for pointers
char shortcut; ///< Shortcut character for printing char shortcut; ///< Shortcut character for printing
protected: protected:
string name; ///< Name of this space string name; ///< Name of this space
uint4 addressSize; ///< Size of an address into this space in bytes uint4 addressSize; ///< Size of an address into this space in bytes
uint4 wordsize; ///< Size of unit being addressed (1=byte) uint4 wordsize; ///< Size of unit being addressed (1=byte)
int4 minimumPointerSize; ///< Smallest size of a pointer into \b this space (in bytes)
int4 index; ///< An integer identifier for the space int4 index; ///< An integer identifier for the space
int4 delay; ///< Delay in heritaging this space int4 delay; ///< Delay in heritaging this space
int4 deadcodedelay; ///< Delay before deadcode removal is allowed on this space int4 deadcodedelay; ///< Delay before deadcode removal is allowed on this space
@ -123,6 +126,8 @@ public:
uint4 getWordSize(void) const; ///< Get the addressable unit size uint4 getWordSize(void) const; ///< Get the addressable unit size
uint4 getAddrSize(void) const; ///< Get the size of the space uint4 getAddrSize(void) const; ///< Get the size of the space
uintb getHighest(void) const; ///< Get the highest byte-scaled address uintb getHighest(void) const; ///< Get the highest byte-scaled address
uintb getPointerLowerBound(void) const; ///< Get lower bound for assuming an offset is a pointer
int4 getMinimumPtrSize(void) const; ///< Get the minimum pointer size for \b this space
uintb wrapOffset(uintb off) const; ///< Wrap -off- to the offset that fits into this space uintb wrapOffset(uintb off) const; ///< Wrap -off- to the offset that fits into this space
char getShortcut(void) const; ///< Get the shortcut character char getShortcut(void) const; ///< Get the shortcut character
bool isHeritaged(void) const; ///< Return \b true if dataflow has been traced bool isHeritaged(void) const; ///< Return \b true if dataflow has been traced
@ -134,6 +139,7 @@ public:
bool isOverlayBase(void) const; ///< Return \b true if other spaces overlay this 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 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 bool isTruncated(void) const; ///< Return \b true if this space is truncated from its original size
bool hasNearPointers(void) const; ///< Return \b true if \e near (truncated) pointers into \b this space are possible
void printOffset(ostream &s,uintb offset) const; ///< Write an address offset to a stream void printOffset(ostream &s,uintb offset) const; ///< Write an address offset to a stream
virtual int4 numSpacebase(void) const; ///< Number of base registers associated with this space virtual int4 numSpacebase(void) const; ///< Number of base registers associated with this space
@ -153,6 +159,7 @@ public:
static uintb byteToAddress(uintb val,uint4 ws); ///< Scale from byte units to addressable units static uintb byteToAddress(uintb val,uint4 ws); ///< Scale from byte units to addressable units
static int4 addressToByteInt(int4 val,uint4 ws); ///< Scale int4 from addressable units to byte units static int4 addressToByteInt(int4 val,uint4 ws); ///< Scale int4 from addressable units to byte units
static int4 byteToAddressInt(int4 val,uint4 ws); ///< Scale int4 from byte units to addressable units static int4 byteToAddressInt(int4 val,uint4 ws); ///< Scale int4 from byte units to addressable units
static bool compareByIndex(const AddrSpace *a,const AddrSpace *b); ///< Compare two spaces by their index
}; };
/// \brief Special AddrSpace for representing constants during analysis. /// \brief Special AddrSpace for representing constants during analysis.
@ -333,6 +340,19 @@ inline uintb AddrSpace::getHighest(void) const {
return highest; return highest;
} }
/// Constant offsets are tested against \b this bound as a quick filter before
/// attempting to lookup symbols.
/// \return the minimum offset that will be inferred as a pointer
inline uintb AddrSpace::getPointerLowerBound(void) const {
return pointerLowerBound;
}
/// A value of 0 means the size must match exactly. If the space is truncated, or
/// if there exists near pointers, this value may be non-zero.
inline int4 AddrSpace::getMinimumPtrSize(void) const {
return minimumPointerSize;
}
/// Calculate \e off modulo the size of this address space in /// Calculate \e off modulo the size of this address space in
/// order to construct the offset "equivalent" to \e off that /// order to construct the offset "equivalent" to \e off that
/// fits properly into this space /// fits properly into this space
@ -416,6 +436,10 @@ inline bool AddrSpace::isTruncated(void) const {
return ((flags&truncated)!=0); return ((flags&truncated)!=0);
} }
inline bool AddrSpace::hasNearPointers(void) const {
return ((flags&has_nearpointers)!=0);
}
/// Some spaces are "virtual", like the stack spaces, where addresses are really relative to a /// Some spaces are "virtual", like the stack spaces, where addresses are really relative to a
/// base pointer stored in a register, like the stackpointer. This routine will return non-zero /// base pointer stored in a register, like the stackpointer. This routine will return non-zero
/// if \b this space is virtual and there is 1 (or more) associated pointer registers /// if \b this space is virtual and there is 1 (or more) associated pointer registers
@ -490,4 +514,13 @@ inline int4 AddrSpace::addressToByteInt(int4 val,uint4 ws) {
inline int4 AddrSpace::byteToAddressInt(int4 val,uint4 ws) { inline int4 AddrSpace::byteToAddressInt(int4 val,uint4 ws) {
return val/ws; return val/ws;
} }
/// For sorting a sequence of address spaces.
/// \param a is the first space
/// \param b is the second space
/// \return \b true if the first space should come before the second
inline bool AddrSpace::compareByIndex(const AddrSpace *a,const AddrSpace *b) {
return (a->index < b->index);
}
#endif #endif

View file

@ -456,6 +456,16 @@ void AddrSpaceManager::assignShortcut(AddrSpace *spc)
spc->shortcut = (char)shortcut; spc->shortcut = (char)shortcut;
} }
/// \param spc is the AddrSpace to mark
/// \param size is the (minimum) size of a near pointer in bytes
void AddrSpaceManager::markNearPointers(AddrSpace *spc,int4 size)
{
spc->setFlags(AddrSpace::has_nearpointers);
if (spc->minimumPointerSize == 0 && spc->addressSize != size)
spc->minimumPointerSize = size;
}
/// All address spaces have a unique name associated with them. /// All address spaces have a unique name associated with them.
/// This routine retrieves the AddrSpace object based on the /// This routine retrieves the AddrSpace object based on the
/// desired name. /// desired name.

View file

@ -235,6 +235,7 @@ protected:
void setDefaultSpace(int4 index); ///< Set the default address space void setDefaultSpace(int4 index); ///< Set the default address space
void setReverseJustified(AddrSpace *spc); ///< Set reverse justified property on this 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 assignShortcut(AddrSpace *spc); ///< Select a shortcut character for a new space
void markNearPointers(AddrSpace *spc,int4 size); ///< Mark that given space can be accessed with near pointers
void insertSpace(AddrSpace *spc); ///< Add a new address space to the model void insertSpace(AddrSpace *spc); ///< Add a new address space to the model
void copySpaces(const AddrSpaceManager *op2); ///< Copy spaces from another manager 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 void addSpacebasePointer(SpacebaseSpace *basespace,const VarnodeData &ptrdata,int4 truncSize,bool stackGrowth); ///< Set the base register of a spacebase space

View file

@ -72,6 +72,7 @@ void XmlArchitecture::buildLoader(DocumentStorage &store)
void XmlArchitecture::postSpecFile(void) void XmlArchitecture::postSpecFile(void)
{ {
Architecture::postSpecFile();
((LoadImageXml *)loader)->open(translate); ((LoadImageXml *)loader)->open(translate);
if (adjustvma != 0) if (adjustvma != 0)
loader->adjustVma(adjustvma); loader->adjustVma(adjustvma);