New Symbol id strategy

This commit is contained in:
caheckman 2019-12-03 10:16:24 -05:00
parent 4560f78833
commit a5ae6e21b0
13 changed files with 302 additions and 163 deletions

View file

@ -17,6 +17,8 @@
#include "funcdata.hh" #include "funcdata.hh"
#include <ctype.h> #include <ctype.h>
uint8 Symbol::ID_BASE = 0x4000000000000000L;
/// This SymbolEntry is unintegrated. An address or hash must be provided /// This SymbolEntry is unintegrated. An address or hash must be provided
/// either directly or via restoreXml(). /// either directly or via restoreXml().
/// \param sym is the Symbol \b this will be a map for /// \param sym is the Symbol \b this will be a map for
@ -338,39 +340,19 @@ void Symbol::restoreXmlHeader(const Element *el)
{ {
name.clear(); name.clear();
category = -1; category = -1;
symbolId = 0;
for(int4 i=0;i<el->getNumAttributes();++i) { for(int4 i=0;i<el->getNumAttributes();++i) {
if (el->getAttributeName(i)=="name") const string &attName(el->getAttributeName(i));
name = el->getAttributeValue(i); switch (attName[0]) {
else if (el->getAttributeName(i)=="cat") { case 'c':
istringstream s(el->getAttributeValue("cat")); if (attName == "cat") {
istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct); s.unsetf(ios::dec | ios::hex | ios::oct);
s >> category; s >> category;
} }
else if (el->getAttributeName(i)=="namelock") { break;
if (xml_readbool(el->getAttributeValue(i))) case 'f':
flags |= Varnode::namelock; if (attName == "format") {
}
else if (el->getAttributeName(i)=="typelock") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= Varnode::typelock;
}
else if (el->getAttributeName(i)=="readonly") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= Varnode::readonly;
}
else if (el->getAttributeName(i)=="volatile") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= Varnode::volatil;
}
else if (el->getAttributeName(i)=="indirectstorage") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= Varnode::indirectstorage;
}
else if (el->getAttributeName(i)=="hiddenretparm") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= Varnode::hiddenretparm;
}
else if (el->getAttributeName(i)=="format") {
const string &formString(el->getAttributeValue(i)); const string &formString(el->getAttributeValue(i));
if (formString == "hex") if (formString == "hex")
dispflags |= Symbol::force_hex; dispflags |= Symbol::force_hex;
@ -383,6 +365,55 @@ void Symbol::restoreXmlHeader(const Element *el)
else if (formString == "bin") else if (formString == "bin")
dispflags |= Symbol::force_bin; dispflags |= Symbol::force_bin;
} }
break;
case 'h':
if (attName == "hiddenretparm") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= Varnode::hiddenretparm;
}
break;
case 'i':
if (attName == "id") {
istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> symbolId;
if ((symbolId >> 56) == (ID_BASE >> 56))
symbolId = 0; // Don't keep old internal id's
}
else if (attName == "indirectstorage") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= Varnode::indirectstorage;
}
break;
case 'n':
if (attName == "name")
name = el->getAttributeValue(i);
else if (attName == "namelock") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= Varnode::namelock;
}
break;
case 'r':
if (attName == "readonly") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= Varnode::readonly;
}
break;
case 't':
if (attName == "typelock") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= Varnode::typelock;
}
break;
case 'v':
if (attName == "volatile") {
if (xml_readbool(el->getAttributeValue(i)))
flags |= Varnode::volatil;
}
break;
default:
break;
}
} }
if (category == 0) { if (category == 0) {
istringstream s2(el->getAttributeValue("index")); istringstream s2(el->getAttributeValue("index"));
@ -716,7 +747,7 @@ void Scope::attachScope(Scope *child)
{ {
child->parent = this; child->parent = this;
pair<const ScopeKey,Scope *> value(ScopeKey(child->name,child->dedupId),child); pair<const ScopeKey,Scope *> value(ScopeKey(child->name,child->uniqueId),child);
pair<ScopeMap::iterator,bool> res; pair<ScopeMap::iterator,bool> res;
if (child->name.size()==0) if (child->name.size()==0)
throw LowlevelError("Non-global scope has empty name"); throw LowlevelError("Non-global scope has empty name");
@ -1574,6 +1605,10 @@ bool Scope::isReadOnly(const Address &addr,int4 size,const Address &usepoint) co
void ScopeInternal::addSymbolInternal(Symbol *sym) void ScopeInternal::addSymbolInternal(Symbol *sym)
{ {
if (sym->symbolId == 0) {
sym->symbolId = Symbol::ID_BASE + (((uint8)uniqueId & 0xffff) << 40) + nextUniqueId;
nextUniqueId += 1;
}
try { try {
if (sym->name.size() == 0) if (sym->name.size() == 0)
sym->name = buildUndefinedName(); sym->name = buildUndefinedName();
@ -1695,6 +1730,7 @@ list<SymbolEntry>::iterator ScopeInternal::endDynamic(void)
ScopeInternal::ScopeInternal(const string &nm,Architecture *g) ScopeInternal::ScopeInternal(const string &nm,Architecture *g)
: Scope(nm,g) : Scope(nm,g)
{ {
nextUniqueId = 0;
int4 numspaces = g->numSpaces(); int4 numspaces = g->numSpaces();
for(int4 i=0;i<numspaces;++i) for(int4 i=0;i<numspaces;++i)
maptable.push_back((EntryMap *)0); maptable.push_back((EntryMap *)0);
@ -1725,6 +1761,7 @@ void ScopeInternal::clear(void)
Symbol *sym = *iter++; Symbol *sym = *iter++;
removeSymbol(sym); removeSymbol(sym);
} }
nextUniqueId = 0;
} }
/// Look for NULL entries in the category tables. If there are, /// Look for NULL entries in the category tables. If there are,
@ -2619,9 +2656,12 @@ void Database::attachScope(Scope *newscope,Scope *parent)
throw LowlevelError("Multiple global scopes"); throw LowlevelError("Multiple global scopes");
if (newscope->name.size() != 0) if (newscope->name.size() != 0)
throw LowlevelError("Global scope does not have empty name"); throw LowlevelError("Global scope does not have empty name");
newscope->assignId(0);
globalscope = newscope; globalscope = newscope;
return; return;
} }
newscope->assignId(nextScopeId);
nextScopeId += 1;
parent->attachScope(newscope); parent->attachScope(newscope);
} }
@ -2635,7 +2675,7 @@ void Database::deleteScope(Scope *scope)
delete scope; delete scope;
} }
else { else {
ScopeKey key(scope->name,scope->dedupId); ScopeKey key(scope->name,scope->uniqueId);
ScopeMap::iterator iter = scope->parent->children.find(key); ScopeMap::iterator iter = scope->parent->children.find(key);
if (iter == scope->parent->children.end()) if (iter == scope->parent->children.end())
throw LowlevelError("Could not remove parent reference to: "+scope->name); throw LowlevelError("Could not remove parent reference to: "+scope->name);

View file

@ -157,17 +157,19 @@ class Symbol {
protected: protected:
Scope *scope; ///< The scope that owns this symbol Scope *scope; ///< The scope that owns this symbol
string name; ///< The local name of the symbol string name; ///< The local name of the symbol
uint4 nameDedup; ///< id to distinguish symbols with the same name
Datatype *type; ///< The symbol's data-type Datatype *type; ///< The symbol's data-type
uint4 nameDedup; ///< id to distinguish symbols with the same name
uint4 flags; ///< Varnode-like properties of the symbol uint4 flags; ///< Varnode-like properties of the symbol
// only typelock,namelock,readonly,externref // only typelock,namelock,readonly,externref
// addrtied, persist inherited from scope // addrtied, persist inherited from scope
uint4 dispflags; ///< Flags affecting the display of this symbol uint4 dispflags; ///< Flags affecting the display of this symbol
int2 category; ///< Special category (-1==none 0=parameter 1=equate) int2 category; ///< Special category (-1==none 0=parameter 1=equate)
uint2 catindex; ///< Index within category uint2 catindex; ///< Index within category
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
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
void setSymbolId(uint8 val) { symbolId = val; } ///< Assign a unique id to the symbol
void checkSizeTypeLock(void); ///< Calculate if \b size_typelock property is on void checkSizeTypeLock(void); ///< Calculate if \b size_typelock property is on
public: public:
/// \brief Possible display (dispflag) properties for a Symbol /// \brief Possible display (dispflag) properties for a Symbol
@ -181,14 +183,14 @@ public:
}; };
/// \brief Construct given a name and data-type /// \brief Construct given a name and data-type
Symbol(Scope *sc,const string &nm,Datatype *ct) Symbol(Scope *sc,const string &nm,Datatype *ct)
{ scope=sc; name=nm; nameDedup=0; type=ct; flags=0; dispflags=0; category=-1; } { scope=sc; name=nm; nameDedup=0; type=ct; flags=0; dispflags=0; category=-1; symbolId = 0; }
/// \brief Construct for use with restoreXml() /// \brief Construct for use with restoreXml()
Symbol(Scope *sc) { scope=sc; nameDedup=0; flags=0; dispflags=0; category=-1; } Symbol(Scope *sc) { scope=sc; nameDedup=0; flags=0; dispflags=0; category=-1; symbolId = 0; }
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
uint4 getId(void) const { return (uint4)(uintp)this; } ///< Get a unique id for the symbol uint8 getId(void) const { return symbolId; } ///< Get a unique id for the symbol
uint4 getFlags(void) const { return flags; } ///< Get the boolean properties of the Symbol uint4 getFlags(void) const { return flags; } ///< Get the boolean properties of the Symbol
uint4 getDisplayFormat(void) const { return (dispflags & 7); } ///< Get the format to display the Symbol in uint4 getDisplayFormat(void) const { return (dispflags & 7); } ///< Get the format to display the Symbol in
int2 getCategory(void) const { return category; } ///< Get the Symbol category int2 getCategory(void) const { return category; } ///< Get the Symbol category
@ -210,6 +212,7 @@ public:
virtual void saveXml(ostream &s) const; ///< Save \b this Symbol to an XML stream virtual void saveXml(ostream &s) const; ///< Save \b this Symbol to an XML stream
virtual void restoreXml(const Element *el); ///< Restore \b this Symbol from an XML stream virtual void restoreXml(const Element *el); ///< Restore \b this Symbol from an XML stream
virtual int4 getBytesConsumed(void) const; ///< Get number of bytes consumed within the address->symbol map virtual int4 getBytesConsumed(void) const; ///< Get number of bytes consumed within the address->symbol map
static uint8 ID_BASE; ///< Base of internal ID's
}; };
/// Force a specific display format for constant symbols /// Force a specific display format for constant symbols
@ -405,12 +408,13 @@ class Scope {
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
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
Funcdata *fd; ///< (If non-null) the function which \b this is the local Scope for Funcdata *fd; ///< (If non-null) the function which \b this is the local Scope for
uint4 dedupId; ///< Id to dedup scopes with same name (when allowed) uint4 uniqueId; ///< Unique id for the scope, for deduping scope names, assigning symbol ids
static const Scope *stackAddr(const Scope *scope1, static const Scope *stackAddr(const Scope *scope1,
const Scope *scope2, const Scope *scope2,
const Address &addr, const Address &addr,
@ -488,7 +492,7 @@ public:
#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) {
name = nm; glb = g; parent = (Scope *)0; fd = (Funcdata *)0; dedupId = 0; name = nm; glb = g; parent = (Scope *)0; fd = (Funcdata *)0; uniqueId = 0;
#ifdef OPACTION_DEBUG #ifdef OPACTION_DEBUG
debugon = false; debugon = false;
#endif #endif
@ -714,6 +718,7 @@ protected:
vector<EntryMap *> maptable; ///< Rangemaps of SymbolEntry, one map for each address space vector<EntryMap *> maptable; ///< Rangemaps of SymbolEntry, one map for each address space
vector<vector<Symbol *> > category; ///< References to Symbol objects organized by category vector<vector<Symbol *> > category; ///< References to Symbol objects organized by category
list<SymbolEntry> dynamicentry; ///< Dynamic symbol entries list<SymbolEntry> dynamicentry; ///< Dynamic symbol entries
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
virtual void clear(void); virtual void clear(void);
@ -817,12 +822,13 @@ class Database {
Scope *globalscope; ///< A quick reference to the \e global Scope Scope *globalscope; ///< A quick reference to the \e global Scope
ScopeResolve resolvemap; ///< The Address to \e namespace map ScopeResolve resolvemap; ///< The Address to \e namespace map
partmap<Address,uint4> flagbase; ///< Map of global properties partmap<Address,uint4> flagbase; ///< Map of global properties
uint4 nextScopeId; ///< Id for next attached scope (0 reserved for global scope)
void clearResolve(Scope *scope); ///< Clear the \e ownership ranges associated with the given Scope void clearResolve(Scope *scope); ///< Clear the \e ownership ranges associated with the given Scope
void clearResolveRecursive(Scope *scope); ///< Clear the \e ownership ranges of a given Scope and its children void clearResolveRecursive(Scope *scope); ///< Clear the \e ownership ranges of a given Scope and its children
void fillResolve(Scope *scope); ///< Add the \e ownership ranges of the given Scope to the map void fillResolve(Scope *scope); ///< Add the \e ownership ranges of the given Scope to the map
static void parseParentTag(const Element *el,string &name,vector<string> &parnames); static void parseParentTag(const Element *el,string &name,vector<string> &parnames);
public: public:
Database(Architecture *g) { glb=g; globalscope=(Scope *)0; flagbase.defaultValue() = 0; } ///< Constructor Database(Architecture *g) { glb=g; globalscope=(Scope *)0; flagbase.defaultValue()=0; nextScopeId=1; } ///< Constructor
~Database(void); ///< Destructor ~Database(void); ///< Destructor
Architecture *getArch(void) const { return glb; } ///< Get the Architecture associate with \b this Architecture *getArch(void) const { return glb; } ///< Get the Architecture associate with \b this
void attachScope(Scope *newscope,Scope *parent); ///< Register a new Scope void attachScope(Scope *newscope,Scope *parent); ///< Register a new Scope

View file

@ -305,7 +305,6 @@ ScopeLocal::ScopeLocal(AddrSpace *spc,Funcdata *fd,Architecture *g) : ScopeInter
rangeLocked = false; rangeLocked = false;
stackGrowsNegative = true; stackGrowsNegative = true;
restrictScope(fd); restrictScope(fd);
dedupId = fd->getAddress().getOffset(); // Allow multiple scopes with same name
} }
/// Turn any symbols that are \e name \e locked but not \e type \e locked into name recommendations /// Turn any symbols that are \e name \e locked but not \e type \e locked into name recommendations

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -57,7 +56,7 @@ public class ClangVariableDecl extends ClangTokenGroup {
public void restoreFromXML(XmlPullParser parser,PcodeFactory pfactory) { public void restoreFromXML(XmlPullParser parser,PcodeFactory pfactory) {
XmlElement node = parser.peek(); XmlElement node = parser.peek();
super.restoreFromXML(parser,pfactory); super.restoreFromXML(parser,pfactory);
int symref = SpecXmlUtils.decodeInt(node.getAttribute(ClangXML.SYMREF)); long symref = SpecXmlUtils.decodeLong(node.getAttribute(ClangXML.SYMREF));
HighSymbol sym = pfactory.getSymbol(symref); HighSymbol sym = pfactory.getSymbol(symref);
if (sym == null) { if (sym == null) {
Msg.error(this, "Invalid symbol reference: " + symref); Msg.error(this, "Invalid symbol reference: " + symref);

View file

@ -831,12 +831,20 @@ public class DecompileCallback {
if ((data.getDataType() == DataType.DEFAULT) && (sym == null) && !isVolatile && !readonly) { if ((data.getDataType() == DataType.DEFAULT) && (sym == null) && !isVolatile && !readonly) {
return null; return null;
} }
long uniqueId;
String name = sym != null ? sym.getName() : SymbolUtilities.getDynamicName(program, addr); String name;
if (sym != null) {
name = sym.getName();
uniqueId = sym.getID();
}
else {
name = SymbolUtilities.getDynamicName(program, addr);
uniqueId = 0;
}
int sz = data.getLength(); int sz = data.getLength();
String symstring = MappedSymbol.buildSymbolXML(dtmanage, name, data.getDataType(), sz, true, String symstring = MappedSymbol.buildSymbolXML(dtmanage, uniqueId, name, data.getDataType(),
true, readonly, isVolatile, -1, -1); sz, true, true, readonly, isVolatile, -1, -1);
if (debug != null) { if (debug != null) {
debug.getType(data.getDataType()); debug.getType(data.getDataType());
} }

View file

@ -44,8 +44,9 @@ public class DynamicSymbol extends HighSymbol {
refs = new Entry[0]; refs = new Entry[0];
} }
public DynamicSymbol(String nm,DataType tp,int size,HighFunction func,Address addr,long hash,int format) { public DynamicSymbol(long uniqueId, String nm, DataType tp, int size, HighFunction func,
super(nm,tp,size,addr,func); Address addr, long hash, int format) {
super(uniqueId, nm, tp, size, addr, func);
refs = new Entry[1]; refs = new Entry[1];
refs[0] = new Entry(addr,hash,format); refs[0] = new Entry(addr,hash,format);
} }
@ -56,18 +57,21 @@ public class DynamicSymbol extends HighSymbol {
public void addReference(Address addr,long hash,int format) { public void addReference(Address addr,long hash,int format) {
Entry[] newrefs = new Entry[refs.length + 1]; Entry[] newrefs = new Entry[refs.length + 1];
for(int i=0;i<refs.length;++i) for(int i=0;i<refs.length;++i) {
newrefs[i] = refs[i]; newrefs[i] = refs[i];
}
newrefs[refs.length] = new Entry(addr,hash,format); newrefs[refs.length] = new Entry(addr,hash,format);
refs = newrefs; refs = newrefs;
if (refs.length == 1) if (refs.length == 1)
{
pcaddr = addr; // Store first address as official pcaddr for symbol pcaddr = addr; // Store first address as official pcaddr for symbol
} }
}
protected void buildHashXML(StringBuilder buf) { protected void buildHashXML(StringBuilder buf) {
for(int i=0;i<refs.length;++i) { for (Entry ref : refs) {
buf.append("<hash val=\"0x").append(Long.toHexString(refs[i].hash)).append("\"/>"); buf.append("<hash val=\"0x").append(Long.toHexString(ref.hash)).append("\"/>");
buildRangelistXML(buf, refs[i].pcaddr); buildRangelistXML(buf, ref.pcaddr);
} }
} }
@ -84,15 +88,16 @@ public class DynamicSymbol extends HighSymbol {
} }
@Override @Override
public int restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException { public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
XmlElement symel = parser.start("symbol"); XmlElement symel = parser.start("symbol");
int symbolId = restoreSymbolXML(symel, func); restoreSymbolXML(symel, func);
type = func.getDataTypeManager().readXMLDataType(parser); type = func.getDataTypeManager().readXMLDataType(parser);
size = type.getLength(); size = type.getLength();
parser.end(symel); parser.end(symel);
if (size == 0) if (size == 0) {
throw new PcodeXMLException("Invalid symbol 0-sized data-type: " + type.getName()); throw new PcodeXMLException("Invalid symbol 0-sized data-type: " + type.getName());
}
while(parser.peek().isStart()) { while(parser.peek().isStart()) {
long hash = 0; long hash = 0;
int format = 0; int format = 0;
@ -103,7 +108,6 @@ public class DynamicSymbol extends HighSymbol {
Address addr = parseRangeList(parser); Address addr = parseRangeList(parser);
addReference(addr,hash,format); addReference(addr,hash,format);
} }
return symbolId;
} }
public static String buildSymbolXML(PcodeDataTypeManager dtmanage, String nm, public static String buildSymbolXML(PcodeDataTypeManager dtmanage, String nm,
@ -117,8 +121,9 @@ public class DynamicSymbol extends HighSymbol {
SpecXmlUtils.encodeBooleanAttribute(res, "typelock", tl); SpecXmlUtils.encodeBooleanAttribute(res, "typelock", tl);
SpecXmlUtils.encodeBooleanAttribute(res, "namelock", nl); SpecXmlUtils.encodeBooleanAttribute(res, "namelock", nl);
SpecXmlUtils.encodeBooleanAttribute(res, "readonly", ro); SpecXmlUtils.encodeBooleanAttribute(res, "readonly", ro);
if (isVolatile) if (isVolatile) {
SpecXmlUtils.encodeBooleanAttribute(res, "volatile", true); SpecXmlUtils.encodeBooleanAttribute(res, "volatile", true);
}
res.append(">\n"); res.append(">\n");
res.append(dtmanage.buildTypeRef(dt, length)); res.append(dtmanage.buildTypeRef(dt, length));
res.append("</symbol>\n"); res.append("</symbol>\n");

View file

@ -36,14 +36,16 @@ public class EquateSymbol extends DynamicSymbol {
public EquateSymbol() { public EquateSymbol() {
} }
public EquateSymbol(String nm,long val,HighFunction func,Address addr,long hash,int format) { public EquateSymbol(long uniqueId, String nm, long val, HighFunction func, Address addr,
super(nm, DataType.DEFAULT, 1, func, addr, hash, format); long hash, int format) {
super(uniqueId, nm, DataType.DEFAULT, 1, func, addr, hash, format);
value = val; value = val;
convert = FORMAT_DEFAULT; convert = FORMAT_DEFAULT;
} }
public EquateSymbol(int conv,long val,HighFunction func,Address addr,long hash,int format) { public EquateSymbol(long uniqueId, int conv, long val, HighFunction func, Address addr,
super("", DataType.DEFAULT, 1, func, addr, hash, format); long hash, int format) {
super(uniqueId, "", DataType.DEFAULT, 1, func, addr, hash, format);
value = val; value = val;
convert = conv; convert = conv;
} }
@ -51,9 +53,9 @@ public class EquateSymbol extends DynamicSymbol {
public long getValue() { return value; } public long getValue() { return value; }
@Override @Override
public int restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException { public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
XmlElement symel = parser.start("equatesymbol"); XmlElement symel = parser.start("equatesymbol");
int symbolId = restoreSymbolXML(symel, func); restoreSymbolXML(symel, func);
type = DataType.DEFAULT; type = DataType.DEFAULT;
size = 1; size = 1;
convert = FORMAT_DEFAULT; convert = FORMAT_DEFAULT;
@ -92,7 +94,6 @@ public class EquateSymbol extends DynamicSymbol {
Address addr = parseRangeList(parser); Address addr = parseRangeList(parser);
addReference(addr,hash,format); addReference(addr,hash,format);
} }
return symbolId;
} }
@Override @Override

View file

@ -120,7 +120,7 @@ public class HighFunction extends PcodeSyntaxTree {
} }
@Override @Override
public HighSymbol getSymbol(int symbolId) { public HighSymbol getSymbol(long symbolId) {
return localSymbols.getSymbol(symbolId); return localSymbols.getSymbol(symbolId);
} }
@ -469,9 +469,8 @@ public class HighFunction extends PcodeSyntaxTree {
// Note that we don't need to distinguish between unique,register,ram etc. and don't // Note that we don't need to distinguish between unique,register,ram etc. and don't
// need to separate out first use versus mapped use. When the high local is written // need to separate out first use versus mapped use. When the high local is written
// to database, these issues will be resolved at that point. // to database, these issues will be resolved at that point.
sym = localSymbols.newMappedSymbol(highloc.getName(), highloc.getDataType(), sym = localSymbols.newMappedSymbol(0, highloc.getName(), highloc.getDataType(),
new VariableStorage(func.getProgram(), vn), vn.getPCAddress(), -1, new VariableStorage(func.getProgram(), vn), vn.getPCAddress(), -1);
vn.hashCode());
reslocal = new HighLocal(highloc.getDataType(), vn, null, vn.getPCAddress(), sym); reslocal = new HighLocal(highloc.getDataType(), vn, null, vn.getPCAddress(), sym);
resremain = highloc; // Keep remaining varnodes in old high resremain = highloc; // Keep remaining varnodes in old high

View file

@ -24,6 +24,7 @@ import ghidra.xml.XmlPullParser;
public abstract class HighSymbol { public abstract class HighSymbol {
public static final long ID_BASE = 0x4000000000000000L; // Put keys in the dynamic symbol portion of the key space
protected String name; protected String name;
protected DataType type; protected DataType type;
protected int size; // Size of this variable protected int size; // Size of this variable
@ -32,13 +33,15 @@ public abstract class HighSymbol {
private boolean namelock; // Is this variable's name locked private boolean namelock; // Is this variable's name locked
private boolean typelock; // Is this variable's datatype locked private boolean typelock; // Is this variable's datatype locked
private boolean readonly; private boolean readonly;
private long id; // Unique id of this symbol
private HighVariable highVariable; private HighVariable highVariable;
public HighSymbol() { // For use with restoreXML public HighSymbol() { // For use with restoreXML
} }
public HighSymbol(String nm,DataType tp,int sz,Address pc,HighFunction func) { public HighSymbol(long uniqueId, String nm, DataType tp, int sz, Address pc,
HighFunction func) {
name = nm; name = nm;
type = tp; type = tp;
size = sz; size = sz;
@ -46,6 +49,11 @@ public abstract class HighSymbol {
namelock = false; namelock = false;
typelock = false; typelock = false;
function = func; function = func;
id = uniqueId;
}
public long getId() {
return id;
} }
public void setHighVariable(HighVariable high) { public void setHighVariable(HighVariable high) {
@ -102,25 +110,26 @@ public abstract class HighSymbol {
public abstract String buildXML(); public abstract String buildXML();
public abstract int restoreXML(XmlPullParser parser,HighFunction func) throws PcodeXMLException; public abstract void restoreXML(XmlPullParser parser, HighFunction func)
throws PcodeXMLException;
protected int restoreSymbolXML(XmlElement symel,HighFunction func) throws PcodeXMLException { protected void restoreSymbolXML(XmlElement symel, HighFunction func) throws PcodeXMLException {
function = func; function = func;
int symbolId = SpecXmlUtils.decodeInt(symel.getAttribute("id")); id = SpecXmlUtils.decodeLong(symel.getAttribute("id"));
if (symbolId == 0) { if (id == 0) {
throw new PcodeXMLException("missing unique symbol id"); throw new PcodeXMLException("missing unique symbol id");
} }
typelock = false; typelock = false;
String typelockstr = symel.getAttribute("typelock"); String typelockstr = symel.getAttribute("typelock");
if ((typelockstr != null) && (SpecXmlUtils.decodeBoolean(typelockstr))) if ((typelockstr != null) && (SpecXmlUtils.decodeBoolean(typelockstr))) {
typelock = true; typelock = true;
}
namelock = false; namelock = false;
String namelockstr = symel.getAttribute("namelock"); String namelockstr = symel.getAttribute("namelock");
if ((namelockstr != null) && (SpecXmlUtils.decodeBoolean(namelockstr))) if ((namelockstr != null) && (SpecXmlUtils.decodeBoolean(namelockstr))) {
namelock = true; namelock = true;
}
name = symel.getAttribute("name"); name = symel.getAttribute("name");
return symbolId;
} }
protected Address parseRangeList(XmlPullParser parser) { protected Address parseRangeList(XmlPullParser parser) {

View file

@ -39,8 +39,9 @@ public class LocalSymbolMap {
private HighFunction func; // Function to which these variables are local private HighFunction func; // Function to which these variables are local
private String spacename; private String spacename;
private HashMap<MappedVarKey, HighSymbol> addrMappedSymbols; // Hashed by addr and pcaddr private HashMap<MappedVarKey, HighSymbol> addrMappedSymbols; // Hashed by addr and pcaddr
private HashMap<Integer, HighSymbol> symbolMap; // Hashed by unique key private HashMap<Long, HighSymbol> symbolMap; // Hashed by unique key
private MappedSymbol[] paramSymbols; private MappedSymbol[] paramSymbols;
private long uniqueSymbolId; // Next available symbol id
/** /**
* @param highFunc HighFunction the local variables are defined within. * @param highFunc HighFunction the local variables are defined within.
@ -50,21 +51,31 @@ public class LocalSymbolMap {
func = highFunc; func = highFunc;
spacename = spcname; spacename = spcname;
addrMappedSymbols = new HashMap<MappedVarKey, HighSymbol>(); addrMappedSymbols = new HashMap<MappedVarKey, HighSymbol>();
symbolMap = new HashMap<Integer, HighSymbol>(); symbolMap = new HashMap<Long, HighSymbol>();
paramSymbols = new MappedSymbol[0]; paramSymbols = new MappedSymbol[0];
uniqueSymbolId = 0;
} }
public HighFunction getHighFunction() { public HighFunction getHighFunction() {
return func; return func;
} }
/**
* Assign a unique id to a new symbol being put in this container.
* @return the unique id
*/
private long getNextId() {
long key = HighSymbol.ID_BASE + uniqueSymbolId;
uniqueSymbolId += 1;
return key;
}
/** /**
* Populate the local variable map from information attached to the Program DB's function. * Populate the local variable map from information attached to the Program DB's function.
* @param includeDefaultNames is true if default symbol names should be considered locked * @param includeDefaultNames is true if default symbol names should be considered locked
*/ */
public void grabFromFunction(boolean includeDefaultNames) { public void grabFromFunction(boolean includeDefaultNames) {
Function dbFunction = func.getFunction(); Function dbFunction = func.getFunction();
int uniqueSymbolId = 0;
Variable locals[] = dbFunction.getLocalVariables(); Variable locals[] = dbFunction.getLocalVariables();
for (Variable local : locals) { for (Variable local : locals) {
Variable var = local; Variable var = local;
@ -82,18 +93,18 @@ public class LocalSymbolMap {
String name = var.getName(); String name = var.getName();
VariableStorage storage = var.getVariableStorage(); VariableStorage storage = var.getVariableStorage();
long id = getNextId();
Address defAddr = null; Address defAddr = null;
if (!storage.isStackStorage()) { if (!storage.isStackStorage()) {
defAddr = dbFunction.getEntryPoint().addWrap(var.getFirstUseOffset()); defAddr = dbFunction.getEntryPoint().addWrap(var.getFirstUseOffset());
} }
HighSymbol sym; HighSymbol sym;
if (storage.isHashStorage()) { if (storage.isHashStorage()) {
sym = sym = newDynamicSymbol(id, name, dt, sz, storage.getFirstVarnode().getOffset(),
newDynamicSymbol(name, dt, sz, storage.getFirstVarnode().getOffset(), defAddr, defAddr, 0);
0, ++uniqueSymbolId);
} }
else { else {
sym = newMappedSymbol(name, dt, storage, defAddr, -1, ++uniqueSymbolId); sym = newMappedSymbol(id, name, dt, storage, defAddr, -1);
} }
sym.setTypeLock(istypelock); sym.setTypeLock(istypelock);
sym.setNameLock(isnamelock); sym.setNameLock(isnamelock);
@ -116,8 +127,9 @@ public class LocalSymbolMap {
String name = var.getName(); String name = var.getName();
VariableStorage storage = var.getVariableStorage(); VariableStorage storage = var.getVariableStorage();
Address resAddr = storage.isStackStorage() ? null : pcaddr; Address resAddr = storage.isStackStorage() ? null : pcaddr;
long id = getNextId();
MappedSymbol paramSymbol = MappedSymbol paramSymbol =
newMappedSymbol(name, dt, storage, resAddr, i, ++uniqueSymbolId); newMappedSymbol(id, name, dt, storage, resAddr, i);
paramList.add(paramSymbol); paramList.add(paramSymbol);
boolean namelock = true; boolean namelock = true;
if (!includeDefaultNames) { if (!includeDefaultNames) {
@ -131,7 +143,7 @@ public class LocalSymbolMap {
paramList.toArray(paramSymbols); paramList.toArray(paramSymbols);
Arrays.sort(paramSymbols, PARAM_SYMBOL_SLOT_COMPARATOR); Arrays.sort(paramSymbols, PARAM_SYMBOL_SLOT_COMPARATOR);
uniqueSymbolId = grabEquates(dbFunction, uniqueSymbolId); grabEquates(dbFunction);
} }
private boolean isUserDefinedName(String name) { private boolean isUserDefinedName(String name) {
@ -164,9 +176,9 @@ public class LocalSymbolMap {
res = new EquateSymbol(); res = new EquateSymbol();
} }
int symbolId = res.restoreXML(parser, func); res.restoreXML(parser, func);
parser.end(node); parser.end(node);
insertSymbol(res,symbolId); insertSymbol(res);
return res; return res;
} }
@ -290,7 +302,7 @@ public class LocalSymbolMap {
* @param id symbol-id * @param id symbol-id
* @return variable or null if not found * @return variable or null if not found
*/ */
public HighSymbol getSymbol(int id) { public HighSymbol getSymbol(long id) {
return symbolMap.get(id); return symbolMap.get(id);
} }
@ -316,43 +328,60 @@ public class LocalSymbolMap {
return false; return false;
} }
public MappedSymbol newMappedSymbol(String nm, DataType dt, VariableStorage store, public MappedSymbol newMappedSymbol(long id, String nm, DataType dt, VariableStorage store,
Address pcaddr, int slot, int id) { Address pcaddr, int slot) {
MappedSymbol sym = new MappedSymbol(nm, dt, store, pcaddr, func, slot); if (id == 0) {
insertSymbol(sym,id); id = getNextId();
}
MappedSymbol sym = new MappedSymbol(id, nm, dt, store, pcaddr, func, slot);
insertSymbol(sym);
return sym; return sym;
} }
public DynamicSymbol newDynamicSymbol(String nm, DataType dt, int sz, long hash, public DynamicSymbol newDynamicSymbol(long id, String nm, DataType dt, int sz, long hash,
Address pcaddr, int format, int id) { Address pcaddr, int format) {
DynamicSymbol sym = new DynamicSymbol(nm, dt, sz, func, pcaddr, hash, format); if (id == 0) {
insertSymbol(sym,id); id = getNextId();
}
DynamicSymbol sym = new DynamicSymbol(id, nm, dt, sz, func, pcaddr, hash, format);
insertSymbol(sym);
return sym; return sym;
} }
private void insertSymbol(HighSymbol sym,int id) { private void insertSymbol(HighSymbol sym) {
long uniqueId = sym.getId();
if ((uniqueId >> 56) == (HighSymbol.ID_BASE >> 56)) {
long val = uniqueId & 0x7fffffff;
if (val > uniqueSymbolId) {
uniqueSymbolId = val;
}
}
if (sym instanceof MappedSymbol) { if (sym instanceof MappedSymbol) {
MappedSymbol mapSym = (MappedSymbol)sym; MappedSymbol mapSym = (MappedSymbol)sym;
MappedVarKey key = new MappedVarKey(mapSym.getStorage(),mapSym.getPCAddress()); MappedVarKey key = new MappedVarKey(mapSym.getStorage(),mapSym.getPCAddress());
addrMappedSymbols.put(key, sym); addrMappedSymbols.put(key, sym);
} }
symbolMap.put(id, sym); symbolMap.put(uniqueId, sym);
} }
private void newEquateSymbol(String nm, long val, long hash, Address addr, int format, private void newEquateSymbol(long uniqueId, String nm, long val, long hash, Address addr,
int format,
TreeMap<String, DynamicSymbol> constantSymbolMap) { TreeMap<String, DynamicSymbol> constantSymbolMap) {
DynamicSymbol eqSymbol = constantSymbolMap.get(nm); DynamicSymbol eqSymbol = constantSymbolMap.get(nm);
if (eqSymbol != null) { if (eqSymbol != null) {
eqSymbol.addReference(addr, hash, format); // New reference to same symbol eqSymbol.addReference(addr, hash, format); // New reference to same symbol
return; return;
} }
if (uniqueId == 0) {
uniqueId = getNextId();
}
int conv = EquateSymbol.convertName(nm, val); int conv = EquateSymbol.convertName(nm, val);
if (conv < 0) { if (conv < 0) {
eqSymbol = new EquateSymbol(nm, val, func, addr, hash, format); eqSymbol = new EquateSymbol(uniqueId, nm, val, func, addr, hash, format);
eqSymbol.setNameLock(true); eqSymbol.setNameLock(true);
} }
else { else {
eqSymbol = new EquateSymbol(conv, val, func, addr, hash, format); eqSymbol = new EquateSymbol(uniqueId, conv, val, func, addr, hash, format);
} }
//Do NOT setTypeLock //Do NOT setTypeLock
constantSymbolMap.put(nm, eqSymbol); constantSymbolMap.put(nm, eqSymbol);
@ -361,10 +390,8 @@ public class LocalSymbolMap {
/** /**
* Build dynamic symbols based on equates * Build dynamic symbols based on equates
* @param dbFunction is the function to pull equates for * @param dbFunction is the function to pull equates for
* @param uniqueSymbolId is the next available symbol id
* @return the next available symbol id
*/ */
private int grabEquates(Function dbFunction, int uniqueSymbolId) { private void grabEquates(Function dbFunction) {
TreeMap<String, DynamicSymbol> constantSymbolMap = null; TreeMap<String, DynamicSymbol> constantSymbolMap = null;
// Find named constants via Equates // Find named constants via Equates
Program program = dbFunction.getProgram(); Program program = dbFunction.getProgram();
@ -383,7 +410,7 @@ public class LocalSymbolMap {
if (constantSymbolMap == null) { if (constantSymbolMap == null) {
constantSymbolMap = new TreeMap<String, DynamicSymbol>(); constantSymbolMap = new TreeMap<String, DynamicSymbol>();
} }
newEquateSymbol(eq.getDisplayName(), eq.getValue(), element, defAddr, 0, newEquateSymbol(0, eq.getDisplayName(), eq.getValue(), element, defAddr, 0,
constantSymbolMap); constantSymbolMap);
} }
} }
@ -405,10 +432,10 @@ public class LocalSymbolMap {
// Add constant dynamic symbols to map // Add constant dynamic symbols to map
if (constantSymbolMap != null) { if (constantSymbolMap != null) {
for (DynamicSymbol sym : constantSymbolMap.values()) { for (DynamicSymbol sym : constantSymbolMap.values()) {
symbolMap.put(++uniqueSymbolId, sym); long id = getNextId();
symbolMap.put(id, sym);
} }
} }
return uniqueSymbolId;
} }
/** /**

View file

@ -33,21 +33,25 @@ public class MappedSymbol extends HighSymbol {
public MappedSymbol() { // For use with restoreXML public MappedSymbol() { // For use with restoreXML
} }
public MappedSymbol(String name, DataType dt, VariableStorage store, Address pcaddr, public MappedSymbol(long uniqueId, String name, DataType dt, VariableStorage store,
Address pcaddr,
HighFunction func, int slot) { HighFunction func, int slot) {
super(name, dt, store.size(), pcaddr, func); super(uniqueId, name, dt, store.size(), pcaddr, func);
if (store.size() != dt.getLength()) { if (store.size() != dt.getLength()) {
if (ParamEntry.getMetatype(dt) != ParamEntry.TYPE_FLOAT) if (ParamEntry.getMetatype(dt) != ParamEntry.TYPE_FLOAT) {
throw new IllegalArgumentException("Specified size does not match storage size"); throw new IllegalArgumentException("Specified size does not match storage size");
} }
}
this.storage = store; this.storage = store;
this.slot = slot; this.slot = slot;
Varnode rep = function.createFromStorage(null, storage, dt.getLength()); Varnode rep = function.createFromStorage(null, storage, dt.getLength());
HighVariable var; HighVariable var;
if (slot < 0) if (slot < 0) {
var = new HighLocal(type, rep, null, pcaddr, this); var = new HighLocal(type, rep, null, pcaddr, this);
else }
else {
var = new HighParam(type, rep, pcaddr, slot, this); var = new HighParam(type, rep, pcaddr, slot, this);
}
setHighVariable(var); setHighVariable(var);
var.setHighOnInstances(); var.setHighOnInstances();
} }
@ -71,27 +75,30 @@ public class MappedSymbol extends HighSymbol {
} }
StringBuilder res = new StringBuilder(); StringBuilder res = new StringBuilder();
int cat = isParameter() ? 0 : -1; int cat = isParameter() ? 0 : -1;
String sym = buildSymbolXML(function.getDataTypeManager(),name, type, size, String sym = buildSymbolXML(function.getDataTypeManager(), getId(), name, type, size,
isTypeLocked(), isNameLocked(), false, false, cat, slot); isTypeLocked(), isNameLocked(), false, false, cat, slot);
int logicalsize = 0; // Assume datatype size and storage size are the same int logicalsize = 0; // Assume datatype size and storage size are the same
if ((type != null) && (type.getLength() != storage.size())) // If sizesdiffer if ((type != null) && (type.getLength() != storage.size()))
{
logicalsize = type.getLength(); // Force a logicalsize logicalsize = type.getLength(); // Force a logicalsize
}
String addrRes = Varnode.buildXMLAddress(storage.getVarnodes(), logicalsize); String addrRes = Varnode.buildXMLAddress(storage.getVarnodes(), logicalsize);
buildMapSymXML(res, addrRes, getPCAddress(), sym); buildMapSymXML(res, addrRes, getPCAddress(), sym);
return res.toString(); return res.toString();
} }
@Override @Override
public int restoreXML(XmlPullParser parser,HighFunction func) throws PcodeXMLException { public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
XmlElement symel = parser.start("symbol"); XmlElement symel = parser.start("symbol");
int symbolId = restoreSymbolXML(symel, func); restoreSymbolXML(symel, func);
slot = -1; slot = -1;
int cat = -1; int cat = -1;
if (symel.hasAttribute("cat")) { if (symel.hasAttribute("cat")) {
cat = SpecXmlUtils.decodeInt(symel.getAttribute("cat")); cat = SpecXmlUtils.decodeInt(symel.getAttribute("cat"));
if (cat == 0) if (cat == 0) {
slot = SpecXmlUtils.decodeInt(symel.getAttribute("index")); slot = SpecXmlUtils.decodeInt(symel.getAttribute("index"));
} }
}
type = func.getDataTypeManager().readXMLDataType(parser); type = func.getDataTypeManager().readXMLDataType(parser);
parser.end(symel); parser.end(symel);
@ -129,26 +136,34 @@ public class MappedSymbol extends HighSymbol {
pcaddr = parseRangeList(parser); pcaddr = parseRangeList(parser);
Varnode rep = function.createFromStorage(addr, storage, sz); Varnode rep = function.createFromStorage(addr, storage, sz);
HighVariable var; HighVariable var;
if (slot < 0) if (slot < 0) {
var = new HighLocal(type, rep, null, pcaddr, this); var = new HighLocal(type, rep, null, pcaddr, this);
else }
else {
var = new HighParam(type, rep, pcaddr, slot, this); var = new HighParam(type, rep, pcaddr, slot, this);
}
setHighVariable(var); setHighVariable(var);
var.setHighOnInstances(); var.setHighOnInstances();
return symbolId;
} }
public static String buildSymbolXML(PcodeDataTypeManager dtmanage, String nm, public static String buildSymbolXML(PcodeDataTypeManager dtmanage, long uniqueId, String nm,
DataType dt, int length, boolean tl, boolean nl, boolean ro, DataType dt, int length, boolean tl, boolean nl, boolean ro,
boolean isVolatile, int cat, int slot) { boolean isVolatile, int cat, int slot) {
StringBuilder res = new StringBuilder(); StringBuilder res = new StringBuilder();
res.append("<symbol"); res.append("<symbol");
if ((uniqueId >> 56) == (ID_BASE >> 56)) {
uniqueId = 0; // Don't send down internal ids
}
if (uniqueId != 0) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(res, "id", uniqueId);
}
SpecXmlUtils.xmlEscapeAttribute(res, "name", nm); SpecXmlUtils.xmlEscapeAttribute(res, "name", nm);
SpecXmlUtils.encodeBooleanAttribute(res, "typelock", tl); SpecXmlUtils.encodeBooleanAttribute(res, "typelock", tl);
SpecXmlUtils.encodeBooleanAttribute(res, "namelock", nl); SpecXmlUtils.encodeBooleanAttribute(res, "namelock", nl);
SpecXmlUtils.encodeBooleanAttribute(res, "readonly", ro); SpecXmlUtils.encodeBooleanAttribute(res, "readonly", ro);
if (isVolatile) if (isVolatile) {
SpecXmlUtils.encodeBooleanAttribute(res, "volatile", true); SpecXmlUtils.encodeBooleanAttribute(res, "volatile", true);
}
SpecXmlUtils.encodeSignedIntegerAttribute(res, "cat", cat); SpecXmlUtils.encodeSignedIntegerAttribute(res, "cat", cat);
if (slot >= 0) { if (slot >= 0) {
SpecXmlUtils.encodeSignedIntegerAttribute(res, "index", slot); SpecXmlUtils.encodeSignedIntegerAttribute(res, "index", slot);

View file

@ -57,7 +57,8 @@ public interface PcodeFactory {
public VariableStorage buildStorage(Varnode vn) throws InvalidInputException; public VariableStorage buildStorage(Varnode vn) throws InvalidInputException;
public Varnode getRef(int refid); public Varnode getRef(int refid);
public PcodeOp getOpRef(int refid); public PcodeOp getOpRef(int refid);
public HighSymbol getSymbol(int symbolId);
public HighSymbol getSymbol(long symbolId);
public Varnode setInput(Varnode vn,boolean val); public Varnode setInput(Varnode vn,boolean val);
public void setAddrTied(Varnode vn,boolean val); public void setAddrTied(Varnode vn,boolean val);
public void setPersistant(Varnode vn,boolean val); public void setPersistant(Varnode vn,boolean val);

View file

@ -142,8 +142,9 @@ public class PcodeSyntaxTree implements PcodeFactory {
// bad prototypes causing the decompiler to produce weird stuff // bad prototypes causing the decompiler to produce weird stuff
// TODO: We should emit some kind of warning // TODO: We should emit some kind of warning
int sz = 0; int sz = 0;
for (Varnode piece : pieces) for (Varnode piece : pieces) {
sz += piece.getSize(); sz += piece.getSize();
}
Address uniqaddr = addrFactory.getUniqueSpace().getAddress(0x20000000); Address uniqaddr = addrFactory.getUniqueSpace().getAddress(0x20000000);
storage = new VariableStorage(datatypeManager.getProgram(),uniqaddr,sz); storage = new VariableStorage(datatypeManager.getProgram(),uniqaddr,sz);
} }
@ -156,26 +157,30 @@ public class PcodeSyntaxTree implements PcodeFactory {
else { else {
offObject = new Integer((int)offset); offObject = new Integer((int)offset);
offset += roundsize; offset += roundsize;
if (offset > joinAllocate) if (offset > joinAllocate) {
joinAllocate = (int)offset; joinAllocate = (int)offset;
} }
if (joinmap == null) }
if (joinmap == null) {
joinmap = new HashMap<Integer,VariableStorage>(); joinmap = new HashMap<Integer,VariableStorage>();
}
joinmap.put(offObject, storage); joinmap.put(offObject, storage);
return storage; return storage;
} }
private VariableStorage findJoinStorage(long offset) { private VariableStorage findJoinStorage(long offset) {
if (joinmap == null) if (joinmap == null) {
return null; return null;
}
return joinmap.get(new Integer((int)offset)); return joinmap.get(new Integer((int)offset));
} }
@Override @Override
public VariableStorage buildStorage(Varnode vn) throws InvalidInputException { public VariableStorage buildStorage(Varnode vn) throws InvalidInputException {
Address addr = vn.getAddress(); Address addr = vn.getAddress();
if (addr.getAddressSpace().getType() == AddressSpace.TYPE_VARIABLE) if (addr.getAddressSpace().getType() == AddressSpace.TYPE_VARIABLE) {
return findJoinStorage(addr.getOffset()); return findJoinStorage(addr.getOffset());
}
return new VariableStorage(datatypeManager.getProgram(),vn); return new VariableStorage(datatypeManager.getProgram(),vn);
} }
@ -306,10 +311,12 @@ public class PcodeSyntaxTree implements PcodeFactory {
@Override @Override
public Varnode newVarnode(int sz, Address addr, int id) { public Varnode newVarnode(int sz, Address addr, int id) {
Varnode vn = vbank.create(sz, addr, id); Varnode vn = vbank.create(sz, addr, id);
if (uniqId <= id) if (uniqId <= id) {
uniqId = id + 1; uniqId = id + 1;
if (refmap != null) }
if (refmap != null) {
refmap.put(id, vn); refmap.put(id, vn);
}
return vn; return vn;
} }
@ -342,10 +349,12 @@ public class PcodeSyntaxTree implements PcodeFactory {
@Override @Override
public Varnode setInput(Varnode vn, boolean val) { public Varnode setInput(Varnode vn, boolean val) {
if ((!vn.isInput()) && val) if ((!vn.isInput()) && val) {
return vbank.setInput(vn); return vbank.setInput(vn);
if (vn.isInput() && (!val)) }
if (vn.isInput() && (!val)) {
vbank.makeFree(vn); vbank.makeFree(vn);
}
return vn; return vn;
} }
@ -360,13 +369,14 @@ public class PcodeSyntaxTree implements PcodeFactory {
@Override @Override
public Varnode getRef(int id) { public Varnode getRef(int id) {
if (refmap == null) if (refmap == null) {
return null; return null;
}
return refmap.get(id); return refmap.get(id);
} }
@Override @Override
public HighSymbol getSymbol(int symbolId) { public HighSymbol getSymbol(long symbolId) {
return null; return null;
} }
@ -410,8 +420,9 @@ public class PcodeSyntaxTree implements PcodeFactory {
@Override @Override
public PcodeOp getOpRef(int id) { public PcodeOp getOpRef(int id) {
if (oprefmap == null) if (oprefmap == null) {
buildOpRefs(); buildOpRefs();
}
return oprefmap.get(id); return oprefmap.get(id);
} }
@ -437,12 +448,16 @@ public class PcodeSyntaxTree implements PcodeFactory {
public void setOutput(PcodeOp op, Varnode vn) { public void setOutput(PcodeOp op, Varnode vn) {
if (vn == op.getOutput()) if (vn == op.getOutput())
{
return; // Output already set to this return; // Output already set to this
if (op.getOutput() != null) }
if (op.getOutput() != null) {
unSetOutput(op); unSetOutput(op);
}
if (vn.getDef() != null) // Varnode is already an output if (vn.getDef() != null) {
unSetOutput(vn.getDef()); unSetOutput(vn.getDef());
}
vn = vbank.setDef(vn, op); vn = vbank.setDef(vn, op);
op.setOutput(vn); op.setOutput(vn);
} }
@ -450,16 +465,21 @@ public class PcodeSyntaxTree implements PcodeFactory {
public void unSetOutput(PcodeOp op) { public void unSetOutput(PcodeOp op) {
Varnode vn = op.getOutput(); Varnode vn = op.getOutput();
if (vn == null) if (vn == null)
{
return; // Nothing to do return; // Nothing to do
}
op.setOutput(null); op.setOutput(null);
vbank.makeFree(vn); vbank.makeFree(vn);
} }
public void setInput(PcodeOp op, Varnode vn, int slot) { public void setInput(PcodeOp op, Varnode vn, int slot) {
if (slot >= op.getNumInputs()) if (slot >= op.getNumInputs())
{
op.setInput(null, slot); // Expand number of inputs as necessary op.setInput(null, slot); // Expand number of inputs as necessary
if (op.getInput(slot) != null) }
if (op.getInput(slot) != null) {
unSetInput(op, slot); unSetInput(op, slot);
}
if (vn != null) { if (vn != null) {
VarnodeAST vnast = (VarnodeAST) vn; VarnodeAST vnast = (VarnodeAST) vn;
vnast.addDescendant(op); vnast.addDescendant(op);
@ -484,29 +504,35 @@ public class PcodeSyntaxTree implements PcodeFactory {
public void unlink(PcodeOpAST op) { public void unlink(PcodeOpAST op) {
unSetOutput(op); unSetOutput(op);
for (int i = 0; i < op.getNumInputs(); ++i) for (int i = 0; i < op.getNumInputs(); ++i) {
unSetInput(op, i); unSetInput(op, i);
if (op.getParent() != null) }
if (op.getParent() != null) {
unInsert(op); unInsert(op);
} }
}
@Override @Override
public PcodeOp newOp(SequenceNumber sq, int opc, ArrayList<Varnode> inputs, Varnode output) public PcodeOp newOp(SequenceNumber sq, int opc, ArrayList<Varnode> inputs, Varnode output)
throws UnknownInstructionException { throws UnknownInstructionException {
PcodeOp op = opbank.create(opc, inputs.size(), sq); PcodeOp op = opbank.create(opc, inputs.size(), sq);
if (output != null) if (output != null) {
setOutput(op, output); setOutput(op, output);
for (int i = 0; i < inputs.size(); ++i) }
for (int i = 0; i < inputs.size(); ++i) {
setInput(op, inputs.get(i), i); setInput(op, inputs.get(i), i);
if (oprefmap != null) }
if (oprefmap != null) {
oprefmap.put(sq.getTime(), op); oprefmap.put(sq.getTime(), op);
}
return op; return op;
} }
private void readVarnodeXML(XmlPullParser parser) throws PcodeXMLException { private void readVarnodeXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("varnodes"); XmlElement el = parser.start("varnodes");
while (parser.peek().isStart()) while (parser.peek().isStart()) {
Varnode.readXML(parser, this); Varnode.readXML(parser, this);
}
parser.end(el); parser.end(el);
} }
@ -524,8 +550,9 @@ public class PcodeSyntaxTree implements PcodeFactory {
bl.insertEnd(op); bl.insertEnd(op);
} }
int index = bl.getIndex(); int index = bl.getIndex();
while (bblocks.size() <= index) while (bblocks.size() <= index) {
bblocks.add(null); bblocks.add(null);
}
bblocks.set(index, bl); bblocks.set(index, bl);
parser.end(el); parser.end(el);
} }
@ -542,18 +569,21 @@ public class PcodeSyntaxTree implements PcodeFactory {
public void readXML(XmlPullParser parser) throws PcodeXMLException { public void readXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("ast"); XmlElement el = parser.start("ast");
if (!vbank.isEmpty()) if (!vbank.isEmpty()) {
clear(); clear();
}
readVarnodeXML(parser); readVarnodeXML(parser);
buildVarnodeRefs(); // Build the HashMap buildVarnodeRefs(); // Build the HashMap
BlockMap blockMap = new BlockMap(addrFactory); BlockMap blockMap = new BlockMap(addrFactory);
while (parser.peek().isStart()) { while (parser.peek().isStart()) {
XmlElement subel = parser.peek(); XmlElement subel = parser.peek();
if (subel.getName().equals("block")) if (subel.getName().equals("block")) {
readBasicBlockXML(parser, blockMap); // Read a basic block and all its PcodeOps readBasicBlockXML(parser, blockMap); // Read a basic block and all its PcodeOps
else // Read block edges }
else {
readBlockEdgeXML(parser); readBlockEdgeXML(parser);
} }
}
parser.end(el); parser.end(el);
} }