mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Facilitating namespaces in testing
This commit is contained in:
parent
e339d91ffd
commit
d4217fb814
14 changed files with 181 additions and 80 deletions
|
@ -276,16 +276,18 @@ void Architecture::clearAnalysis(Funcdata *fd)
|
||||||
|
|
||||||
/// Symbols do not necessarily need to be available for the decompiler.
|
/// Symbols do not necessarily need to be available for the decompiler.
|
||||||
/// This routine loads all the \e load \e image knows about into the symbol table
|
/// This routine loads all the \e load \e image knows about into the symbol table
|
||||||
void Architecture::readLoaderSymbols(void)
|
/// \param delim is the delimiter separating namespaces from symbol base names
|
||||||
|
void Architecture::readLoaderSymbols(const string &delim)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (loadersymbols_parsed) return; // already read
|
if (loadersymbols_parsed) return; // already read
|
||||||
Scope *scope = symboltab->getGlobalScope();
|
|
||||||
loader->openSymbols();
|
loader->openSymbols();
|
||||||
loadersymbols_parsed = true;
|
loadersymbols_parsed = true;
|
||||||
LoadImageFunc record;
|
LoadImageFunc record;
|
||||||
while(loader->getNextSymbol(record)) {
|
while(loader->getNextSymbol(record)) {
|
||||||
scope->addFunction(record.address,record.name);
|
string basename;
|
||||||
|
Scope *scope = symboltab->findCreateScopeFromSymbolName(record.name, delim, basename, (Scope *)0);
|
||||||
|
scope->addFunction(record.address,basename);
|
||||||
}
|
}
|
||||||
loader->closeSymbols();
|
loader->closeSymbols();
|
||||||
}
|
}
|
||||||
|
@ -324,7 +326,11 @@ SegmentOp *Architecture::getSegmentOp(AddrSpace *spc) const
|
||||||
void Architecture::setPrototype(const PrototypePieces &pieces)
|
void Architecture::setPrototype(const PrototypePieces &pieces)
|
||||||
|
|
||||||
{
|
{
|
||||||
Funcdata *fd = symboltab->getGlobalScope()->queryFunction( pieces.name );
|
string basename;
|
||||||
|
Scope *scope = symboltab->resolveScopeFromSymbolName(pieces.name, "::", basename, (Scope *)0);
|
||||||
|
if (scope == (Scope *)0)
|
||||||
|
throw ParseError("Unknown namespace: " + pieces.name);
|
||||||
|
Funcdata *fd = scope->queryFunction( basename );
|
||||||
if (fd == (Funcdata *)0)
|
if (fd == (Funcdata *)0)
|
||||||
throw ParseError("Unknown function name: " + pieces.name);
|
throw ParseError("Unknown function name: " + pieces.name);
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ public:
|
||||||
int4 getMinimumLanedRegisterSize(void) const; ///< Get the minimum size of a laned register in bytes
|
int4 getMinimumLanedRegisterSize(void) const; ///< Get the minimum size of a laned register in bytes
|
||||||
void setDefaultModel(const string &nm); ///< Set the default PrototypeModel
|
void setDefaultModel(const string &nm); ///< Set the default PrototypeModel
|
||||||
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(const string &delim); ///< 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
|
||||||
SegmentOp *getSegmentOp(AddrSpace *spc) const; ///< Retrieve the \e segment op for the given space if any
|
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
|
||||||
|
|
|
@ -96,7 +96,7 @@ void IfcLoadFile::execute(istream &s)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (capa->getName() == "xml") // If file is xml
|
if (capa->getName() == "xml") // If file is xml
|
||||||
dcp->conf->readLoaderSymbols(); // Read in loader symbols
|
dcp->conf->readLoaderSymbols("::"); // Read in loader symbols
|
||||||
#ifdef OPACTION_DEBUG
|
#ifdef OPACTION_DEBUG
|
||||||
dcp->conf->setDebugStream(status->optr);
|
dcp->conf->setDebugStream(status->optr);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1702,6 +1702,12 @@ bool Scope::isReadOnly(const Address &addr,int4 size,const Address &usepoint) co
|
||||||
return ((flags & Varnode::readonly)!=0);
|
return ((flags & Varnode::readonly)!=0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scope *ScopeInternal::buildSubScope(const string &nm)
|
||||||
|
|
||||||
|
{
|
||||||
|
return new ScopeInternal(nm,glb);
|
||||||
|
}
|
||||||
|
|
||||||
void ScopeInternal::addSymbolInternal(Symbol *sym)
|
void ScopeInternal::addSymbolInternal(Symbol *sym)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -2291,10 +2297,10 @@ void ScopeInternal::findByName(const string &name,vector<Symbol *> &res) const
|
||||||
bool ScopeInternal::isNameUsed(const string &nm,const Scope *op2) const
|
bool ScopeInternal::isNameUsed(const string &nm,const Scope *op2) const
|
||||||
|
|
||||||
{
|
{
|
||||||
Symbol sym((Scope *)0,name,(Datatype *)0);
|
Symbol sym((Scope *)0,nm,(Datatype *)0);
|
||||||
SymbolNameTree::const_iterator iter = nametree.lower_bound(&sym);
|
SymbolNameTree::const_iterator iter = nametree.lower_bound(&sym);
|
||||||
if (iter != nametree.end()) {
|
if (iter != nametree.end()) {
|
||||||
if ((*iter)->getName() == name)
|
if ((*iter)->getName() == nm)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Scope *par = getParent();
|
Scope *par = getParent();
|
||||||
|
@ -2583,6 +2589,23 @@ void ScopeInternal::processHole(const Element *el)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Parse a \<collision> tag indicating a named symbol with no storage or data-type info
|
||||||
|
///
|
||||||
|
/// Let the decompiler know that a name is occupied within the scope for isNameUsed queries, without
|
||||||
|
/// specifying storage and data-type information about the symbol. This is modeled currently by
|
||||||
|
/// creating an unmapped symbol.
|
||||||
|
/// \param el is the \<collision> element
|
||||||
|
void ScopeInternal::processCollision(const Element *el)
|
||||||
|
|
||||||
|
{
|
||||||
|
const string &nm(el->getAttributeValue("name"));
|
||||||
|
SymbolNameTree::const_iterator iter = findFirstByName(nm);
|
||||||
|
if (iter == nametree.end()) {
|
||||||
|
Datatype *ct = glb->types->getBase(1,TYPE_INT);
|
||||||
|
addSymbol(nm,ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Insert a Symbol into the \b nametree
|
/// \brief Insert a Symbol into the \b nametree
|
||||||
///
|
///
|
||||||
/// Duplicate symbol names are allowed for by establishing a deduplication id for the Symbol.
|
/// Duplicate symbol names are allowed for by establishing a deduplication id for the Symbol.
|
||||||
|
@ -2657,6 +2680,8 @@ void ScopeInternal::restoreXml(const Element *el)
|
||||||
}
|
}
|
||||||
else if (subel->getName() == "hole")
|
else if (subel->getName() == "hole")
|
||||||
processHole(subel);
|
processHole(subel);
|
||||||
|
else if (subel->getName() == "collision")
|
||||||
|
processCollision(subel);
|
||||||
else
|
else
|
||||||
throw LowlevelError("Unknown symbollist tag: "+subel->getName());
|
throw LowlevelError("Unknown symbollist tag: "+subel->getName());
|
||||||
++iter2;
|
++iter2;
|
||||||
|
@ -2911,6 +2936,22 @@ void Database::removeRange(Scope *scope,AddrSpace *spc,uintb first,uintb last)
|
||||||
fillResolve(scope);
|
fillResolve(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Look for an immediate child scope by name in a given parent. If does not exist,
|
||||||
|
/// create a new scope with the name and attach it to the parent.
|
||||||
|
/// \param nm is the base name of the desired subscope
|
||||||
|
/// \param parent is the given parent scope to search
|
||||||
|
/// \return the subscope object either found or created
|
||||||
|
Scope *Database::findCreateSubscope(const string &nm,Scope *parent)
|
||||||
|
|
||||||
|
{
|
||||||
|
Scope *res = parent->resolveScope(nm);
|
||||||
|
if (res != (Scope *)0)
|
||||||
|
return res;
|
||||||
|
res = globalscope->buildSubScope(nm);
|
||||||
|
attachScope(res, parent);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/// An \e absolute \e path of Scope names must be provided, from the global
|
/// An \e absolute \e path of Scope names must be provided, from the global
|
||||||
/// Scope down to the desired Scope. If the first path name is blank (""), it
|
/// Scope down to the desired Scope. If the first path name is blank (""), it
|
||||||
/// matches the global Scope. If the first path name is not blank, the
|
/// matches the global Scope. If the first path name is not blank, the
|
||||||
|
@ -2945,7 +2986,7 @@ Scope *Database::resolveScope(const vector<string> &subnames) const
|
||||||
/// \param basename will hold the passed back base Symbol name
|
/// \param basename will hold the passed back base Symbol name
|
||||||
/// \param start is the Scope to start drilling down from, or NULL for the global scope
|
/// \param start is the Scope to start drilling down from, or NULL for the global scope
|
||||||
/// \return the Scope being referred to by the name
|
/// \return the Scope being referred to by the name
|
||||||
Scope *Database::resolveScopeSymbolName(const string &fullname,const string &delim,string &basename,
|
Scope *Database::resolveScopeFromSymbolName(const string &fullname,const string &delim,string &basename,
|
||||||
Scope *start) const
|
Scope *start) const
|
||||||
{
|
{
|
||||||
if (start == (Scope *)0)
|
if (start == (Scope *)0)
|
||||||
|
@ -2966,6 +3007,37 @@ Scope *Database::resolveScopeSymbolName(const string &fullname,const string &del
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Find and/or create Scopes associated with a qualified Symbol name
|
||||||
|
///
|
||||||
|
/// The name is parsed using a \b delimiter that is passed in. The name can
|
||||||
|
/// be only partially qualified by passing in a starting Scope, which the
|
||||||
|
/// name is assumed to be relative to. Otherwise the name is assumed to be
|
||||||
|
/// relative to the global Scope. The unqualified (base) name of the Symbol
|
||||||
|
/// is passed back to the caller. Any missing scope in the path is created.
|
||||||
|
/// \param fullname is the qualified Symbol name
|
||||||
|
/// \param delim is the delimiter separating names
|
||||||
|
/// \param basename will hold the passed back base Symbol name
|
||||||
|
/// \param start is the Scope to start drilling down from, or NULL for the global scope
|
||||||
|
/// \return the Scope being referred to by the name
|
||||||
|
Scope *Database::findCreateScopeFromSymbolName(const string &fullname,const string &delim,string &basename,
|
||||||
|
Scope *start)
|
||||||
|
{
|
||||||
|
if (start == (Scope *)0)
|
||||||
|
start = globalscope;
|
||||||
|
|
||||||
|
string::size_type mark = 0;
|
||||||
|
string::size_type endmark;
|
||||||
|
for(;;) {
|
||||||
|
endmark = fullname.find(delim,mark);
|
||||||
|
if (endmark == string::npos) break;
|
||||||
|
string scopename = fullname.substr(mark,endmark-mark);
|
||||||
|
start = findCreateSubscope(scopename, start);
|
||||||
|
mark = endmark + delim.size();
|
||||||
|
}
|
||||||
|
basename = fullname.substr(mark,endmark);
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Determine the lowest-level Scope which might contain the given address as a Symbol
|
/// \brief Determine the lowest-level Scope which might contain the given address as a Symbol
|
||||||
///
|
///
|
||||||
/// As currently implemented, this method can only find a \e namespace Scope.
|
/// As currently implemented, this method can only find a \e namespace Scope.
|
||||||
|
@ -3114,28 +3186,13 @@ void Database::restoreXml(const Element *el)
|
||||||
|
|
||||||
for(;iter!=list.end();++iter) {
|
for(;iter!=list.end();++iter) {
|
||||||
const Element *subel = *iter;
|
const Element *subel = *iter;
|
||||||
Scope *new_scope;
|
|
||||||
string name;
|
string name;
|
||||||
vector<string> parnames;
|
vector<string> parnames;
|
||||||
parseParentTag(subel,name,parnames);
|
parseParentTag(subel,name,parnames);
|
||||||
parnames.push_back(name);
|
parnames.push_back(name);
|
||||||
new_scope = resolveScope(parnames);
|
Scope *new_scope = globalscope;
|
||||||
if (new_scope == (Scope *)0) {
|
for(int4 i=1;i<parnames.size();++i)
|
||||||
// Scope wasn't pre-existing
|
new_scope = findCreateSubscope(parnames[i], new_scope);
|
||||||
Scope *curscope = globalscope;
|
|
||||||
int4 i;
|
|
||||||
for(i=1;i<parnames.size();++i) {
|
|
||||||
Scope *nextscope = curscope->resolveScope(parnames[i]); // Resolve through any pre-existing scopes
|
|
||||||
if (nextscope == (Scope *)0) break;
|
|
||||||
curscope = nextscope;
|
|
||||||
}
|
|
||||||
while(i != parnames.size()) {
|
|
||||||
new_scope = new ScopeInternal(parnames[i],glb); // Create any new scopes, up to and including
|
|
||||||
attachScope(new_scope,curscope); // the scope represented by this Element
|
|
||||||
curscope = new_scope;
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new_scope->restoreXml(subel);
|
new_scope->restoreXml(subel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -418,7 +418,6 @@ class Scope {
|
||||||
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
|
||||||
void assignId(uint4 val) { uniqueId = val; } ///< Let the database assign a unique id to \b this scope
|
void assignId(uint4 val) { uniqueId = val; } ///< Let the database assign a unique id to \b this scope
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Architecture *glb; ///< Architecture of \b this scope
|
Architecture *glb; ///< Architecture of \b this scope
|
||||||
string name; ///< Name of \b this scope
|
string name; ///< Name of \b this scope
|
||||||
|
@ -453,6 +452,15 @@ protected:
|
||||||
LabSymbol **addrmatch);
|
LabSymbol **addrmatch);
|
||||||
|
|
||||||
const RangeList &getRangeTree(void) const { return rangetree; } ///< Access the address ranges owned by \b this Scope
|
const RangeList &getRangeTree(void) const { return rangetree; } ///< Access the address ranges owned by \b this Scope
|
||||||
|
|
||||||
|
/// \brief Build an unattached Scope to be associated as a sub-scope of \b this
|
||||||
|
///
|
||||||
|
/// This is a Scope object \e factory, intended to be called off of the global scope for building
|
||||||
|
/// global namespace scopes. Function scopes are handled differently.
|
||||||
|
/// \param nm is the name of the new scope
|
||||||
|
/// \return the new Scope object
|
||||||
|
virtual Scope *buildSubScope(const string &nm)=0;
|
||||||
|
|
||||||
virtual void restrictScope(Funcdata *f); ///< Convert \b this to a local Scope
|
virtual void restrictScope(Funcdata *f); ///< Convert \b this to a local Scope
|
||||||
|
|
||||||
// These add/remove range are for scope \b discovery, i.e. we may
|
// These add/remove range are for scope \b discovery, i.e. we may
|
||||||
|
@ -719,9 +727,11 @@ public:
|
||||||
/// a \b maptable, which is a list of rangemaps that own the SymbolEntry objects.
|
/// a \b maptable, which is a list of rangemaps that own the SymbolEntry objects.
|
||||||
class ScopeInternal : public Scope {
|
class ScopeInternal : public Scope {
|
||||||
void processHole(const Element *el);
|
void processHole(const Element *el);
|
||||||
|
void processCollision(const Element *el);
|
||||||
void insertNameTree(Symbol *sym);
|
void insertNameTree(Symbol *sym);
|
||||||
SymbolNameTree::const_iterator findFirstByName(const string &name) const;
|
SymbolNameTree::const_iterator findFirstByName(const string &name) const;
|
||||||
protected:
|
protected:
|
||||||
|
virtual Scope *buildSubScope(const string &nm); ///< Build an unattached Scope to be associated as a sub-scope of \b this
|
||||||
virtual void addSymbolInternal(Symbol *sym);
|
virtual void addSymbolInternal(Symbol *sym);
|
||||||
virtual SymbolEntry *addMapInternal(Symbol *sym,uint4 exfl,const Address &addr,int4 off,int4 sz,const RangeList &uselim);
|
virtual SymbolEntry *addMapInternal(Symbol *sym,uint4 exfl,const Address &addr,int4 off,int4 sz,const RangeList &uselim);
|
||||||
virtual SymbolEntry *addDynamicMapInternal(Symbol *sym,uint4 exfl,uint8 hash,int4 off,int4 sz,
|
virtual SymbolEntry *addDynamicMapInternal(Symbol *sym,uint4 exfl,uint8 hash,int4 off,int4 sz,
|
||||||
|
@ -858,7 +868,9 @@ public:
|
||||||
void removeRange(Scope *scope,AddrSpace *spc,uintb first,uintb last); ///< Remove an address range from \e ownership of a Scope
|
void removeRange(Scope *scope,AddrSpace *spc,uintb first,uintb last); ///< Remove an address range from \e ownership of a Scope
|
||||||
Scope *getGlobalScope(void) const { return globalscope; } ///< Get the global Scope
|
Scope *getGlobalScope(void) const { return globalscope; } ///< Get the global Scope
|
||||||
Scope *resolveScope(const vector<string> &subnames) const; ///< Look-up a Scope by name
|
Scope *resolveScope(const vector<string> &subnames) const; ///< Look-up a Scope by name
|
||||||
Scope *resolveScopeSymbolName(const string &fullname,const string &delim,string &basename,Scope *start) const;
|
Scope *resolveScopeFromSymbolName(const string &fullname,const string &delim,string &basename,Scope *start) const;
|
||||||
|
Scope *findCreateSubscope(const string &nm,Scope *parent); /// Find (and if not found create) a specific subscope
|
||||||
|
Scope *findCreateScopeFromSymbolName(const string &fullname,const string &delim,string &basename,Scope *start);
|
||||||
const Scope *mapScope(const Scope *qpoint,const Address &addr,const Address &usepoint) const;
|
const Scope *mapScope(const Scope *qpoint,const Address &addr,const Address &usepoint) const;
|
||||||
Scope *mapScope(Scope *qpoint,const Address &addr,const Address &usepoint);
|
Scope *mapScope(Scope *qpoint,const Address &addr,const Address &usepoint);
|
||||||
uint4 getProperty(const Address &addr) const { return flagbase.getValue(addr); } ///< Get boolean properties at the given address
|
uint4 getProperty(const Address &addr) const { return flagbase.getValue(addr); } ///< Get boolean properties at the given address
|
||||||
|
|
|
@ -16,6 +16,12 @@
|
||||||
#include "database_ghidra.hh"
|
#include "database_ghidra.hh"
|
||||||
#include "funcdata.hh"
|
#include "funcdata.hh"
|
||||||
|
|
||||||
|
Scope *ScopeGhidra::buildSubScope(const string &nm)
|
||||||
|
|
||||||
|
{
|
||||||
|
return new ScopeGhidraNamespace(nm,ghidra);
|
||||||
|
}
|
||||||
|
|
||||||
/// \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,this)
|
: Scope("",g,this)
|
||||||
|
@ -31,30 +37,6 @@ ScopeGhidra::~ScopeGhidra(void)
|
||||||
delete cache;
|
delete cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ghidra may report that a Symbol is in a \e namespace. This method
|
|
||||||
/// creates a dedicated Scope object to hold such a Symbol. The immediate
|
|
||||||
/// parent for the new Scope must already exist.
|
|
||||||
/// \param nm is the name of the new \e namespace
|
|
||||||
/// \param id is the Ghidra specific id associated with the namespace
|
|
||||||
/// \param par is the parent Scope
|
|
||||||
/// \return the new \e namespace Scope
|
|
||||||
Scope *ScopeGhidra::createNewScope(const string &nm,uint8 id,Scope *par) const
|
|
||||||
|
|
||||||
{
|
|
||||||
Scope *newscope = par->resolveScope(nm);
|
|
||||||
if (newscope != (Scope *)0) {
|
|
||||||
// Its possible because of the way that we merge root namespaces that
|
|
||||||
// Ghidra has distinct namespace ids for namespaces that we want merged
|
|
||||||
// So we return any existing namespace even though the id is different.
|
|
||||||
return newscope;
|
|
||||||
}
|
|
||||||
newscope = new ScopeGhidraNamespace(nm,id,ghidra);
|
|
||||||
ghidra->symboltab->attachScope(newscope,par);
|
|
||||||
if (id != 0)
|
|
||||||
namespaceMap[id] = newscope;
|
|
||||||
return newscope;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The Ghidra client reports a \e namespace id associated with
|
/// The Ghidra client reports a \e namespace id associated with
|
||||||
/// Symbol. Determine if a matching \e namespac Scope already exists in the cache and build
|
/// Symbol. Determine if a matching \e namespac Scope already exists in the cache and build
|
||||||
/// it if it isn't. This may mean creating a new \e namespace Scope.
|
/// it if it isn't. This may mean creating a new \e namespace Scope.
|
||||||
|
@ -85,8 +67,13 @@ Scope *ScopeGhidra::reresolveScope(uint8 id) const
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||||
s >> scopeId;
|
s >> scopeId;
|
||||||
miter = namespaceMap.find(scopeId);
|
miter = namespaceMap.find(scopeId);
|
||||||
if (miter == namespaceMap.end())
|
if (miter == namespaceMap.end()) {
|
||||||
curscope = createNewScope(el->getContent(), scopeId, curscope);
|
curscope = glb->symboltab->findCreateSubscope(el->getContent(), curscope);
|
||||||
|
ScopeGhidraNamespace *ghidraScope = (ScopeGhidraNamespace *)curscope;
|
||||||
|
if (ghidraScope->getClientId() == 0)
|
||||||
|
ghidraScope->setClientId(scopeId);
|
||||||
|
namespaceMap[scopeId] = curscope;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
curscope = (*miter).second;
|
curscope = (*miter).second;
|
||||||
}
|
}
|
||||||
|
@ -428,6 +415,6 @@ bool ScopeGhidraNamespace::isNameUsed(const string &nm,const Scope *op2) const
|
||||||
if (ArchitectureGhidra::isDynamicSymbolName(nm))
|
if (ArchitectureGhidra::isDynamicSymbolName(nm))
|
||||||
return false; // Just assume default FUN_ and DAT_ names don't collide
|
return false; // Just assume default FUN_ and DAT_ names don't collide
|
||||||
const ScopeGhidraNamespace *otherScope = dynamic_cast<const ScopeGhidraNamespace *>(op2);
|
const ScopeGhidraNamespace *otherScope = dynamic_cast<const ScopeGhidraNamespace *>(op2);
|
||||||
uint8 otherId = (otherScope != (const ScopeGhidraNamespace *)0) ? otherScope->getId() : 0;
|
uint8 otherId = (otherScope != (const ScopeGhidraNamespace *)0) ? otherScope->getClientId() : 0;
|
||||||
return ghidra->isNameUsed(nm, scopeId, otherId);
|
return ghidra->isNameUsed(nm, scopeId, otherId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,12 +43,12 @@ class ScopeGhidra : public Scope {
|
||||||
Symbol *dump2Cache(Document *doc) const; ///< Parse a response into the cache
|
Symbol *dump2Cache(Document *doc) const; ///< Parse a response into the cache
|
||||||
Symbol *removeQuery(const Address &addr) const; ///< Process a query that missed the cache
|
Symbol *removeQuery(const Address &addr) const; ///< Process a query that missed the cache
|
||||||
void processHole(const Element *el) const; ///< Process a response describing a hole
|
void processHole(const Element *el) const; ///< Process a response describing a hole
|
||||||
Scope *createNewScope(const string &nm,uint8 id,Scope *par) const; ///< Create a global \e namespace Scope
|
|
||||||
Scope *reresolveScope(uint8 id) const; ///< Find the Scope that will contain a result Symbol
|
Scope *reresolveScope(uint8 id) const; ///< Find the Scope that will contain a result Symbol
|
||||||
virtual void addRange(AddrSpace *spc,uintb first,uintb last);
|
virtual void addRange(AddrSpace *spc,uintb first,uintb last);
|
||||||
virtual void removeRange(AddrSpace *spc,uintb first,uintb last) {
|
virtual void removeRange(AddrSpace *spc,uintb first,uintb last) {
|
||||||
throw LowlevelError("remove_range should not be performed on ghidra scope");
|
throw LowlevelError("remove_range should not be performed on ghidra scope");
|
||||||
}
|
}
|
||||||
|
virtual Scope *buildSubScope(const string &nm);
|
||||||
virtual void addSymbolInternal(Symbol *sym) { throw LowlevelError("add_symbol_internal unimplemented"); }
|
virtual void addSymbolInternal(Symbol *sym) { throw LowlevelError("add_symbol_internal unimplemented"); }
|
||||||
virtual SymbolEntry *addMapInternal(Symbol *sym,uint4 exfl,const Address &addr,int4 off,int4 sz,
|
virtual SymbolEntry *addMapInternal(Symbol *sym,uint4 exfl,const Address &addr,int4 off,int4 sz,
|
||||||
const RangeList &uselim) { throw LowlevelError("addMap unimplemented"); }
|
const RangeList &uselim) { throw LowlevelError("addMap unimplemented"); }
|
||||||
|
@ -125,15 +125,18 @@ public:
|
||||||
/// be a ScopeGhidra. This will query the Ghidra client on behalf of the \e namespace and
|
/// be a ScopeGhidra. This will query the Ghidra client on behalf of the \e namespace and
|
||||||
/// register any new symbols with \b this Scope.
|
/// register any new symbols with \b this Scope.
|
||||||
class ScopeGhidraNamespace : public ScopeInternal {
|
class ScopeGhidraNamespace : public ScopeInternal {
|
||||||
|
friend class ScopeGhidra;
|
||||||
ArchitectureGhidra *ghidra; ///< Connection to the Ghidra client
|
ArchitectureGhidra *ghidra; ///< Connection to the Ghidra client
|
||||||
uint8 scopeId; ///< Internal id allowing Ghidra client to reference formal namespaces
|
uint8 scopeId; ///< Internal id allowing Ghidra client to reference formal namespaces
|
||||||
|
void setClientId(uint8 id) { scopeId = id; }
|
||||||
|
protected:
|
||||||
virtual SymbolEntry *addMapInternal(Symbol *sym,uint4 exfl,const Address &addr,int4 off,int4 sz,
|
virtual SymbolEntry *addMapInternal(Symbol *sym,uint4 exfl,const Address &addr,int4 off,int4 sz,
|
||||||
const RangeList &uselim);
|
const RangeList &uselim);
|
||||||
public:
|
public:
|
||||||
ScopeGhidraNamespace(const string &nm,uint8 id,ArchitectureGhidra *g)
|
ScopeGhidraNamespace(const string &nm,ArchitectureGhidra *g)
|
||||||
: ScopeInternal(nm,g) { ghidra = g; scopeId = id; } ///< Constructor
|
: ScopeInternal(nm,g) { ghidra = g; scopeId = 0; } ///< Constructor
|
||||||
|
|
||||||
uint8 getId(void) const { return scopeId; } ///< Get the Ghidra specific id
|
uint8 getClientId(void) const { return scopeId; } ///< Get the Ghidra specific id
|
||||||
virtual bool isNameUsed(const string &nm,const Scope *op2) const;
|
virtual bool isNameUsed(const string &nm,const Scope *op2) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -524,7 +524,7 @@ uint4 GrammarLexer::moveState(char lookahead)
|
||||||
}
|
}
|
||||||
else if ((lookahead>='a')&&(lookahead<='z')) {
|
else if ((lookahead>='a')&&(lookahead<='z')) {
|
||||||
}
|
}
|
||||||
else if (lookahead == '_') {
|
else if (lookahead == '_' || lookahead == ':') {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
state = start;
|
state = start;
|
||||||
|
|
|
@ -393,7 +393,7 @@ void IfcFuncload::execute(istream &s)
|
||||||
throw IfaceExecutionError("No image loaded");
|
throw IfaceExecutionError("No image loaded");
|
||||||
|
|
||||||
string basename;
|
string basename;
|
||||||
Scope *funcscope = dcp->conf->symboltab->resolveScopeSymbolName(funcname,"::",basename,(Scope *)0);
|
Scope *funcscope = dcp->conf->symboltab->resolveScopeFromSymbolName(funcname,"::",basename,(Scope *)0);
|
||||||
if (funcscope == (Scope *)0)
|
if (funcscope == (Scope *)0)
|
||||||
throw IfaceExecutionError("Bad namespace: "+funcname);
|
throw IfaceExecutionError("Bad namespace: "+funcname);
|
||||||
dcp->fd = funcscope->queryFunction( basename ); // Is function already in database
|
dcp->fd = funcscope->queryFunction( basename ); // Is function already in database
|
||||||
|
@ -438,7 +438,7 @@ void IfcReadSymbols::execute(istream &s)
|
||||||
if (dcp->conf->loader == (LoadImage *)0)
|
if (dcp->conf->loader == (LoadImage *)0)
|
||||||
throw IfaceExecutionError("No binary loaded");
|
throw IfaceExecutionError("No binary loaded");
|
||||||
|
|
||||||
dcp->conf->readLoaderSymbols();
|
dcp->conf->readLoaderSymbols("::");
|
||||||
}
|
}
|
||||||
|
|
||||||
void IfcMapaddress::execute(istream &s)
|
void IfcMapaddress::execute(istream &s)
|
||||||
|
@ -460,11 +460,18 @@ void IfcMapaddress::execute(istream &s)
|
||||||
Symbol *sym;
|
Symbol *sym;
|
||||||
uint4 flags = Varnode::namelock|Varnode::typelock;
|
uint4 flags = Varnode::namelock|Varnode::typelock;
|
||||||
flags |= dcp->conf->symboltab->getProperty(addr); // Inherit existing properties
|
flags |= dcp->conf->symboltab->getProperty(addr); // Inherit existing properties
|
||||||
sym = dcp->conf->symboltab->getGlobalScope()->addSymbol(name,ct,addr,Address())->getSymbol();
|
string basename;
|
||||||
|
Scope *scope = dcp->conf->symboltab->findCreateScopeFromSymbolName(name, "::", basename, (Scope *)0);
|
||||||
|
sym = scope->addSymbol(basename,ct,addr,Address())->getSymbol();
|
||||||
sym->getScope()->setAttribute(sym,flags);
|
sym->getScope()->setAttribute(sym,flags);
|
||||||
|
if (scope->getParent() != (Scope *)0) { // If this is a global namespace scope
|
||||||
|
SymbolEntry *e = sym->getFirstWholeMap(); // Adjust range
|
||||||
|
dcp->conf->symboltab->addRange(scope,e->getAddr().getSpace(),e->getFirst(),e->getLast());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void IfcMaphash::execute(istream &s)
|
void IfcMaphash::execute(istream &s)
|
||||||
|
|
||||||
{ // Add a dynamic entry to the current function's symbol table given a known hash and pc address
|
{ // Add a dynamic entry to the current function's symbol table given a known hash and pc address
|
||||||
|
@ -497,7 +504,9 @@ void IfcMapfunction::execute(istream &s)
|
||||||
s >> name; // Read optional name
|
s >> name; // Read optional name
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
dcp->conf->nameFunction(addr,name); // Pick default name if necessary
|
dcp->conf->nameFunction(addr,name); // Pick default name if necessary
|
||||||
dcp->fd = dcp->conf->symboltab->getGlobalScope()->addFunction(addr,name)->getFunction();
|
string basename;
|
||||||
|
Scope *scope = dcp->conf->symboltab->findCreateScopeFromSymbolName(name, "::", basename, (Scope *)0);
|
||||||
|
dcp->fd = scope->addFunction(addr,name)->getFunction();
|
||||||
|
|
||||||
string nocode;
|
string nocode;
|
||||||
s >> ws >> nocode;
|
s >> ws >> nocode;
|
||||||
|
@ -1774,18 +1783,15 @@ void IfcPrintMap::execute(istream &s)
|
||||||
|
|
||||||
if (dcp->conf == (Architecture *)0)
|
if (dcp->conf == (Architecture *)0)
|
||||||
throw IfaceExecutionError("No load image");
|
throw IfaceExecutionError("No load image");
|
||||||
if ((name=="global")||(dcp->fd==(Funcdata *)0)) {
|
if (name.size() != 0 || dcp->fd==(Funcdata *)0) {
|
||||||
scope = dcp->conf->symboltab->getGlobalScope();
|
string fullname = name + "::a"; // Add fake variable name
|
||||||
name = "";
|
scope = dcp->conf->symboltab->resolveScopeFromSymbolName(fullname, "::", fullname, (Scope *)0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
scope = dcp->fd->getScopeLocal();
|
scope = dcp->fd->getScopeLocal();
|
||||||
|
|
||||||
if (name.size() != 0) {
|
|
||||||
scope = scope->resolveScope(name);
|
|
||||||
if (scope == (Scope *)0)
|
if (scope == (Scope *)0)
|
||||||
throw IfaceExecutionError("No map named: "+name);
|
throw IfaceExecutionError("No map named: "+name);
|
||||||
}
|
|
||||||
|
|
||||||
*status->fileoptr << scope->getFullName() << endl;
|
*status->fileoptr << scope->getFullName() << endl;
|
||||||
scope->printBounds(*status->fileoptr);
|
scope->printBounds(*status->fileoptr);
|
||||||
|
|
|
@ -46,6 +46,20 @@ PrintJava::PrintJava(Architecture *glb,const string &nm) : PrintC(glb,nm)
|
||||||
castStrategy = new CastStrategyJava();
|
castStrategy = new CastStrategyJava();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrintJava::docFunction(const Funcdata *fd)
|
||||||
|
|
||||||
|
{
|
||||||
|
bool singletonFunction = false;
|
||||||
|
if (curscope == (const Scope *)0) {
|
||||||
|
singletonFunction = true;
|
||||||
|
// Always assume we are in the scope of the parent class
|
||||||
|
pushScope(fd->getScopeLocal()->getParent());
|
||||||
|
}
|
||||||
|
PrintC::docFunction(fd);
|
||||||
|
if (singletonFunction)
|
||||||
|
popScope();
|
||||||
|
}
|
||||||
|
|
||||||
/// Print a data-type up to the identifier, store off array sizes
|
/// Print a data-type up to the identifier, store off array sizes
|
||||||
/// for printing after the identifier. Find the root type (the one with an identifier)
|
/// for printing after the identifier. Find the root type (the one with an identifier)
|
||||||
/// and the count number of wrapping arrays.
|
/// and the count number of wrapping arrays.
|
||||||
|
|
|
@ -59,6 +59,7 @@ class PrintJava : public PrintC {
|
||||||
virtual void printUnicode(ostream &s,int4 onechar) const;
|
virtual void printUnicode(ostream &s,int4 onechar) const;
|
||||||
public:
|
public:
|
||||||
PrintJava(Architecture *g,const string &nm="java-language"); ///< Constructor
|
PrintJava(Architecture *g,const string &nm="java-language"); ///< Constructor
|
||||||
|
virtual void docFunction(const Funcdata *fd);
|
||||||
virtual void pushTypeStart(const Datatype *ct,bool noident);
|
virtual void pushTypeStart(const Datatype *ct,bool noident);
|
||||||
virtual void pushTypeEnd(const Datatype *ct);
|
virtual void pushTypeEnd(const Datatype *ct);
|
||||||
virtual bool doEmitWideCharPrefix(void) const { return false; }
|
virtual bool doEmitWideCharPrefix(void) const { return false; }
|
||||||
|
|
|
@ -563,7 +563,7 @@ public class DecompileCallback {
|
||||||
int pathSize = 0;
|
int pathSize = 0;
|
||||||
Namespace curspace = namespace;
|
Namespace curspace = namespace;
|
||||||
long curId = namespace.getID();
|
long curId = namespace.getID();
|
||||||
while (curId != stopId && curId != 0) {
|
while (curId != stopId && curId != 0 && !(curspace instanceof Library)) {
|
||||||
pathSize += 1;
|
pathSize += 1;
|
||||||
curspace = curspace.getParentNamespace();
|
curspace = curspace.getParentNamespace();
|
||||||
curId = curspace.getID();
|
curId = curspace.getID();
|
||||||
|
@ -592,6 +592,9 @@ public class DecompileCallback {
|
||||||
}
|
}
|
||||||
for (int i = 0; i < pathSize; ++i) {
|
for (int i = 0; i < pathSize; ++i) {
|
||||||
if (path[i] == id) {
|
if (path[i] == id) {
|
||||||
|
if (debug != null) {
|
||||||
|
debug.nameIsUsed(symSpace, name);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -677,6 +677,14 @@ public class DecompileDebug {
|
||||||
cpool.add(buf.toString());
|
cpool.add(buf.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void nameIsUsed(Namespace spc, String nm) {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
buffer.append("<collision");
|
||||||
|
SpecXmlUtils.xmlEscapeAttribute(buffer, "name", nm);
|
||||||
|
buffer.append("/>\n");
|
||||||
|
getMapped(spc, buffer.toString());
|
||||||
|
}
|
||||||
|
|
||||||
public void addFlowOverride(Address addr,FlowOverride fo) {
|
public void addFlowOverride(Address addr,FlowOverride fo) {
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
buf.append("<flow type=\"");
|
buf.append("<flow type=\"");
|
||||||
|
|
|
@ -89,18 +89,22 @@ final public class DexAnalysisState implements AnalysisState {
|
||||||
* @return the EncodedMethod
|
* @return the EncodedMethod
|
||||||
*/
|
*/
|
||||||
public EncodedMethod getEncodedMethod(Address addr) {
|
public EncodedMethod getEncodedMethod(Address addr) {
|
||||||
|
synchronized (this) {
|
||||||
if (methodMap == null) {
|
if (methodMap == null) {
|
||||||
buildMethodMap();
|
buildMethodMap();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return methodMap.get(addr);
|
return methodMap.get(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return persistent <code>DexAnalysisState</code> which corresponds to the specified program instance.
|
* Return persistent <code>DexAnalysisState</code> which corresponds to the specified program instance.
|
||||||
* @param program
|
* @param program is the specified program instance
|
||||||
* @return <code>DexAnalysisState</code> for specified program instance
|
* @return <code>DexAnalysisState</code> for specified program instance
|
||||||
|
* @throws IOException if there are problems during construction of the state object
|
||||||
*/
|
*/
|
||||||
public static DexAnalysisState getState(Program program) throws IOException {
|
public synchronized static DexAnalysisState getState(Program program) throws IOException {
|
||||||
DexAnalysisState analysisState =
|
DexAnalysisState analysisState =
|
||||||
AnalysisStateInfo.getAnalysisState(program, DexAnalysisState.class);
|
AnalysisStateInfo.getAnalysisState(program, DexAnalysisState.class);
|
||||||
if (analysisState == null) {
|
if (analysisState == null) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue