mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
Print symbol namespace paths in context
This commit is contained in:
parent
a027a5cdd8
commit
f7a8e264aa
11 changed files with 196 additions and 72 deletions
|
@ -295,18 +295,32 @@ int4 Symbol::getMapEntryPosition(const SymbolEntry *entry) const
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A value of 0 means the base Symbol name is visible and not overridden in the given use scope.
|
/// For a given context scope where \b this Symbol is used, determine how many elements of
|
||||||
|
/// the full namespace path need to be printed to correctly distinguish it.
|
||||||
|
/// A value of 0 means the base symbol name is visible and not overridden in the context scope.
|
||||||
/// A value of 1 means the base name may be overridden, but the parent scope name is not.
|
/// A value of 1 means the base name may be overridden, but the parent scope name is not.
|
||||||
/// The minimual number of names that distinguishes \b this Symbol uniquely within the
|
/// The minimal number of names that distinguishes the symbol name uniquely within the
|
||||||
/// use scope is returned.
|
/// use scope is returned.
|
||||||
/// \param useScope is the given scope where \b this Symbol is being used
|
/// \param useScope is the given scope where the symbol is being used
|
||||||
/// \return the number of (extra) names needed to distinguish \b this Symbol
|
/// \return the number of (extra) names needed to distinguish the symbol
|
||||||
int4 Symbol::getResolutionDepth(const Scope *useScope) const
|
int4 Symbol::getResolutionDepth(const Scope *useScope) const
|
||||||
|
|
||||||
{
|
{
|
||||||
if (scope == useScope) return 0; // Symbol is in scope where it is used
|
if (scope == useScope) return 0; // Symbol is in scope where it is used
|
||||||
|
if (useScope == (const Scope *)0) { // Treat null useScope as resolving the full path
|
||||||
|
const Scope *point = scope;
|
||||||
|
int4 count = 0;
|
||||||
|
while(point != (const Scope *)0) {
|
||||||
|
count += 1;
|
||||||
|
point = point->getParent();
|
||||||
|
}
|
||||||
|
return count-1; // Don't print global scope
|
||||||
|
}
|
||||||
|
if (depthScope == useScope)
|
||||||
|
return depthResolution;
|
||||||
|
depthScope = useScope;
|
||||||
const Scope *distinguishScope = scope->findDistinguishingScope(useScope);
|
const Scope *distinguishScope = scope->findDistinguishingScope(useScope);
|
||||||
int4 depth = 0;
|
depthResolution = 0;
|
||||||
string distinguishName;
|
string distinguishName;
|
||||||
const Scope *terminatingScope;
|
const Scope *terminatingScope;
|
||||||
if (distinguishScope == (const Scope *)0) { // Symbol scope is ancestor of use scope
|
if (distinguishScope == (const Scope *)0) { // Symbol scope is ancestor of use scope
|
||||||
|
@ -317,15 +331,15 @@ int4 Symbol::getResolutionDepth(const Scope *useScope) const
|
||||||
distinguishName = distinguishScope->getName();
|
distinguishName = distinguishScope->getName();
|
||||||
const Scope *currentScope = scope;
|
const Scope *currentScope = scope;
|
||||||
while(currentScope != distinguishScope) { // For any scope up to the distinguishing scope
|
while(currentScope != distinguishScope) { // For any scope up to the distinguishing scope
|
||||||
depth += 1; // Print its name
|
depthResolution += 1; // Print its name
|
||||||
currentScope = currentScope->getParent();
|
currentScope = currentScope->getParent();
|
||||||
}
|
}
|
||||||
depth += 1; // Also print the distinguishing scope name
|
depthResolution += 1; // Also print the distinguishing scope name
|
||||||
terminatingScope = distinguishScope->getParent();
|
terminatingScope = distinguishScope->getParent();
|
||||||
}
|
}
|
||||||
if (useScope->isNameUsed(distinguishName,terminatingScope))
|
if (useScope->isNameUsed(distinguishName,terminatingScope))
|
||||||
depth += 1; // Name was overridden, we need one more distinguishing name
|
depthResolution += 1; // Name was overridden, we need one more distinguishing name
|
||||||
return depth;
|
return depthResolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param s is the output stream
|
/// \param s is the output stream
|
||||||
|
@ -564,7 +578,7 @@ Funcdata *FunctionSymbol::getFunction(void)
|
||||||
{
|
{
|
||||||
if (fd != (Funcdata *)0) return fd;
|
if (fd != (Funcdata *)0) return fd;
|
||||||
SymbolEntry *entry = getFirstWholeMap();
|
SymbolEntry *entry = getFirstWholeMap();
|
||||||
fd = new Funcdata(name,scope,entry->getAddr());
|
fd = new Funcdata(name,scope,entry->getAddr(),this);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,7 +600,7 @@ void FunctionSymbol::restoreXml(const Element *el)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (el->getName() == "function") {
|
if (el->getName() == "function") {
|
||||||
fd = new Funcdata("",scope,Address());
|
fd = new Funcdata("",scope,Address(),this);
|
||||||
symbolId = fd->restoreXml(el);
|
symbolId = fd->restoreXml(el);
|
||||||
name = fd->getName();
|
name = fd->getName();
|
||||||
if (consumeSize < fd->getSize()) {
|
if (consumeSize < fd->getSize()) {
|
||||||
|
@ -1377,20 +1391,19 @@ void Scope::getNameSegments(vector<string> &vec) const
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Put the parent scopes of \b this into an array in order, starting with the global scope.
|
/// Put the parent scopes of \b this into an array in order, starting with the global scope.
|
||||||
/// This scope itself will not be in the array.
|
|
||||||
/// \param vec is storage for the array of scopes
|
/// \param vec is storage for the array of scopes
|
||||||
void Scope::getScopePath(vector<Scope *> &vec) const
|
void Scope::getScopePath(vector<const Scope *> &vec) const
|
||||||
|
|
||||||
{
|
{
|
||||||
int4 count = 0;
|
int4 count = 0;
|
||||||
Scope *cur = parent;
|
const Scope *cur = this;
|
||||||
while(cur != (Scope *)0) { // Count number of elements in path
|
while(cur != (const Scope *)0) { // Count number of elements in path
|
||||||
count += 1;
|
count += 1;
|
||||||
cur = cur->parent;
|
cur = cur->parent;
|
||||||
}
|
}
|
||||||
vec.resize(count);
|
vec.resize(count);
|
||||||
cur = parent;
|
cur = this;
|
||||||
while(cur != (Scope *)0) {
|
while(cur != (const Scope *)0) {
|
||||||
count -= 1;
|
count -= 1;
|
||||||
vec[count] = cur;
|
vec[count] = cur;
|
||||||
cur = cur->parent;
|
cur = cur->parent;
|
||||||
|
@ -1407,7 +1420,7 @@ bool Scope::isNameUsed(const string &nm,const Scope *op2) const
|
||||||
{
|
{
|
||||||
const Scope *currentScope = this;
|
const Scope *currentScope = this;
|
||||||
while(currentScope != op2) {
|
while(currentScope != op2) {
|
||||||
if (currentScope->isNameUsed(name))
|
if (currentScope->isNameUsed(nm))
|
||||||
return true;
|
return true;
|
||||||
currentScope = currentScope->parent;
|
currentScope = currentScope->parent;
|
||||||
}
|
}
|
||||||
|
@ -1422,12 +1435,12 @@ bool Scope::isNameUsed(const string &nm,const Scope *op2) const
|
||||||
const Scope *Scope::findDistinguishingScope(const Scope *op2) const
|
const Scope *Scope::findDistinguishingScope(const Scope *op2) const
|
||||||
|
|
||||||
{
|
{
|
||||||
if (this == op2) return (Scope *)0; // Quickly check most common cases
|
if (this == op2) return (const Scope *)0; // Quickly check most common cases
|
||||||
if (parent == op2) return this;
|
if (parent == op2) return this;
|
||||||
if (op2->parent == this) return op2;
|
if (op2->parent == this) return (const Scope *)0;
|
||||||
if (parent == op2->parent) return this;
|
if (parent == op2->parent) return this;
|
||||||
vector<Scope *> thisPath;
|
vector<const Scope *> thisPath;
|
||||||
vector<Scope *> op2Path;
|
vector<const Scope *> op2Path;
|
||||||
getScopePath(thisPath);
|
getScopePath(thisPath);
|
||||||
op2->getScopePath(op2Path);
|
op2->getScopePath(op2Path);
|
||||||
int4 min = thisPath.size();
|
int4 min = thisPath.size();
|
||||||
|
@ -1440,7 +1453,7 @@ const Scope *Scope::findDistinguishingScope(const Scope *op2) const
|
||||||
if (min < thisPath.size())
|
if (min < thisPath.size())
|
||||||
return thisPath[min]; // thisPath matches op2Path but is longer
|
return thisPath[min]; // thisPath matches op2Path but is longer
|
||||||
if (min < op2Path.size())
|
if (min < op2Path.size())
|
||||||
return (Scope *)0; // op2Path matches thisPath but is longer
|
return (const Scope *)0; // op2Path matches thisPath but is longer
|
||||||
return this; // ancestor paths are identical (only base scopes differ)
|
return this; // ancestor paths are identical (only base scopes differ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1453,7 +1466,7 @@ Symbol *Scope::addSymbol(const string &name,Datatype *ct)
|
||||||
{
|
{
|
||||||
Symbol *sym;
|
Symbol *sym;
|
||||||
|
|
||||||
sym = new Symbol(this,name,ct);
|
sym = new Symbol(owner,name,ct);
|
||||||
addSymbolInternal(sym); // Let this scope lay claim to the new object
|
addSymbolInternal(sym); // Let this scope lay claim to the new object
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
@ -1474,7 +1487,7 @@ SymbolEntry *Scope::addSymbol(const string &name,Datatype *ct,
|
||||||
{
|
{
|
||||||
Symbol *sym;
|
Symbol *sym;
|
||||||
|
|
||||||
sym = new Symbol(this,name,ct);
|
sym = new Symbol(owner,name,ct);
|
||||||
addSymbolInternal(sym);
|
addSymbolInternal(sym);
|
||||||
return addMapPoint(sym,addr,usepoint);
|
return addMapPoint(sym,addr,usepoint);
|
||||||
}
|
}
|
||||||
|
@ -1509,19 +1522,19 @@ Symbol *Scope::addMapSym(const Element *el)
|
||||||
Symbol *sym;
|
Symbol *sym;
|
||||||
const string &symname( subel->getName() );
|
const string &symname( subel->getName() );
|
||||||
if (symname == "symbol")
|
if (symname == "symbol")
|
||||||
sym = new Symbol(this);
|
sym = new Symbol(owner);
|
||||||
else if (symname == "dynsymbol")
|
else if (symname == "dynsymbol")
|
||||||
sym = new Symbol(this);
|
sym = new Symbol(owner);
|
||||||
else if (symname == "equatesymbol")
|
else if (symname == "equatesymbol")
|
||||||
sym = new EquateSymbol(this);
|
sym = new EquateSymbol(owner);
|
||||||
else if (symname == "function")
|
else if (symname == "function")
|
||||||
sym = new FunctionSymbol(this,glb->min_funcsymbol_size);
|
sym = new FunctionSymbol(owner,glb->min_funcsymbol_size);
|
||||||
else if (symname == "functionshell")
|
else if (symname == "functionshell")
|
||||||
sym = new FunctionSymbol(this,glb->min_funcsymbol_size);
|
sym = new FunctionSymbol(owner,glb->min_funcsymbol_size);
|
||||||
else if (symname == "labelsym")
|
else if (symname == "labelsym")
|
||||||
sym = new LabSymbol(this);
|
sym = new LabSymbol(owner);
|
||||||
else if (symname == "externrefsymbol")
|
else if (symname == "externrefsymbol")
|
||||||
sym = new ExternRefSymbol(this);
|
sym = new ExternRefSymbol(owner);
|
||||||
else
|
else
|
||||||
throw LowlevelError("Unknown symbol type: "+symname);
|
throw LowlevelError("Unknown symbol type: "+symname);
|
||||||
try { // Protect against duplicate scope errors
|
try { // Protect against duplicate scope errors
|
||||||
|
@ -1563,7 +1576,7 @@ FunctionSymbol *Scope::addFunction(const Address &addr,const string &nm)
|
||||||
errmsg += " overlaps object: "+overlap->getSymbol()->getName();
|
errmsg += " overlaps object: "+overlap->getSymbol()->getName();
|
||||||
glb->printMessage(errmsg);
|
glb->printMessage(errmsg);
|
||||||
}
|
}
|
||||||
sym = new FunctionSymbol(this,nm,glb->min_funcsymbol_size);
|
sym = new FunctionSymbol(owner,nm,glb->min_funcsymbol_size);
|
||||||
addSymbolInternal(sym);
|
addSymbolInternal(sym);
|
||||||
// Map symbol to base address of function
|
// Map symbol to base address of function
|
||||||
// there is no limit on the applicability of this map within scope
|
// there is no limit on the applicability of this map within scope
|
||||||
|
@ -1584,7 +1597,7 @@ ExternRefSymbol *Scope::addExternalRef(const Address &addr,const Address &refadd
|
||||||
{
|
{
|
||||||
ExternRefSymbol *sym;
|
ExternRefSymbol *sym;
|
||||||
|
|
||||||
sym = new ExternRefSymbol(this,refaddr,nm);
|
sym = new ExternRefSymbol(owner,refaddr,nm);
|
||||||
addSymbolInternal(sym);
|
addSymbolInternal(sym);
|
||||||
// Map symbol to given address
|
// Map symbol to given address
|
||||||
// there is no limit on applicability of this map within scope
|
// there is no limit on applicability of this map within scope
|
||||||
|
@ -1612,7 +1625,7 @@ LabSymbol *Scope::addCodeLabel(const Address &addr,const string &nm)
|
||||||
errmsg += " overlaps object: "+overlap->getSymbol()->getName();
|
errmsg += " overlaps object: "+overlap->getSymbol()->getName();
|
||||||
glb->printMessage(errmsg);
|
glb->printMessage(errmsg);
|
||||||
}
|
}
|
||||||
sym = new LabSymbol(this,nm);
|
sym = new LabSymbol(owner,nm);
|
||||||
addSymbolInternal(sym);
|
addSymbolInternal(sym);
|
||||||
addMapPoint(sym,addr,Address());
|
addMapPoint(sym,addr,Address());
|
||||||
return sym;
|
return sym;
|
||||||
|
@ -1632,7 +1645,7 @@ Symbol *Scope::addDynamicSymbol(const string &nm,Datatype *ct,const Address &cad
|
||||||
{
|
{
|
||||||
Symbol *sym;
|
Symbol *sym;
|
||||||
|
|
||||||
sym = new Symbol(this,nm,ct);
|
sym = new Symbol(owner,nm,ct);
|
||||||
addSymbolInternal(sym);
|
addSymbolInternal(sym);
|
||||||
RangeList rnglist;
|
RangeList rnglist;
|
||||||
if (!caddr.isInvalid())
|
if (!caddr.isInvalid())
|
||||||
|
@ -1832,12 +1845,17 @@ list<SymbolEntry>::iterator ScopeInternal::endDynamic(void)
|
||||||
/// \param nm is the name of the Scope
|
/// \param nm is the name of the Scope
|
||||||
/// \param g is the Architecture it belongs to
|
/// \param g is the Architecture it belongs to
|
||||||
ScopeInternal::ScopeInternal(const string &nm,Architecture *g)
|
ScopeInternal::ScopeInternal(const string &nm,Architecture *g)
|
||||||
: Scope(nm,g)
|
: Scope(nm,g,this)
|
||||||
{
|
{
|
||||||
nextUniqueId = 0;
|
nextUniqueId = 0;
|
||||||
int4 numspaces = g->numSpaces();
|
maptable.resize(g->numSpaces(),(EntryMap *)0);
|
||||||
for(int4 i=0;i<numspaces;++i)
|
}
|
||||||
maptable.push_back((EntryMap *)0);
|
|
||||||
|
ScopeInternal::ScopeInternal(const string &nm,Architecture *g, Scope *own)
|
||||||
|
: Scope(nm,g,own)
|
||||||
|
{
|
||||||
|
nextUniqueId = 0;
|
||||||
|
maptable.resize(g->numSpaces(),(EntryMap *)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopeInternal::~ScopeInternal(void)
|
ScopeInternal::~ScopeInternal(void)
|
||||||
|
|
|
@ -167,6 +167,8 @@ protected:
|
||||||
uint2 catindex; ///< Index within category
|
uint2 catindex; ///< Index within category
|
||||||
uint8 symbolId; ///< Unique id, 0=unassigned
|
uint8 symbolId; ///< Unique id, 0=unassigned
|
||||||
vector<list<SymbolEntry>::iterator> mapentry; ///< List of storage locations labeled with \b this Symbol
|
vector<list<SymbolEntry>::iterator> mapentry; ///< List of storage locations labeled with \b this Symbol
|
||||||
|
mutable const Scope *depthScope; ///< Scope associated with current depth resolution
|
||||||
|
mutable int4 depthResolution; ///< Number of namespace elements required to resolve symbol in current scope
|
||||||
uint4 wholeCount; ///< Number of SymbolEntries that map to the whole Symbol
|
uint4 wholeCount; ///< Number of SymbolEntries that map to the whole Symbol
|
||||||
virtual ~Symbol(void) {} ///< Destructor
|
virtual ~Symbol(void) {} ///< Destructor
|
||||||
void setDisplayFormat(uint4 val); ///< Set the display format for \b this Symbol
|
void setDisplayFormat(uint4 val); ///< Set the display format for \b this Symbol
|
||||||
|
@ -183,13 +185,9 @@ public:
|
||||||
isolate = 16, ///< Symbol should not speculatively merge automatically
|
isolate = 16, ///< Symbol should not speculatively merge automatically
|
||||||
merge_problems = 32 ///< Set if some SymbolEntrys did not get merged
|
merge_problems = 32 ///< Set if some SymbolEntrys did not get merged
|
||||||
};
|
};
|
||||||
/// \brief Construct given a name and data-type
|
|
||||||
Symbol(Scope *sc,const string &nm,Datatype *ct)
|
|
||||||
{ scope=sc; name=nm; nameDedup=0; type=ct; flags=0; dispflags=0; category=-1; symbolId=0; wholeCount=0; }
|
|
||||||
|
|
||||||
/// \brief Construct for use with restoreXml()
|
|
||||||
Symbol(Scope *sc) { scope=sc; nameDedup=0; flags=0; dispflags=0; category=-1; symbolId = 0; wholeCount=0; }
|
|
||||||
|
|
||||||
|
Symbol(Scope *sc,const string &nm,Datatype *ct); ///< Construct given a name and data-type
|
||||||
|
Symbol(Scope *sc); ///< Construct for use with restoreXml()
|
||||||
const string &getName(void) const { return name; } ///< Get the local name of the symbol
|
const string &getName(void) const { return name; } ///< Get the local name of the symbol
|
||||||
Datatype *getType(void) const { return type; } ///< Get the data-type
|
Datatype *getType(void) const { return type; } ///< Get the data-type
|
||||||
uint8 getId(void) const { return symbolId; } ///< Get a unique id for the symbol
|
uint8 getId(void) const { return symbolId; } ///< Get a unique id for the symbol
|
||||||
|
@ -214,7 +212,7 @@ public:
|
||||||
int4 numEntries(void) const { return mapentry.size(); } ///< Return the number of SymbolEntrys
|
int4 numEntries(void) const { return mapentry.size(); } ///< Return the number of SymbolEntrys
|
||||||
SymbolEntry *getMapEntry(int4 i) const { return &(*mapentry[i]); } ///< Return the i-th SymbolEntry for \b this Symbol
|
SymbolEntry *getMapEntry(int4 i) const { return &(*mapentry[i]); } ///< Return the i-th SymbolEntry for \b this Symbol
|
||||||
int4 getMapEntryPosition(const SymbolEntry *entry) const; ///< Position of given SymbolEntry within \b this multi-entry Symbol
|
int4 getMapEntryPosition(const SymbolEntry *entry) const; ///< Position of given SymbolEntry within \b this multi-entry Symbol
|
||||||
int4 getResolutionDepth(const Scope *useScope) const; ///< Get the number of scope names to print to resolve symbol in given context
|
int4 getResolutionDepth(const Scope *useScope) const; ///< Get number of scope names needed to resolve \b this symbol
|
||||||
void saveXmlHeader(ostream &s) const; ///< Save basic Symbol properties as XML attributes
|
void saveXmlHeader(ostream &s) const; ///< Save basic Symbol properties as XML attributes
|
||||||
void restoreXmlHeader(const Element *el); ///< Restore basic Symbol properties from XML
|
void restoreXmlHeader(const Element *el); ///< Restore basic Symbol properties from XML
|
||||||
void saveXmlBody(ostream &s) const; ///< Save details of the Symbol to XML
|
void saveXmlBody(ostream &s) const; ///< Save details of the Symbol to XML
|
||||||
|
@ -415,6 +413,7 @@ class Scope {
|
||||||
friend class ScopeCompare;
|
friend class ScopeCompare;
|
||||||
RangeList rangetree; ///< Range of data addresses \e owned by \b this scope
|
RangeList rangetree; ///< Range of data addresses \e owned by \b this scope
|
||||||
Scope *parent; ///< The parent scope
|
Scope *parent; ///< The parent scope
|
||||||
|
Scope *owner; ///< Scope using \b this as a cache
|
||||||
ScopeMap children; ///< Sorted list of child scopes
|
ScopeMap children; ///< Sorted list of child scopes
|
||||||
void attachScope(Scope *child); ///< Attach a new child Scope to \b this
|
void attachScope(Scope *child); ///< Attach a new child Scope to \b this
|
||||||
void detachScope(ScopeMap::iterator iter); ///< Detach a child Scope from \b this
|
void detachScope(ScopeMap::iterator iter); ///< Detach a child Scope from \b this
|
||||||
|
@ -502,8 +501,8 @@ public:
|
||||||
void turnOffDebug(void) const { debugon = false; }
|
void turnOffDebug(void) const { debugon = false; }
|
||||||
#endif
|
#endif
|
||||||
/// \brief Construct an empty scope, given a name and Architecture
|
/// \brief Construct an empty scope, given a name and Architecture
|
||||||
Scope(const string &nm,Architecture *g) {
|
Scope(const string &nm,Architecture *g,Scope *own) {
|
||||||
name = nm; glb = g; parent = (Scope *)0; fd = (Funcdata *)0; uniqueId = 0;
|
name = nm; glb = g; parent = (Scope *)0; fd = (Funcdata *)0; uniqueId = 0; owner=own;
|
||||||
#ifdef OPACTION_DEBUG
|
#ifdef OPACTION_DEBUG
|
||||||
debugon = false;
|
debugon = false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -694,7 +693,7 @@ public:
|
||||||
bool isSubScope(const Scope *scp) const; ///< Is this a sub-scope of the given Scope
|
bool isSubScope(const Scope *scp) const; ///< Is this a sub-scope of the given Scope
|
||||||
string getFullName(void) const; ///< Get the full name of \b this Scope
|
string getFullName(void) const; ///< Get the full name of \b this Scope
|
||||||
void getNameSegments(vector<string> &vec) const; ///< Get the fullname of \b this in segments
|
void getNameSegments(vector<string> &vec) const; ///< Get the fullname of \b this in segments
|
||||||
void getScopePath(vector<Scope *> &vec) const; ///< Get the ordered list of parent scopes to \b this
|
void getScopePath(vector<const Scope *> &vec) const; ///< Get the ordered list of scopes up to \b this
|
||||||
bool isNameUsed(const string &nm,const Scope *op2) const; ///< Is the given name in use within given scope path
|
bool isNameUsed(const string &nm,const Scope *op2) const; ///< Is the given name in use within given scope path
|
||||||
const Scope *findDistinguishingScope(const Scope *op2) const; ///< Find first ancestor of \b this not shared by given scope
|
const Scope *findDistinguishingScope(const Scope *op2) const; ///< Find first ancestor of \b this not shared by given scope
|
||||||
Architecture *getArch(void) const { return glb; } ///< Get the Architecture associated with \b this
|
Architecture *getArch(void) const { return glb; } ///< Get the Architecture associated with \b this
|
||||||
|
@ -735,6 +734,7 @@ protected:
|
||||||
uint8 nextUniqueId; ///< Next available symbol id
|
uint8 nextUniqueId; ///< Next available symbol id
|
||||||
public:
|
public:
|
||||||
ScopeInternal(const string &nm,Architecture *g); ///< Construct the Scope
|
ScopeInternal(const string &nm,Architecture *g); ///< Construct the Scope
|
||||||
|
ScopeInternal(const string &nm,Architecture *g, Scope *own); ///< Construct as a cache
|
||||||
virtual void clear(void);
|
virtual void clear(void);
|
||||||
virtual void categorySanity(void); ///< Make sure Symbol categories are sane
|
virtual void categorySanity(void); ///< Make sure Symbol categories are sane
|
||||||
virtual void clearCategory(int4 cat);
|
virtual void clearCategory(int4 cat);
|
||||||
|
@ -870,4 +870,41 @@ public:
|
||||||
void restoreXmlScope(const Element *el,Scope *new_scope); ///< Register and fill out a single Scope from XML
|
void restoreXmlScope(const Element *el,Scope *new_scope); ///< Register and fill out a single Scope from XML
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \param sc is the scope containing the new symbol
|
||||||
|
/// \param nm is the local name of the symbol
|
||||||
|
/// \param ct is the data-type of the symbol
|
||||||
|
inline Symbol::Symbol(Scope *sc,const string &nm,Datatype *ct)
|
||||||
|
|
||||||
|
{
|
||||||
|
scope=sc;
|
||||||
|
name=nm;
|
||||||
|
nameDedup=0;
|
||||||
|
type=ct;
|
||||||
|
flags=0;
|
||||||
|
dispflags=0;
|
||||||
|
category=-1;
|
||||||
|
catindex = 0;
|
||||||
|
symbolId=0;
|
||||||
|
wholeCount=0;
|
||||||
|
depthScope = (const Scope *)0;
|
||||||
|
depthResolution = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \param sc is the scope containing the new symbol
|
||||||
|
inline Symbol::Symbol(Scope *sc)
|
||||||
|
|
||||||
|
{
|
||||||
|
scope=sc;
|
||||||
|
nameDedup=0;
|
||||||
|
type = (Datatype *)0;
|
||||||
|
flags=0;
|
||||||
|
dispflags=0;
|
||||||
|
category=-1;
|
||||||
|
catindex = 0;
|
||||||
|
symbolId = 0;
|
||||||
|
wholeCount=0;
|
||||||
|
depthScope = (const Scope *)0;
|
||||||
|
depthResolution = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
|
|
||||||
/// \param g is the Architecture and connection to the Ghidra client
|
/// \param g is the Architecture and connection to the Ghidra client
|
||||||
ScopeGhidra::ScopeGhidra(ArchitectureGhidra *g)
|
ScopeGhidra::ScopeGhidra(ArchitectureGhidra *g)
|
||||||
: Scope("",g)
|
: Scope("",g,this)
|
||||||
{
|
{
|
||||||
ghidra = g;
|
ghidra = g;
|
||||||
cache = new ScopeInternal("",g);
|
cache = new ScopeInternal("",g,this);
|
||||||
cacheDirty = false;
|
cacheDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
/// \param scope is Symbol scope associated with the function
|
/// \param scope is Symbol scope associated with the function
|
||||||
/// \param addr is the entry address for the function
|
/// \param addr is the entry address for the function
|
||||||
/// \param sz is the number of bytes (of code) in the function body
|
/// \param sz is the number of bytes (of code) in the function body
|
||||||
Funcdata::Funcdata(const string &nm,Scope *scope,const Address &addr,int4 sz)
|
Funcdata::Funcdata(const string &nm,Scope *scope,const Address &addr,FunctionSymbol *sym,int4 sz)
|
||||||
: baseaddr(addr),
|
: baseaddr(addr),
|
||||||
funcp(),
|
funcp(),
|
||||||
vbank(scope->getArch(),
|
vbank(scope->getArch(),
|
||||||
|
@ -31,6 +31,7 @@ Funcdata::Funcdata(const string &nm,Scope *scope,const Address &addr,int4 sz)
|
||||||
|
|
||||||
{ // Initialize high-level properties of
|
{ // Initialize high-level properties of
|
||||||
// function by giving address and size
|
// function by giving address and size
|
||||||
|
functionSymbol = sym;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
clean_up_index = 0;
|
clean_up_index = 0;
|
||||||
high_level_index = 0;
|
high_level_index = 0;
|
||||||
|
|
|
@ -63,9 +63,10 @@ class Funcdata {
|
||||||
uint4 high_level_index; ///< Creation index of first Varnode created after HighVariables are created
|
uint4 high_level_index; ///< Creation index of first Varnode created after HighVariables are created
|
||||||
uint4 cast_phase_index; ///< Creation index of first Varnode created after ActionSetCasts
|
uint4 cast_phase_index; ///< Creation index of first Varnode created after ActionSetCasts
|
||||||
uint4 minLanedSize; ///< Minimum Varnode size to check as LanedRegister
|
uint4 minLanedSize; ///< Minimum Varnode size to check as LanedRegister
|
||||||
Architecture *glb; ///< Global configuration data
|
|
||||||
string name; ///< Name of function
|
|
||||||
int4 size; ///< Number of bytes of binary data in function body
|
int4 size; ///< Number of bytes of binary data in function body
|
||||||
|
Architecture *glb; ///< Global configuration data
|
||||||
|
FunctionSymbol *functionSymbol; ///< The symbol representing \b this function
|
||||||
|
string name; ///< Name of function
|
||||||
Address baseaddr; ///< Starting code address of binary data
|
Address baseaddr; ///< Starting code address of binary data
|
||||||
FuncProto funcp; ///< Prototype of this function
|
FuncProto funcp; ///< Prototype of this function
|
||||||
ScopeLocal *localmap; ///< Local variables (symbols in the function scope)
|
ScopeLocal *localmap; ///< Local variables (symbols in the function scope)
|
||||||
|
@ -119,12 +120,13 @@ class Funcdata {
|
||||||
static PcodeOp *findPrimaryBranch(PcodeOpTree::const_iterator iter,PcodeOpTree::const_iterator enditer,
|
static PcodeOp *findPrimaryBranch(PcodeOpTree::const_iterator iter,PcodeOpTree::const_iterator enditer,
|
||||||
bool findbranch,bool findcall,bool findreturn);
|
bool findbranch,bool findcall,bool findreturn);
|
||||||
public:
|
public:
|
||||||
Funcdata(const string &nm,Scope *conf,const Address &addr,int4 sz=0); ///< Constructor
|
Funcdata(const string &nm,Scope *conf,const Address &addr,FunctionSymbol *sym,int4 sz=0); ///< Constructor
|
||||||
~Funcdata(void); ///< Destructor
|
~Funcdata(void); ///< Destructor
|
||||||
const string &getName(void) const { return name; } ///< Get the function's local symbol name
|
const string &getName(void) const { return name; } ///< Get the function's local symbol name
|
||||||
const Address &getAddress(void) const { return baseaddr; } ///< Get the entry point address
|
const Address &getAddress(void) const { return baseaddr; } ///< Get the entry point address
|
||||||
int4 getSize(void) const { return size; } ///< Get the function body size in bytes
|
int4 getSize(void) const { return size; } ///< Get the function body size in bytes
|
||||||
Architecture *getArch(void) const { return glb; } ///< Get the program/architecture owning the function
|
Architecture *getArch(void) const { return glb; } ///< Get the program/architecture owning \b this function
|
||||||
|
FunctionSymbol *getSymbol(void) const { return functionSymbol; } ///< Return the symbol associated with \b this function
|
||||||
bool isHighOn(void) const { return ((flags&highlevel_on)!=0); } ///< Are high-level variables assigned to Varnodes
|
bool isHighOn(void) const { return ((flags&highlevel_on)!=0); } ///< Are high-level variables assigned to Varnodes
|
||||||
bool isProcStarted(void) const { return ((flags&processing_started)!=0); } ///< Has processing of the function started
|
bool isProcStarted(void) const { return ((flags&processing_started)!=0); } ///< Has processing of the function started
|
||||||
bool isProcComplete(void) const { return ((flags&processing_complete)!=0); } ///< Is processing of the function complete
|
bool isProcComplete(void) const { return ((flags&processing_complete)!=0); } ///< Is processing of the function complete
|
||||||
|
|
|
@ -495,7 +495,7 @@ int4 Funcdata::stageJumpTable(JumpTable *jt,PcodeOp *op,FlowInfo *flow)
|
||||||
s1 << name << "@@jump@";
|
s1 << name << "@@jump@";
|
||||||
op->getAddr().printRaw(s1);
|
op->getAddr().printRaw(s1);
|
||||||
|
|
||||||
Funcdata partial(s1.str(),localmap->getParent(),baseaddr);
|
Funcdata partial(s1.str(),localmap->getParent(),baseaddr,(FunctionSymbol *)0);
|
||||||
partial.flags |= jumptablerecovery_on; // Mark that this Funcdata object is dedicated to jumptable recovery
|
partial.flags |= jumptablerecovery_on; // Mark that this Funcdata object is dedicated to jumptable recovery
|
||||||
partial.truncatedFlow(this,flow);
|
partial.truncatedFlow(this,flow);
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ OpToken PrintC::binary_plus = { "+", 2, 50, true, OpToken::binary, 1, 0, (OpToke
|
||||||
OpToken PrintC::binary_minus = { "-", 2, 50, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
OpToken PrintC::binary_minus = { "-", 2, 50, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
||||||
OpToken PrintC::shift_left = { "<<", 2, 46, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
OpToken PrintC::shift_left = { "<<", 2, 46, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
||||||
OpToken PrintC::shift_right = { ">>", 2, 46, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
OpToken PrintC::shift_right = { ">>", 2, 46, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
||||||
|
OpToken PrintC::shift_sright = { ">>", 2, 46, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
||||||
OpToken PrintC::less_than = { "<", 2, 42, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
OpToken PrintC::less_than = { "<", 2, 42, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
||||||
OpToken PrintC::less_equal = { "<=", 2, 42, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
OpToken PrintC::less_equal = { "<=", 2, 42, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
||||||
OpToken PrintC::greater_than = { ">", 2, 42, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
OpToken PrintC::greater_than = { ">", 2, 42, false, OpToken::binary, 1, 0, (OpToken *)0 };
|
||||||
|
@ -167,6 +168,48 @@ void PrintC::pushPrototypeInputs(const FuncProto *proto)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate what elements of a given symbol's namespace path are necessary to distinguish
|
||||||
|
/// it within the current scope. Then print these elements.
|
||||||
|
/// \param symbol is the given symbol
|
||||||
|
void PrintC::pushSymbolScope(const Symbol *symbol)
|
||||||
|
|
||||||
|
{
|
||||||
|
int4 scopedepth = symbol->getResolutionDepth(curscope);
|
||||||
|
if (scopedepth != 0) {
|
||||||
|
vector<const Scope *> scopeList;
|
||||||
|
const Scope *point = symbol->getScope();
|
||||||
|
for(int4 i=0;i<scopedepth;++i) {
|
||||||
|
scopeList.push_back(point);
|
||||||
|
point = point->getParent();
|
||||||
|
pushOp(&scope, (PcodeOp *)0);
|
||||||
|
}
|
||||||
|
for(int4 i=scopedepth-1;i>=0;--i) {
|
||||||
|
pushAtom(Atom(scopeList[i]->getName(),syntax,EmitXml::global_color,(PcodeOp *)0,(Varnode *)0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Emit the elements of the given function's namespace path that distinguish it within
|
||||||
|
/// the current scope.
|
||||||
|
/// \param fd is the given function
|
||||||
|
void PrintC::emitSymbolScope(const Symbol *symbol)
|
||||||
|
|
||||||
|
{
|
||||||
|
int4 scopedepth = symbol->getResolutionDepth(curscope);
|
||||||
|
if (scopedepth != 0) {
|
||||||
|
vector<const Scope *> scopeList;
|
||||||
|
const Scope *point = symbol->getScope();
|
||||||
|
for(int4 i=0;i<scopedepth;++i) {
|
||||||
|
scopeList.push_back(point);
|
||||||
|
point = point->getParent();
|
||||||
|
}
|
||||||
|
for(int4 i=scopedepth-1;i>=0;--i) {
|
||||||
|
emit->print(scopeList[i]->getName().c_str(), EmitXml::global_color);
|
||||||
|
emit->print(scope.print, EmitXml::no_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Store off array sizes for printing after the identifier
|
/// Store off array sizes for printing after the identifier
|
||||||
/// \param ct is the data-type to push
|
/// \param ct is the data-type to push
|
||||||
/// \param noident is \b true if an identifier will not be pushed as part of the declaration
|
/// \param noident is \b true if an identifier will not be pushed as part of the declaration
|
||||||
|
@ -453,8 +496,12 @@ void PrintC::opCall(const PcodeOp *op)
|
||||||
string name = genericFunctionName(fc->getEntryAddress());
|
string name = genericFunctionName(fc->getEntryAddress());
|
||||||
pushAtom(Atom(name,functoken,EmitXml::funcname_color,op,(const Funcdata *)0));
|
pushAtom(Atom(name,functoken,EmitXml::funcname_color,op,(const Funcdata *)0));
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
Funcdata *fd = fc->getFuncdata();
|
||||||
|
if (fd != (Funcdata *)0)
|
||||||
|
pushSymbolScope(fd->getSymbol());
|
||||||
pushAtom(Atom(fc->getName(),functoken,EmitXml::funcname_color,op,(const Funcdata *)0));
|
pushAtom(Atom(fc->getName(),functoken,EmitXml::funcname_color,op,(const Funcdata *)0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
clear();
|
clear();
|
||||||
|
@ -718,8 +765,10 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
||||||
int4 newoff;
|
int4 newoff;
|
||||||
const TypeField *fld = ((TypeStruct *)ct)->getField((int4)suboff,0,&newoff);
|
const TypeField *fld = ((TypeStruct *)ct)->getField((int4)suboff,0,&newoff);
|
||||||
if (fld == (const TypeField *)0) {
|
if (fld == (const TypeField *)0) {
|
||||||
if (ct->getSize() <= suboff)
|
if (ct->getSize() <= suboff) {
|
||||||
|
clear();
|
||||||
throw LowlevelError("PTRSUB out of bounds into struct");
|
throw LowlevelError("PTRSUB out of bounds into struct");
|
||||||
|
}
|
||||||
// Try to match the Ghidra's default field name from DataTypeComponent.getDefaultFieldName
|
// Try to match the Ghidra's default field name from DataTypeComponent.getDefaultFieldName
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << "field_0x" << hex << suboff;
|
s << "field_0x" << hex << suboff;
|
||||||
|
@ -1577,7 +1626,7 @@ void PrintC::pushSymbol(const Symbol *sym,const Varnode *vn,const PcodeOp *op)
|
||||||
tokenColor = EmitXml::param_color;
|
tokenColor = EmitXml::param_color;
|
||||||
else
|
else
|
||||||
tokenColor = EmitXml::var_color;
|
tokenColor = EmitXml::var_color;
|
||||||
// FIXME: resolve scopes
|
pushSymbolScope(sym);
|
||||||
if (sym->hasMergeProblems() && vn != (Varnode *)0) {
|
if (sym->hasMergeProblems() && vn != (Varnode *)0) {
|
||||||
HighVariable *high = vn->getHigh();
|
HighVariable *high = vn->getHigh();
|
||||||
if (high->isUnmerged()) {
|
if (high->isUnmerged()) {
|
||||||
|
@ -1934,6 +1983,8 @@ void PrintC::resetDefaults(void)
|
||||||
void PrintC::adjustTypeOperators(void)
|
void PrintC::adjustTypeOperators(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
scope.print = "::";
|
||||||
|
shift_right.print = ">>";
|
||||||
TypeOp::selectJavaOperators(glb->inst,false);
|
TypeOp::selectJavaOperators(glb->inst,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2179,12 +2230,14 @@ void PrintC::emitFunctionDeclaration(const Funcdata *fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int4 id1 = emit->openGroup();
|
int4 id1 = emit->openGroup();
|
||||||
|
emitSymbolScope(fd->getSymbol());
|
||||||
emit->tagFuncName(fd->getName().c_str(),EmitXml::funcname_color,
|
emit->tagFuncName(fd->getName().c_str(),EmitXml::funcname_color,
|
||||||
fd,(PcodeOp *)0);
|
fd,(PcodeOp *)0);
|
||||||
|
|
||||||
emit->spaces(function_call.spacing,function_call.bump);
|
emit->spaces(function_call.spacing,function_call.bump);
|
||||||
int4 id2 = emit->openParen('(');
|
int4 id2 = emit->openParen('(');
|
||||||
emit->spaces(0,function_call.bump);
|
emit->spaces(0,function_call.bump);
|
||||||
|
pushScope(fd->getScopeLocal()); // Enter the function's scope for parameters
|
||||||
emitPrototypeInputs(proto);
|
emitPrototypeInputs(proto);
|
||||||
emit->closeParen(')',id2);
|
emit->closeParen(')',id2);
|
||||||
emit->closeGroup(id1);
|
emit->closeGroup(id1);
|
||||||
|
@ -2241,7 +2294,7 @@ void PrintC::docFunction(const Funcdata *fd)
|
||||||
int4 id1 = emit->beginFunction(fd);
|
int4 id1 = emit->beginFunction(fd);
|
||||||
emitCommentFuncHeader(fd);
|
emitCommentFuncHeader(fd);
|
||||||
emit->tagLine();
|
emit->tagLine();
|
||||||
emitFunctionDeclaration(fd);
|
emitFunctionDeclaration(fd); // Causes us to enter function's scope
|
||||||
emit->tagLine();
|
emit->tagLine();
|
||||||
emit->tagLine();
|
emit->tagLine();
|
||||||
int4 id = emit->startIndent();
|
int4 id = emit->startIndent();
|
||||||
|
@ -2251,6 +2304,7 @@ void PrintC::docFunction(const Funcdata *fd)
|
||||||
emitBlockGraph(&fd->getBasicBlocks());
|
emitBlockGraph(&fd->getBasicBlocks());
|
||||||
else
|
else
|
||||||
emitBlockGraph(&fd->getStructure());
|
emitBlockGraph(&fd->getStructure());
|
||||||
|
popScope(); // Exit function's scope
|
||||||
emit->stopIndent(id);
|
emit->stopIndent(id);
|
||||||
emit->tagLine();
|
emit->tagLine();
|
||||||
emit->print("}");
|
emit->print("}");
|
||||||
|
|
|
@ -82,6 +82,7 @@ protected:
|
||||||
static OpToken binary_minus; ///< The \e binary \e subtraction operator
|
static OpToken binary_minus; ///< The \e binary \e subtraction operator
|
||||||
static OpToken shift_left; ///< The \e left \e shift operator
|
static OpToken shift_left; ///< The \e left \e shift operator
|
||||||
static OpToken shift_right; ///< The \e right \e shift operator
|
static OpToken shift_right; ///< The \e right \e shift operator
|
||||||
|
static OpToken shift_sright; ///< The signed \e right \e shift operator
|
||||||
static OpToken less_than; ///< The \e less \e than operator
|
static OpToken less_than; ///< The \e less \e than operator
|
||||||
static OpToken less_equal; ///< The \e less \e than \e or \e equal operator
|
static OpToken less_equal; ///< The \e less \e than \e or \e equal operator
|
||||||
static OpToken greater_than; ///< The \e greater \e than operator
|
static OpToken greater_than; ///< The \e greater \e than operator
|
||||||
|
@ -124,6 +125,8 @@ protected:
|
||||||
// Routines that are specific to C/C++
|
// Routines that are specific to C/C++
|
||||||
void buildTypeStack(const Datatype *ct,vector<const Datatype *> &typestack); ///< Prepare to push components of a data-type declaration
|
void buildTypeStack(const Datatype *ct,vector<const Datatype *> &typestack); ///< Prepare to push components of a data-type declaration
|
||||||
void pushPrototypeInputs(const FuncProto *proto); ///< Push input parameters
|
void pushPrototypeInputs(const FuncProto *proto); ///< Push input parameters
|
||||||
|
void pushSymbolScope(const Symbol *symbol); ///< Push tokens resolving a symbol's scope
|
||||||
|
void emitSymbolScope(const Symbol *symbol); ///< Emit tokens resolving a symbol's scope
|
||||||
virtual void pushTypeStart(const Datatype *ct,bool noident); ///< Push part of a data-type declaration onto the RPN stack, up to the identifier
|
virtual void pushTypeStart(const Datatype *ct,bool noident); ///< Push part of a data-type declaration onto the RPN stack, up to the identifier
|
||||||
virtual void pushTypeEnd(const Datatype *ct); ///< Push the tail ends of a data-type declaration onto the RPN stack
|
virtual void pushTypeEnd(const Datatype *ct); ///< Push the tail ends of a data-type declaration onto the RPN stack
|
||||||
void pushBoolConstant(uintb val,const TypeBase *ct,const Varnode *vn,
|
void pushBoolConstant(uintb val,const TypeBase *ct,const Varnode *vn,
|
||||||
|
@ -251,7 +254,7 @@ public:
|
||||||
virtual void opIntOr(const PcodeOp *op) { opBinary(&bitwise_or,op); }
|
virtual void opIntOr(const PcodeOp *op) { opBinary(&bitwise_or,op); }
|
||||||
virtual void opIntLeft(const PcodeOp *op) { opBinary(&shift_left,op); }
|
virtual void opIntLeft(const PcodeOp *op) { opBinary(&shift_left,op); }
|
||||||
virtual void opIntRight(const PcodeOp *op) { opBinary(&shift_right,op); }
|
virtual void opIntRight(const PcodeOp *op) { opBinary(&shift_right,op); }
|
||||||
virtual void opIntSright(const PcodeOp *op) { opBinary(&shift_right,op); }
|
virtual void opIntSright(const PcodeOp *op) { opBinary(&shift_sright,op); }
|
||||||
virtual void opIntMult(const PcodeOp *op) { opBinary(&multiply,op); }
|
virtual void opIntMult(const PcodeOp *op) { opBinary(&multiply,op); }
|
||||||
virtual void opIntDiv(const PcodeOp *op) { opBinary(÷,op); }
|
virtual void opIntDiv(const PcodeOp *op) { opBinary(÷,op); }
|
||||||
virtual void opIntSdiv(const PcodeOp *op) { opBinary(÷,op); }
|
virtual void opIntSdiv(const PcodeOp *op) { opBinary(÷,op); }
|
||||||
|
|
|
@ -99,6 +99,8 @@ void PrintJava::pushTypeEnd(const Datatype *ct)
|
||||||
void PrintJava::adjustTypeOperators(void)
|
void PrintJava::adjustTypeOperators(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
scope.print = ".";
|
||||||
|
shift_right.print = ">>>";
|
||||||
TypeOp::selectJavaOperators(glb->inst,true);
|
TypeOp::selectJavaOperators(glb->inst,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,16 @@ void PrintLanguage::setCommentDelimeter(const string &start,const string &stop,b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrintLanguage::popScope(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
scopestack.pop_back();
|
||||||
|
if (scopestack.empty())
|
||||||
|
curscope = (Scope *)0;
|
||||||
|
else
|
||||||
|
curscope = scopestack.back();
|
||||||
|
}
|
||||||
|
|
||||||
/// This generally will recursively push an entire expression onto the RPN stack,
|
/// This generally will recursively push an entire expression onto the RPN stack,
|
||||||
/// up to Varnode objects marked as \e explicit, and will decide token order
|
/// up to Varnode objects marked as \e explicit, and will decide token order
|
||||||
/// and parenthesis placement. As the ordering gets resolved,
|
/// and parenthesis placement. As the ordering gets resolved,
|
||||||
|
@ -658,10 +668,8 @@ void PrintLanguage::clear(void)
|
||||||
mods = modstack.front();
|
mods = modstack.front();
|
||||||
modstack.clear();
|
modstack.clear();
|
||||||
}
|
}
|
||||||
if (!scopestack.empty()) {
|
scopestack.clear();
|
||||||
curscope = scopestack.front();
|
curscope = (const Scope *)0;
|
||||||
scopestack.clear();
|
|
||||||
}
|
|
||||||
revpol.clear();
|
revpol.clear();
|
||||||
pending = 0;
|
pending = 0;
|
||||||
|
|
||||||
|
|
|
@ -230,8 +230,7 @@ public:
|
||||||
private:
|
private:
|
||||||
string name; ///< The name of the high-level language
|
string name; ///< The name of the high-level language
|
||||||
vector<uint4> modstack; ///< Printing modification stack
|
vector<uint4> modstack; ///< Printing modification stack
|
||||||
vector<Scope *> scopestack; ///< The symbol scope stack
|
vector<const Scope *> scopestack; ///< The symbol scope stack
|
||||||
Scope *curscope; ///< The current symbol scope
|
|
||||||
vector<ReversePolish> revpol; ///< The Reverse Polish Notation (RPN) token stack
|
vector<ReversePolish> revpol; ///< The Reverse Polish Notation (RPN) token stack
|
||||||
vector<NodePending> nodepend; ///< Data-flow nodes waiting to be pushed onto the RPN stack
|
vector<NodePending> nodepend; ///< Data-flow nodes waiting to be pushed onto the RPN stack
|
||||||
int4 pending; ///< Number of data-flow nodes waiting to be pushed
|
int4 pending; ///< Number of data-flow nodes waiting to be pushed
|
||||||
|
@ -240,6 +239,7 @@ private:
|
||||||
string commentend; ///< Delimiter characters (if any) for the end of a comment
|
string commentend; ///< Delimiter characters (if any) for the end of a comment
|
||||||
protected:
|
protected:
|
||||||
Architecture *glb; ///< The Architecture owning the language emitter
|
Architecture *glb; ///< The Architecture owning the language emitter
|
||||||
|
const Scope *curscope; ///< The current symbol scope
|
||||||
CastStrategy *castStrategy; ///< The strategy for emitting explicit \e case operations
|
CastStrategy *castStrategy; ///< The strategy for emitting explicit \e case operations
|
||||||
EmitXml *emit; ///< The low-level token emitter
|
EmitXml *emit; ///< The low-level token emitter
|
||||||
uint4 mods; ///< Currently active printing modifications
|
uint4 mods; ///< Currently active printing modifications
|
||||||
|
@ -251,8 +251,8 @@ protected:
|
||||||
#endif
|
#endif
|
||||||
// Routines that are probably consistent across languages
|
// Routines that are probably consistent across languages
|
||||||
bool isSet(uint4 m) const { return ((mods & m)!=0); } ///< Is the given printing modification active
|
bool isSet(uint4 m) const { return ((mods & m)!=0); } ///< Is the given printing modification active
|
||||||
void pushScope(Scope *sc) { scopestack.push_back(sc); curscope = sc; } ///< Push a new symbol scope
|
void pushScope(const Scope *sc) { scopestack.push_back(sc); curscope = sc; } ///< Push a new symbol scope
|
||||||
void popScope(void) { scopestack.pop_back(); curscope = scopestack.back(); } ///< Pop to the previous symbol scope
|
void popScope(void); ///< Pop to the previous symbol scope
|
||||||
void pushMod(void) { modstack.push_back(mods); } ///< Push current printing modifications to the stack
|
void pushMod(void) { modstack.push_back(mods); } ///< Push current printing modifications to the stack
|
||||||
void popMod(void) { mods = modstack.back(); modstack.pop_back(); } ///< Pop to the previous printing modifications
|
void popMod(void) { mods = modstack.back(); modstack.pop_back(); } ///< Pop to the previous printing modifications
|
||||||
void setMod(uint4 m) { mods |= m; } ///< Activate the given printing modification
|
void setMod(uint4 m) { mods |= m; } ///< Activate the given printing modification
|
||||||
|
@ -405,7 +405,6 @@ public:
|
||||||
CastStrategy *getCastStrategy(void) const { return castStrategy; } ///< Get the casting strategy for the language
|
CastStrategy *getCastStrategy(void) const { return castStrategy; } ///< Get the casting strategy for the language
|
||||||
ostream *getOutputStream(void) const { return emit->getOutputStream(); } ///< Get the output stream being emitted to
|
ostream *getOutputStream(void) const { return emit->getOutputStream(); } ///< Get the output stream being emitted to
|
||||||
void setOutputStream(ostream *t) { emit->setOutputStream(t); } ///< Set the output stream to emit to
|
void setOutputStream(ostream *t) { emit->setOutputStream(t); } ///< Set the output stream to emit to
|
||||||
void setScope(Scope *sc) { curscope = sc; } ///< Set the current Symbol scope
|
|
||||||
void setMaxLineSize(int4 mls) { emit->setMaxLineSize(mls); } ///< Set the maximum number of characters per line
|
void setMaxLineSize(int4 mls) { emit->setMaxLineSize(mls); } ///< Set the maximum number of characters per line
|
||||||
void setIndentIncrement(int4 inc) { emit->setIndentIncrement(inc); } ///< Set the number of characters to indent per level of code nesting
|
void setIndentIncrement(int4 inc) { emit->setIndentIncrement(inc); } ///< Set the number of characters to indent per level of code nesting
|
||||||
void setLineCommentIndent(int4 val); ///< Set the number of characters to indent comment lines
|
void setLineCommentIndent(int4 val); ///< Set the number of characters to indent comment lines
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue