mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Allow constant pointer inference into multiple address spaces
This commit is contained in:
parent
b5e2efff77
commit
2e80935edb
12 changed files with 181 additions and 30 deletions
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue