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.
|
||||
/// 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
|
||||
Scope *scope = symboltab->getGlobalScope();
|
||||
loader->openSymbols();
|
||||
loadersymbols_parsed = true;
|
||||
LoadImageFunc 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();
|
||||
}
|
||||
|
@ -324,7 +326,11 @@ SegmentOp *Architecture::getSegmentOp(AddrSpace *spc) const
|
|||
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)
|
||||
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
|
||||
void setDefaultModel(const string &nm); ///< Set the default PrototypeModel
|
||||
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
|
||||
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
|
||||
|
|
|
@ -96,7 +96,7 @@ void IfcLoadFile::execute(istream &s)
|
|||
return;
|
||||
}
|
||||
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
|
||||
dcp->conf->setDebugStream(status->optr);
|
||||
#endif
|
||||
|
|
|
@ -1702,6 +1702,12 @@ bool Scope::isReadOnly(const Address &addr,int4 size,const Address &usepoint) co
|
|||
return ((flags & Varnode::readonly)!=0);
|
||||
}
|
||||
|
||||
Scope *ScopeInternal::buildSubScope(const string &nm)
|
||||
|
||||
{
|
||||
return new ScopeInternal(nm,glb);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
{
|
||||
Symbol sym((Scope *)0,name,(Datatype *)0);
|
||||
Symbol sym((Scope *)0,nm,(Datatype *)0);
|
||||
SymbolNameTree::const_iterator iter = nametree.lower_bound(&sym);
|
||||
if (iter != nametree.end()) {
|
||||
if ((*iter)->getName() == name)
|
||||
if ((*iter)->getName() == nm)
|
||||
return true;
|
||||
}
|
||||
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
|
||||
///
|
||||
/// 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")
|
||||
processHole(subel);
|
||||
else if (subel->getName() == "collision")
|
||||
processCollision(subel);
|
||||
else
|
||||
throw LowlevelError("Unknown symbollist tag: "+subel->getName());
|
||||
++iter2;
|
||||
|
@ -2911,6 +2936,22 @@ void Database::removeRange(Scope *scope,AddrSpace *spc,uintb first,uintb last)
|
|||
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
|
||||
/// 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
|
||||
|
@ -2945,7 +2986,7 @@ Scope *Database::resolveScope(const vector<string> &subnames) const
|
|||
/// \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::resolveScopeSymbolName(const string &fullname,const string &delim,string &basename,
|
||||
Scope *Database::resolveScopeFromSymbolName(const string &fullname,const string &delim,string &basename,
|
||||
Scope *start) const
|
||||
{
|
||||
if (start == (Scope *)0)
|
||||
|
@ -2966,6 +3007,37 @@ Scope *Database::resolveScopeSymbolName(const string &fullname,const string &del
|
|||
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
|
||||
///
|
||||
/// 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) {
|
||||
const Element *subel = *iter;
|
||||
Scope *new_scope;
|
||||
string name;
|
||||
vector<string> parnames;
|
||||
parseParentTag(subel,name,parnames);
|
||||
parnames.push_back(name);
|
||||
new_scope = resolveScope(parnames);
|
||||
if (new_scope == (Scope *)0) {
|
||||
// Scope wasn't pre-existing
|
||||
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;
|
||||
}
|
||||
}
|
||||
Scope *new_scope = globalscope;
|
||||
for(int4 i=1;i<parnames.size();++i)
|
||||
new_scope = findCreateSubscope(parnames[i], new_scope);
|
||||
new_scope->restoreXml(subel);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -418,7 +418,6 @@ class Scope {
|
|||
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 assignId(uint4 val) { uniqueId = val; } ///< Let the database assign a unique id to \b this scope
|
||||
|
||||
protected:
|
||||
Architecture *glb; ///< Architecture of \b this scope
|
||||
string name; ///< Name of \b this scope
|
||||
|
@ -453,6 +452,15 @@ protected:
|
|||
LabSymbol **addrmatch);
|
||||
|
||||
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
|
||||
|
||||
// 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.
|
||||
class ScopeInternal : public Scope {
|
||||
void processHole(const Element *el);
|
||||
void processCollision(const Element *el);
|
||||
void insertNameTree(Symbol *sym);
|
||||
SymbolNameTree::const_iterator findFirstByName(const string &name) const;
|
||||
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 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,
|
||||
|
@ -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
|
||||
Scope *getGlobalScope(void) const { return globalscope; } ///< Get the global Scope
|
||||
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;
|
||||
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
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
#include "database_ghidra.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
|
||||
ScopeGhidra::ScopeGhidra(ArchitectureGhidra *g)
|
||||
: Scope("",g,this)
|
||||
|
@ -31,30 +37,6 @@ ScopeGhidra::~ScopeGhidra(void)
|
|||
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
|
||||
/// 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.
|
||||
|
@ -85,8 +67,13 @@ Scope *ScopeGhidra::reresolveScope(uint8 id) const
|
|||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> scopeId;
|
||||
miter = namespaceMap.find(scopeId);
|
||||
if (miter == namespaceMap.end())
|
||||
curscope = createNewScope(el->getContent(), scopeId, curscope);
|
||||
if (miter == namespaceMap.end()) {
|
||||
curscope = glb->symboltab->findCreateSubscope(el->getContent(), curscope);
|
||||
ScopeGhidraNamespace *ghidraScope = (ScopeGhidraNamespace *)curscope;
|
||||
if (ghidraScope->getClientId() == 0)
|
||||
ghidraScope->setClientId(scopeId);
|
||||
namespaceMap[scopeId] = curscope;
|
||||
}
|
||||
else
|
||||
curscope = (*miter).second;
|
||||
}
|
||||
|
@ -428,6 +415,6 @@ bool ScopeGhidraNamespace::isNameUsed(const string &nm,const Scope *op2) const
|
|||
if (ArchitectureGhidra::isDynamicSymbolName(nm))
|
||||
return false; // Just assume default FUN_ and DAT_ names don't collide
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -43,12 +43,12 @@ class ScopeGhidra : public Scope {
|
|||
Symbol *dump2Cache(Document *doc) const; ///< Parse a response into 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
|
||||
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
|
||||
virtual void addRange(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");
|
||||
}
|
||||
virtual Scope *buildSubScope(const string &nm);
|
||||
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,
|
||||
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
|
||||
/// register any new symbols with \b this Scope.
|
||||
class ScopeGhidraNamespace : public ScopeInternal {
|
||||
friend class ScopeGhidra;
|
||||
ArchitectureGhidra *ghidra; ///< Connection to the Ghidra client
|
||||
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,
|
||||
const RangeList &uselim);
|
||||
public:
|
||||
ScopeGhidraNamespace(const string &nm,uint8 id,ArchitectureGhidra *g)
|
||||
: ScopeInternal(nm,g) { ghidra = g; scopeId = id; } ///< Constructor
|
||||
ScopeGhidraNamespace(const string &nm,ArchitectureGhidra *g)
|
||||
: 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;
|
||||
};
|
||||
|
||||
|
|
|
@ -524,7 +524,7 @@ uint4 GrammarLexer::moveState(char lookahead)
|
|||
}
|
||||
else if ((lookahead>='a')&&(lookahead<='z')) {
|
||||
}
|
||||
else if (lookahead == '_') {
|
||||
else if (lookahead == '_' || lookahead == ':') {
|
||||
}
|
||||
else {
|
||||
state = start;
|
||||
|
|
|
@ -393,7 +393,7 @@ void IfcFuncload::execute(istream &s)
|
|||
throw IfaceExecutionError("No image loaded");
|
||||
|
||||
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)
|
||||
throw IfaceExecutionError("Bad namespace: "+funcname);
|
||||
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)
|
||||
throw IfaceExecutionError("No binary loaded");
|
||||
|
||||
dcp->conf->readLoaderSymbols();
|
||||
dcp->conf->readLoaderSymbols("::");
|
||||
}
|
||||
|
||||
void IfcMapaddress::execute(istream &s)
|
||||
|
@ -460,11 +460,18 @@ void IfcMapaddress::execute(istream &s)
|
|||
Symbol *sym;
|
||||
uint4 flags = Varnode::namelock|Varnode::typelock;
|
||||
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);
|
||||
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)
|
||||
|
||||
{ // 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
|
||||
if (name.empty())
|
||||
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;
|
||||
s >> ws >> nocode;
|
||||
|
@ -1774,18 +1783,15 @@ void IfcPrintMap::execute(istream &s)
|
|||
|
||||
if (dcp->conf == (Architecture *)0)
|
||||
throw IfaceExecutionError("No load image");
|
||||
if ((name=="global")||(dcp->fd==(Funcdata *)0)) {
|
||||
scope = dcp->conf->symboltab->getGlobalScope();
|
||||
name = "";
|
||||
if (name.size() != 0 || dcp->fd==(Funcdata *)0) {
|
||||
string fullname = name + "::a"; // Add fake variable name
|
||||
scope = dcp->conf->symboltab->resolveScopeFromSymbolName(fullname, "::", fullname, (Scope *)0);
|
||||
}
|
||||
else
|
||||
scope = dcp->fd->getScopeLocal();
|
||||
|
||||
if (name.size() != 0) {
|
||||
scope = scope->resolveScope(name);
|
||||
if (scope == (Scope *)0)
|
||||
throw IfaceExecutionError("No map named: "+name);
|
||||
}
|
||||
|
||||
*status->fileoptr << scope->getFullName() << endl;
|
||||
scope->printBounds(*status->fileoptr);
|
||||
|
|
|
@ -46,6 +46,20 @@ PrintJava::PrintJava(Architecture *glb,const string &nm) : PrintC(glb,nm)
|
|||
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
|
||||
/// for printing after the identifier. Find the root type (the one with an identifier)
|
||||
/// and the count number of wrapping arrays.
|
||||
|
|
|
@ -59,6 +59,7 @@ class PrintJava : public PrintC {
|
|||
virtual void printUnicode(ostream &s,int4 onechar) const;
|
||||
public:
|
||||
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 pushTypeEnd(const Datatype *ct);
|
||||
virtual bool doEmitWideCharPrefix(void) const { return false; }
|
||||
|
|
|
@ -563,7 +563,7 @@ public class DecompileCallback {
|
|||
int pathSize = 0;
|
||||
Namespace curspace = namespace;
|
||||
long curId = namespace.getID();
|
||||
while (curId != stopId && curId != 0) {
|
||||
while (curId != stopId && curId != 0 && !(curspace instanceof Library)) {
|
||||
pathSize += 1;
|
||||
curspace = curspace.getParentNamespace();
|
||||
curId = curspace.getID();
|
||||
|
@ -592,6 +592,9 @@ public class DecompileCallback {
|
|||
}
|
||||
for (int i = 0; i < pathSize; ++i) {
|
||||
if (path[i] == id) {
|
||||
if (debug != null) {
|
||||
debug.nameIsUsed(symSpace, name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -677,6 +677,14 @@ public class DecompileDebug {
|
|||
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) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("<flow type=\"");
|
||||
|
|
|
@ -89,18 +89,22 @@ final public class DexAnalysisState implements AnalysisState {
|
|||
* @return the EncodedMethod
|
||||
*/
|
||||
public EncodedMethod getEncodedMethod(Address addr) {
|
||||
synchronized (this) {
|
||||
if (methodMap == null) {
|
||||
buildMethodMap();
|
||||
|
||||
}
|
||||
}
|
||||
return methodMap.get(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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 =
|
||||
AnalysisStateInfo.getAnalysisState(program, DexAnalysisState.class);
|
||||
if (analysisState == null) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue