mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
New Symbol id strategy
This commit is contained in:
parent
4560f78833
commit
a5ae6e21b0
13 changed files with 302 additions and 163 deletions
|
@ -17,6 +17,8 @@
|
|||
#include "funcdata.hh"
|
||||
#include <ctype.h>
|
||||
|
||||
uint8 Symbol::ID_BASE = 0x4000000000000000L;
|
||||
|
||||
/// This SymbolEntry is unintegrated. An address or hash must be provided
|
||||
/// either directly or via restoreXml().
|
||||
/// \param sym is the Symbol \b this will be a map for
|
||||
|
@ -338,50 +340,79 @@ void Symbol::restoreXmlHeader(const Element *el)
|
|||
{
|
||||
name.clear();
|
||||
category = -1;
|
||||
symbolId = 0;
|
||||
for(int4 i=0;i<el->getNumAttributes();++i) {
|
||||
if (el->getAttributeName(i)=="name")
|
||||
name = el->getAttributeValue(i);
|
||||
else if (el->getAttributeName(i)=="cat") {
|
||||
istringstream s(el->getAttributeValue("cat"));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> category;
|
||||
}
|
||||
else if (el->getAttributeName(i)=="namelock") {
|
||||
if (xml_readbool(el->getAttributeValue(i)))
|
||||
flags |= Varnode::namelock;
|
||||
}
|
||||
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));
|
||||
if (formString == "hex")
|
||||
dispflags |= Symbol::force_hex;
|
||||
else if (formString == "dec")
|
||||
dispflags |= Symbol::force_dec;
|
||||
else if (formString == "char")
|
||||
dispflags |= Symbol::force_char;
|
||||
else if (formString == "oct")
|
||||
dispflags |= Symbol::force_oct;
|
||||
else if (formString == "bin")
|
||||
dispflags |= Symbol::force_bin;
|
||||
const string &attName(el->getAttributeName(i));
|
||||
switch (attName[0]) {
|
||||
case 'c':
|
||||
if (attName == "cat") {
|
||||
istringstream s(el->getAttributeValue(i));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> category;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
if (attName == "format") {
|
||||
const string &formString(el->getAttributeValue(i));
|
||||
if (formString == "hex")
|
||||
dispflags |= Symbol::force_hex;
|
||||
else if (formString == "dec")
|
||||
dispflags |= Symbol::force_dec;
|
||||
else if (formString == "char")
|
||||
dispflags |= Symbol::force_char;
|
||||
else if (formString == "oct")
|
||||
dispflags |= Symbol::force_oct;
|
||||
else if (formString == "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) {
|
||||
|
@ -716,7 +747,7 @@ void Scope::attachScope(Scope *child)
|
|||
|
||||
{
|
||||
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;
|
||||
if (child->name.size()==0)
|
||||
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)
|
||||
|
||||
{
|
||||
if (sym->symbolId == 0) {
|
||||
sym->symbolId = Symbol::ID_BASE + (((uint8)uniqueId & 0xffff) << 40) + nextUniqueId;
|
||||
nextUniqueId += 1;
|
||||
}
|
||||
try {
|
||||
if (sym->name.size() == 0)
|
||||
sym->name = buildUndefinedName();
|
||||
|
@ -1695,6 +1730,7 @@ list<SymbolEntry>::iterator ScopeInternal::endDynamic(void)
|
|||
ScopeInternal::ScopeInternal(const string &nm,Architecture *g)
|
||||
: Scope(nm,g)
|
||||
{
|
||||
nextUniqueId = 0;
|
||||
int4 numspaces = g->numSpaces();
|
||||
for(int4 i=0;i<numspaces;++i)
|
||||
maptable.push_back((EntryMap *)0);
|
||||
|
@ -1725,6 +1761,7 @@ void ScopeInternal::clear(void)
|
|||
Symbol *sym = *iter++;
|
||||
removeSymbol(sym);
|
||||
}
|
||||
nextUniqueId = 0;
|
||||
}
|
||||
|
||||
/// 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");
|
||||
if (newscope->name.size() != 0)
|
||||
throw LowlevelError("Global scope does not have empty name");
|
||||
newscope->assignId(0);
|
||||
globalscope = newscope;
|
||||
return;
|
||||
}
|
||||
newscope->assignId(nextScopeId);
|
||||
nextScopeId += 1;
|
||||
parent->attachScope(newscope);
|
||||
}
|
||||
|
||||
|
@ -2635,7 +2675,7 @@ void Database::deleteScope(Scope *scope)
|
|||
delete scope;
|
||||
}
|
||||
else {
|
||||
ScopeKey key(scope->name,scope->dedupId);
|
||||
ScopeKey key(scope->name,scope->uniqueId);
|
||||
ScopeMap::iterator iter = scope->parent->children.find(key);
|
||||
if (iter == scope->parent->children.end())
|
||||
throw LowlevelError("Could not remove parent reference to: "+scope->name);
|
||||
|
|
|
@ -157,17 +157,19 @@ class Symbol {
|
|||
protected:
|
||||
Scope *scope; ///< The scope that owns this 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
|
||||
uint4 nameDedup; ///< id to distinguish symbols with the same name
|
||||
uint4 flags; ///< Varnode-like properties of the symbol
|
||||
// only typelock,namelock,readonly,externref
|
||||
// addrtied, persist inherited from scope
|
||||
uint4 dispflags; ///< Flags affecting the display of this symbol
|
||||
int2 category; ///< Special category (-1==none 0=parameter 1=equate)
|
||||
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
|
||||
virtual ~Symbol(void) {} ///< Destructor
|
||||
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
|
||||
public:
|
||||
/// \brief Possible display (dispflag) properties for a Symbol
|
||||
|
@ -181,14 +183,14 @@ public:
|
|||
};
|
||||
/// \brief Construct given a name and data-type
|
||||
Symbol(Scope *sc,const string &nm,Datatype *ct)
|
||||
{ scope=sc; name=nm; nameDedup=0; type=ct; flags=0; dispflags=0; category=-1; }
|
||||
{ scope=sc; name=nm; nameDedup=0; type=ct; flags=0; dispflags=0; category=-1; symbolId = 0; }
|
||||
|
||||
/// \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
|
||||
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 getDisplayFormat(void) const { return (dispflags & 7); } ///< Get the format to display the Symbol in
|
||||
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 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
|
||||
static uint8 ID_BASE; ///< Base of internal ID's
|
||||
};
|
||||
|
||||
/// Force a specific display format for constant symbols
|
||||
|
@ -405,12 +408,13 @@ class Scope {
|
|||
ScopeMap children; ///< Sorted list of child scopes
|
||||
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
|
||||
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,
|
||||
const Scope *scope2,
|
||||
const Address &addr,
|
||||
|
@ -488,7 +492,7 @@ public:
|
|||
#endif
|
||||
/// \brief Construct an empty scope, given a name and Architecture
|
||||
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
|
||||
debugon = false;
|
||||
#endif
|
||||
|
@ -714,6 +718,7 @@ protected:
|
|||
vector<EntryMap *> maptable; ///< Rangemaps of SymbolEntry, one map for each address space
|
||||
vector<vector<Symbol *> > category; ///< References to Symbol objects organized by category
|
||||
list<SymbolEntry> dynamicentry; ///< Dynamic symbol entries
|
||||
uint8 nextUniqueId; ///< Next available symbol id
|
||||
public:
|
||||
ScopeInternal(const string &nm,Architecture *g); ///< Construct the Scope
|
||||
virtual void clear(void);
|
||||
|
@ -817,12 +822,13 @@ class Database {
|
|||
Scope *globalscope; ///< A quick reference to the \e global Scope
|
||||
ScopeResolve resolvemap; ///< The Address to \e namespace map
|
||||
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 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
|
||||
static void parseParentTag(const Element *el,string &name,vector<string> &parnames);
|
||||
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
|
||||
Architecture *getArch(void) const { return glb; } ///< Get the Architecture associate with \b this
|
||||
void attachScope(Scope *newscope,Scope *parent); ///< Register a new Scope
|
||||
|
|
|
@ -305,7 +305,6 @@ ScopeLocal::ScopeLocal(AddrSpace *spc,Funcdata *fd,Architecture *g) : ScopeInter
|
|||
rangeLocked = false;
|
||||
stackGrowsNegative = true;
|
||||
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
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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) {
|
||||
XmlElement node = parser.peek();
|
||||
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);
|
||||
if (sym == null) {
|
||||
Msg.error(this, "Invalid symbol reference: " + symref);
|
||||
|
|
|
@ -831,12 +831,20 @@ public class DecompileCallback {
|
|||
if ((data.getDataType() == DataType.DEFAULT) && (sym == null) && !isVolatile && !readonly) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String name = sym != null ? sym.getName() : SymbolUtilities.getDynamicName(program, addr);
|
||||
long uniqueId;
|
||||
String name;
|
||||
if (sym != null) {
|
||||
name = sym.getName();
|
||||
uniqueId = sym.getID();
|
||||
}
|
||||
else {
|
||||
name = SymbolUtilities.getDynamicName(program, addr);
|
||||
uniqueId = 0;
|
||||
}
|
||||
|
||||
int sz = data.getLength();
|
||||
String symstring = MappedSymbol.buildSymbolXML(dtmanage, name, data.getDataType(), sz, true,
|
||||
true, readonly, isVolatile, -1, -1);
|
||||
String symstring = MappedSymbol.buildSymbolXML(dtmanage, uniqueId, name, data.getDataType(),
|
||||
sz, true, true, readonly, isVolatile, -1, -1);
|
||||
if (debug != null) {
|
||||
debug.getType(data.getDataType());
|
||||
}
|
||||
|
|
|
@ -44,8 +44,9 @@ public class DynamicSymbol extends HighSymbol {
|
|||
refs = new Entry[0];
|
||||
}
|
||||
|
||||
public DynamicSymbol(String nm,DataType tp,int size,HighFunction func,Address addr,long hash,int format) {
|
||||
super(nm,tp,size,addr,func);
|
||||
public DynamicSymbol(long uniqueId, String nm, DataType tp, int size, HighFunction func,
|
||||
Address addr, long hash, int format) {
|
||||
super(uniqueId, nm, tp, size, addr, func);
|
||||
refs = new Entry[1];
|
||||
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) {
|
||||
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[refs.length] = new Entry(addr,hash,format);
|
||||
refs = newrefs;
|
||||
if (refs.length == 1)
|
||||
{
|
||||
pcaddr = addr; // Store first address as official pcaddr for symbol
|
||||
}
|
||||
}
|
||||
|
||||
protected void buildHashXML(StringBuilder buf) {
|
||||
for(int i=0;i<refs.length;++i) {
|
||||
buf.append("<hash val=\"0x").append(Long.toHexString(refs[i].hash)).append("\"/>");
|
||||
buildRangelistXML(buf, refs[i].pcaddr);
|
||||
for (Entry ref : refs) {
|
||||
buf.append("<hash val=\"0x").append(Long.toHexString(ref.hash)).append("\"/>");
|
||||
buildRangelistXML(buf, ref.pcaddr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,15 +88,16 @@ public class DynamicSymbol extends HighSymbol {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
|
||||
public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
|
||||
XmlElement symel = parser.start("symbol");
|
||||
int symbolId = restoreSymbolXML(symel, func);
|
||||
restoreSymbolXML(symel, func);
|
||||
type = func.getDataTypeManager().readXMLDataType(parser);
|
||||
size = type.getLength();
|
||||
parser.end(symel);
|
||||
|
||||
if (size == 0)
|
||||
if (size == 0) {
|
||||
throw new PcodeXMLException("Invalid symbol 0-sized data-type: " + type.getName());
|
||||
}
|
||||
while(parser.peek().isStart()) {
|
||||
long hash = 0;
|
||||
int format = 0;
|
||||
|
@ -103,7 +108,6 @@ public class DynamicSymbol extends HighSymbol {
|
|||
Address addr = parseRangeList(parser);
|
||||
addReference(addr,hash,format);
|
||||
}
|
||||
return symbolId;
|
||||
}
|
||||
|
||||
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, "namelock", nl);
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "readonly", ro);
|
||||
if (isVolatile)
|
||||
if (isVolatile) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "volatile", true);
|
||||
}
|
||||
res.append(">\n");
|
||||
res.append(dtmanage.buildTypeRef(dt, length));
|
||||
res.append("</symbol>\n");
|
||||
|
|
|
@ -36,14 +36,16 @@ public class EquateSymbol extends DynamicSymbol {
|
|||
public EquateSymbol() {
|
||||
}
|
||||
|
||||
public EquateSymbol(String nm,long val,HighFunction func,Address addr,long hash,int format) {
|
||||
super(nm, DataType.DEFAULT, 1, func, addr, hash, format);
|
||||
public EquateSymbol(long uniqueId, String nm, long val, HighFunction func, Address addr,
|
||||
long hash, int format) {
|
||||
super(uniqueId, nm, DataType.DEFAULT, 1, func, addr, hash, format);
|
||||
value = val;
|
||||
convert = FORMAT_DEFAULT;
|
||||
}
|
||||
|
||||
public EquateSymbol(int conv,long val,HighFunction func,Address addr,long hash,int format) {
|
||||
super("", DataType.DEFAULT, 1, func, addr, hash, format);
|
||||
public EquateSymbol(long uniqueId, int conv, long val, HighFunction func, Address addr,
|
||||
long hash, int format) {
|
||||
super(uniqueId, "", DataType.DEFAULT, 1, func, addr, hash, format);
|
||||
value = val;
|
||||
convert = conv;
|
||||
}
|
||||
|
@ -51,9 +53,9 @@ public class EquateSymbol extends DynamicSymbol {
|
|||
public long getValue() { return value; }
|
||||
|
||||
@Override
|
||||
public int restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
|
||||
public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
|
||||
XmlElement symel = parser.start("equatesymbol");
|
||||
int symbolId = restoreSymbolXML(symel, func);
|
||||
restoreSymbolXML(symel, func);
|
||||
type = DataType.DEFAULT;
|
||||
size = 1;
|
||||
convert = FORMAT_DEFAULT;
|
||||
|
@ -92,7 +94,6 @@ public class EquateSymbol extends DynamicSymbol {
|
|||
Address addr = parseRangeList(parser);
|
||||
addReference(addr,hash,format);
|
||||
}
|
||||
return symbolId;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -120,7 +120,7 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
}
|
||||
|
||||
@Override
|
||||
public HighSymbol getSymbol(int symbolId) {
|
||||
public HighSymbol getSymbol(long 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
|
||||
// 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.
|
||||
sym = localSymbols.newMappedSymbol(highloc.getName(), highloc.getDataType(),
|
||||
new VariableStorage(func.getProgram(), vn), vn.getPCAddress(), -1,
|
||||
vn.hashCode());
|
||||
sym = localSymbols.newMappedSymbol(0, highloc.getName(), highloc.getDataType(),
|
||||
new VariableStorage(func.getProgram(), vn), vn.getPCAddress(), -1);
|
||||
reslocal = new HighLocal(highloc.getDataType(), vn, null, vn.getPCAddress(), sym);
|
||||
|
||||
resremain = highloc; // Keep remaining varnodes in old high
|
||||
|
|
|
@ -24,6 +24,7 @@ import ghidra.xml.XmlPullParser;
|
|||
|
||||
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 DataType type;
|
||||
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 typelock; // Is this variable's datatype locked
|
||||
private boolean readonly;
|
||||
private long id; // Unique id of this symbol
|
||||
|
||||
private HighVariable highVariable;
|
||||
|
||||
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;
|
||||
type = tp;
|
||||
size = sz;
|
||||
|
@ -46,6 +49,11 @@ public abstract class HighSymbol {
|
|||
namelock = false;
|
||||
typelock = false;
|
||||
function = func;
|
||||
id = uniqueId;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setHighVariable(HighVariable high) {
|
||||
|
@ -102,25 +110,26 @@ public abstract class HighSymbol {
|
|||
|
||||
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;
|
||||
int symbolId = SpecXmlUtils.decodeInt(symel.getAttribute("id"));
|
||||
if (symbolId == 0) {
|
||||
id = SpecXmlUtils.decodeLong(symel.getAttribute("id"));
|
||||
if (id == 0) {
|
||||
throw new PcodeXMLException("missing unique symbol id");
|
||||
}
|
||||
typelock = false;
|
||||
String typelockstr = symel.getAttribute("typelock");
|
||||
if ((typelockstr != null) && (SpecXmlUtils.decodeBoolean(typelockstr)))
|
||||
if ((typelockstr != null) && (SpecXmlUtils.decodeBoolean(typelockstr))) {
|
||||
typelock = true;
|
||||
}
|
||||
namelock = false;
|
||||
String namelockstr = symel.getAttribute("namelock");
|
||||
if ((namelockstr != null) && (SpecXmlUtils.decodeBoolean(namelockstr)))
|
||||
if ((namelockstr != null) && (SpecXmlUtils.decodeBoolean(namelockstr))) {
|
||||
namelock = true;
|
||||
}
|
||||
name = symel.getAttribute("name");
|
||||
|
||||
return symbolId;
|
||||
}
|
||||
|
||||
protected Address parseRangeList(XmlPullParser parser) {
|
||||
|
|
|
@ -39,8 +39,9 @@ public class LocalSymbolMap {
|
|||
private HighFunction func; // Function to which these variables are local
|
||||
private String spacename;
|
||||
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 long uniqueSymbolId; // Next available symbol id
|
||||
|
||||
/**
|
||||
* @param highFunc HighFunction the local variables are defined within.
|
||||
|
@ -50,21 +51,31 @@ public class LocalSymbolMap {
|
|||
func = highFunc;
|
||||
spacename = spcname;
|
||||
addrMappedSymbols = new HashMap<MappedVarKey, HighSymbol>();
|
||||
symbolMap = new HashMap<Integer, HighSymbol>();
|
||||
symbolMap = new HashMap<Long, HighSymbol>();
|
||||
paramSymbols = new MappedSymbol[0];
|
||||
uniqueSymbolId = 0;
|
||||
}
|
||||
|
||||
public HighFunction getHighFunction() {
|
||||
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.
|
||||
* @param includeDefaultNames is true if default symbol names should be considered locked
|
||||
*/
|
||||
public void grabFromFunction(boolean includeDefaultNames) {
|
||||
Function dbFunction = func.getFunction();
|
||||
int uniqueSymbolId = 0;
|
||||
Variable locals[] = dbFunction.getLocalVariables();
|
||||
for (Variable local : locals) {
|
||||
Variable var = local;
|
||||
|
@ -82,18 +93,18 @@ public class LocalSymbolMap {
|
|||
String name = var.getName();
|
||||
|
||||
VariableStorage storage = var.getVariableStorage();
|
||||
long id = getNextId();
|
||||
Address defAddr = null;
|
||||
if (!storage.isStackStorage()) {
|
||||
defAddr = dbFunction.getEntryPoint().addWrap(var.getFirstUseOffset());
|
||||
}
|
||||
HighSymbol sym;
|
||||
if (storage.isHashStorage()) {
|
||||
sym =
|
||||
newDynamicSymbol(name, dt, sz, storage.getFirstVarnode().getOffset(), defAddr,
|
||||
0, ++uniqueSymbolId);
|
||||
sym = newDynamicSymbol(id, name, dt, sz, storage.getFirstVarnode().getOffset(),
|
||||
defAddr, 0);
|
||||
}
|
||||
else {
|
||||
sym = newMappedSymbol(name, dt, storage, defAddr, -1, ++uniqueSymbolId);
|
||||
sym = newMappedSymbol(id, name, dt, storage, defAddr, -1);
|
||||
}
|
||||
sym.setTypeLock(istypelock);
|
||||
sym.setNameLock(isnamelock);
|
||||
|
@ -116,8 +127,9 @@ public class LocalSymbolMap {
|
|||
String name = var.getName();
|
||||
VariableStorage storage = var.getVariableStorage();
|
||||
Address resAddr = storage.isStackStorage() ? null : pcaddr;
|
||||
long id = getNextId();
|
||||
MappedSymbol paramSymbol =
|
||||
newMappedSymbol(name, dt, storage, resAddr, i, ++uniqueSymbolId);
|
||||
newMappedSymbol(id, name, dt, storage, resAddr, i);
|
||||
paramList.add(paramSymbol);
|
||||
boolean namelock = true;
|
||||
if (!includeDefaultNames) {
|
||||
|
@ -131,7 +143,7 @@ public class LocalSymbolMap {
|
|||
paramList.toArray(paramSymbols);
|
||||
Arrays.sort(paramSymbols, PARAM_SYMBOL_SLOT_COMPARATOR);
|
||||
|
||||
uniqueSymbolId = grabEquates(dbFunction, uniqueSymbolId);
|
||||
grabEquates(dbFunction);
|
||||
}
|
||||
|
||||
private boolean isUserDefinedName(String name) {
|
||||
|
@ -164,9 +176,9 @@ public class LocalSymbolMap {
|
|||
res = new EquateSymbol();
|
||||
}
|
||||
|
||||
int symbolId = res.restoreXML(parser, func);
|
||||
res.restoreXML(parser, func);
|
||||
parser.end(node);
|
||||
insertSymbol(res,symbolId);
|
||||
insertSymbol(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -290,7 +302,7 @@ public class LocalSymbolMap {
|
|||
* @param id symbol-id
|
||||
* @return variable or null if not found
|
||||
*/
|
||||
public HighSymbol getSymbol(int id) {
|
||||
public HighSymbol getSymbol(long id) {
|
||||
return symbolMap.get(id);
|
||||
}
|
||||
|
||||
|
@ -316,43 +328,60 @@ public class LocalSymbolMap {
|
|||
return false;
|
||||
}
|
||||
|
||||
public MappedSymbol newMappedSymbol(String nm, DataType dt, VariableStorage store,
|
||||
Address pcaddr, int slot, int id) {
|
||||
MappedSymbol sym = new MappedSymbol(nm, dt, store, pcaddr, func, slot);
|
||||
insertSymbol(sym,id);
|
||||
public MappedSymbol newMappedSymbol(long id, String nm, DataType dt, VariableStorage store,
|
||||
Address pcaddr, int slot) {
|
||||
if (id == 0) {
|
||||
id = getNextId();
|
||||
}
|
||||
MappedSymbol sym = new MappedSymbol(id, nm, dt, store, pcaddr, func, slot);
|
||||
insertSymbol(sym);
|
||||
return sym;
|
||||
}
|
||||
|
||||
public DynamicSymbol newDynamicSymbol(String nm, DataType dt, int sz, long hash,
|
||||
Address pcaddr, int format, int id) {
|
||||
DynamicSymbol sym = new DynamicSymbol(nm, dt, sz, func, pcaddr, hash, format);
|
||||
insertSymbol(sym,id);
|
||||
public DynamicSymbol newDynamicSymbol(long id, String nm, DataType dt, int sz, long hash,
|
||||
Address pcaddr, int format) {
|
||||
if (id == 0) {
|
||||
id = getNextId();
|
||||
}
|
||||
DynamicSymbol sym = new DynamicSymbol(id, nm, dt, sz, func, pcaddr, hash, format);
|
||||
insertSymbol(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) {
|
||||
MappedSymbol mapSym = (MappedSymbol)sym;
|
||||
MappedVarKey key = new MappedVarKey(mapSym.getStorage(),mapSym.getPCAddress());
|
||||
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) {
|
||||
DynamicSymbol eqSymbol = constantSymbolMap.get(nm);
|
||||
if (eqSymbol != null) {
|
||||
eqSymbol.addReference(addr, hash, format); // New reference to same symbol
|
||||
return;
|
||||
}
|
||||
if (uniqueId == 0) {
|
||||
uniqueId = getNextId();
|
||||
}
|
||||
int conv = EquateSymbol.convertName(nm, val);
|
||||
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);
|
||||
}
|
||||
else {
|
||||
eqSymbol = new EquateSymbol(conv, val, func, addr, hash, format);
|
||||
eqSymbol = new EquateSymbol(uniqueId, conv, val, func, addr, hash, format);
|
||||
}
|
||||
//Do NOT setTypeLock
|
||||
constantSymbolMap.put(nm, eqSymbol);
|
||||
|
@ -361,10 +390,8 @@ public class LocalSymbolMap {
|
|||
/**
|
||||
* Build dynamic symbols based on equates
|
||||
* @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;
|
||||
// Find named constants via Equates
|
||||
Program program = dbFunction.getProgram();
|
||||
|
@ -383,7 +410,7 @@ public class LocalSymbolMap {
|
|||
if (constantSymbolMap == null) {
|
||||
constantSymbolMap = new TreeMap<String, DynamicSymbol>();
|
||||
}
|
||||
newEquateSymbol(eq.getDisplayName(), eq.getValue(), element, defAddr, 0,
|
||||
newEquateSymbol(0, eq.getDisplayName(), eq.getValue(), element, defAddr, 0,
|
||||
constantSymbolMap);
|
||||
}
|
||||
}
|
||||
|
@ -405,10 +432,10 @@ public class LocalSymbolMap {
|
|||
// Add constant dynamic symbols to map
|
||||
if (constantSymbolMap != null) {
|
||||
for (DynamicSymbol sym : constantSymbolMap.values()) {
|
||||
symbolMap.put(++uniqueSymbolId, sym);
|
||||
long id = getNextId();
|
||||
symbolMap.put(id, sym);
|
||||
}
|
||||
}
|
||||
return uniqueSymbolId;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,21 +33,25 @@ public class MappedSymbol extends HighSymbol {
|
|||
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) {
|
||||
super(name, dt, store.size(), pcaddr, func);
|
||||
super(uniqueId, name, dt, store.size(), pcaddr, func);
|
||||
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");
|
||||
}
|
||||
}
|
||||
this.storage = store;
|
||||
this.slot = slot;
|
||||
Varnode rep = function.createFromStorage(null, storage, dt.getLength());
|
||||
HighVariable var;
|
||||
if (slot < 0)
|
||||
if (slot < 0) {
|
||||
var = new HighLocal(type, rep, null, pcaddr, this);
|
||||
else
|
||||
}
|
||||
else {
|
||||
var = new HighParam(type, rep, pcaddr, slot, this);
|
||||
}
|
||||
setHighVariable(var);
|
||||
var.setHighOnInstances();
|
||||
}
|
||||
|
@ -71,26 +75,29 @@ public class MappedSymbol extends HighSymbol {
|
|||
}
|
||||
StringBuilder res = new StringBuilder();
|
||||
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);
|
||||
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
|
||||
}
|
||||
String addrRes = Varnode.buildXMLAddress(storage.getVarnodes(), logicalsize);
|
||||
buildMapSymXML(res, addrRes, getPCAddress(), sym);
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int restoreXML(XmlPullParser parser,HighFunction func) throws PcodeXMLException {
|
||||
public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
|
||||
XmlElement symel = parser.start("symbol");
|
||||
int symbolId = restoreSymbolXML(symel, func);
|
||||
restoreSymbolXML(symel, func);
|
||||
slot = -1;
|
||||
int cat = -1;
|
||||
if (symel.hasAttribute("cat")) {
|
||||
cat = SpecXmlUtils.decodeInt(symel.getAttribute("cat"));
|
||||
if (cat == 0)
|
||||
if (cat == 0) {
|
||||
slot = SpecXmlUtils.decodeInt(symel.getAttribute("index"));
|
||||
}
|
||||
}
|
||||
type = func.getDataTypeManager().readXMLDataType(parser);
|
||||
parser.end(symel);
|
||||
|
@ -129,26 +136,34 @@ public class MappedSymbol extends HighSymbol {
|
|||
pcaddr = parseRangeList(parser);
|
||||
Varnode rep = function.createFromStorage(addr, storage, sz);
|
||||
HighVariable var;
|
||||
if (slot < 0)
|
||||
if (slot < 0) {
|
||||
var = new HighLocal(type, rep, null, pcaddr, this);
|
||||
else
|
||||
}
|
||||
else {
|
||||
var = new HighParam(type, rep, pcaddr, slot, this);
|
||||
}
|
||||
setHighVariable(var);
|
||||
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,
|
||||
boolean isVolatile, int cat, int slot) {
|
||||
StringBuilder res = new StringBuilder();
|
||||
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.encodeBooleanAttribute(res, "typelock", tl);
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "namelock", nl);
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "readonly", ro);
|
||||
if (isVolatile)
|
||||
if (isVolatile) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "volatile", true);
|
||||
}
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(res, "cat", cat);
|
||||
if (slot >= 0) {
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(res, "index", slot);
|
||||
|
|
|
@ -57,7 +57,8 @@ public interface PcodeFactory {
|
|||
public VariableStorage buildStorage(Varnode vn) throws InvalidInputException;
|
||||
public Varnode getRef(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 void setAddrTied(Varnode vn,boolean val);
|
||||
public void setPersistant(Varnode vn,boolean val);
|
||||
|
|
|
@ -142,8 +142,9 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
|||
// bad prototypes causing the decompiler to produce weird stuff
|
||||
// TODO: We should emit some kind of warning
|
||||
int sz = 0;
|
||||
for (Varnode piece : pieces)
|
||||
for (Varnode piece : pieces) {
|
||||
sz += piece.getSize();
|
||||
}
|
||||
Address uniqaddr = addrFactory.getUniqueSpace().getAddress(0x20000000);
|
||||
storage = new VariableStorage(datatypeManager.getProgram(),uniqaddr,sz);
|
||||
}
|
||||
|
@ -156,26 +157,30 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
|||
else {
|
||||
offObject = new Integer((int)offset);
|
||||
offset += roundsize;
|
||||
if (offset > joinAllocate)
|
||||
if (offset > joinAllocate) {
|
||||
joinAllocate = (int)offset;
|
||||
}
|
||||
}
|
||||
if (joinmap == null)
|
||||
if (joinmap == null) {
|
||||
joinmap = new HashMap<Integer,VariableStorage>();
|
||||
}
|
||||
joinmap.put(offObject, storage);
|
||||
return storage;
|
||||
}
|
||||
|
||||
private VariableStorage findJoinStorage(long offset) {
|
||||
if (joinmap == null)
|
||||
if (joinmap == null) {
|
||||
return null;
|
||||
}
|
||||
return joinmap.get(new Integer((int)offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VariableStorage buildStorage(Varnode vn) throws InvalidInputException {
|
||||
Address addr = vn.getAddress();
|
||||
if (addr.getAddressSpace().getType() == AddressSpace.TYPE_VARIABLE)
|
||||
if (addr.getAddressSpace().getType() == AddressSpace.TYPE_VARIABLE) {
|
||||
return findJoinStorage(addr.getOffset());
|
||||
}
|
||||
return new VariableStorage(datatypeManager.getProgram(),vn);
|
||||
}
|
||||
|
||||
|
@ -306,10 +311,12 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
|||
@Override
|
||||
public Varnode newVarnode(int sz, Address addr, int id) {
|
||||
Varnode vn = vbank.create(sz, addr, id);
|
||||
if (uniqId <= id)
|
||||
if (uniqId <= id) {
|
||||
uniqId = id + 1;
|
||||
if (refmap != null)
|
||||
}
|
||||
if (refmap != null) {
|
||||
refmap.put(id, vn);
|
||||
}
|
||||
return vn;
|
||||
}
|
||||
|
||||
|
@ -342,10 +349,12 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
|||
|
||||
@Override
|
||||
public Varnode setInput(Varnode vn, boolean val) {
|
||||
if ((!vn.isInput()) && val)
|
||||
if ((!vn.isInput()) && val) {
|
||||
return vbank.setInput(vn);
|
||||
if (vn.isInput() && (!val))
|
||||
}
|
||||
if (vn.isInput() && (!val)) {
|
||||
vbank.makeFree(vn);
|
||||
}
|
||||
return vn;
|
||||
}
|
||||
|
||||
|
@ -360,13 +369,14 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
|||
|
||||
@Override
|
||||
public Varnode getRef(int id) {
|
||||
if (refmap == null)
|
||||
if (refmap == null) {
|
||||
return null;
|
||||
}
|
||||
return refmap.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HighSymbol getSymbol(int symbolId) {
|
||||
public HighSymbol getSymbol(long symbolId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -410,8 +420,9 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
|||
|
||||
@Override
|
||||
public PcodeOp getOpRef(int id) {
|
||||
if (oprefmap == null)
|
||||
if (oprefmap == null) {
|
||||
buildOpRefs();
|
||||
}
|
||||
return oprefmap.get(id);
|
||||
}
|
||||
|
||||
|
@ -437,12 +448,16 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
|||
|
||||
public void setOutput(PcodeOp op, Varnode vn) {
|
||||
if (vn == op.getOutput())
|
||||
{
|
||||
return; // Output already set to this
|
||||
if (op.getOutput() != null)
|
||||
}
|
||||
if (op.getOutput() != null) {
|
||||
unSetOutput(op);
|
||||
}
|
||||
|
||||
if (vn.getDef() != null) // Varnode is already an output
|
||||
if (vn.getDef() != null) {
|
||||
unSetOutput(vn.getDef());
|
||||
}
|
||||
vn = vbank.setDef(vn, op);
|
||||
op.setOutput(vn);
|
||||
}
|
||||
|
@ -450,16 +465,21 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
|||
public void unSetOutput(PcodeOp op) {
|
||||
Varnode vn = op.getOutput();
|
||||
if (vn == null)
|
||||
{
|
||||
return; // Nothing to do
|
||||
}
|
||||
op.setOutput(null);
|
||||
vbank.makeFree(vn);
|
||||
}
|
||||
|
||||
public void setInput(PcodeOp op, Varnode vn, int slot) {
|
||||
if (slot >= op.getNumInputs())
|
||||
{
|
||||
op.setInput(null, slot); // Expand number of inputs as necessary
|
||||
if (op.getInput(slot) != null)
|
||||
}
|
||||
if (op.getInput(slot) != null) {
|
||||
unSetInput(op, slot);
|
||||
}
|
||||
if (vn != null) {
|
||||
VarnodeAST vnast = (VarnodeAST) vn;
|
||||
vnast.addDescendant(op);
|
||||
|
@ -484,29 +504,35 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
|||
|
||||
public void unlink(PcodeOpAST op) {
|
||||
unSetOutput(op);
|
||||
for (int i = 0; i < op.getNumInputs(); ++i)
|
||||
for (int i = 0; i < op.getNumInputs(); ++i) {
|
||||
unSetInput(op, i);
|
||||
if (op.getParent() != null)
|
||||
}
|
||||
if (op.getParent() != null) {
|
||||
unInsert(op);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp newOp(SequenceNumber sq, int opc, ArrayList<Varnode> inputs, Varnode output)
|
||||
throws UnknownInstructionException {
|
||||
PcodeOp op = opbank.create(opc, inputs.size(), sq);
|
||||
if (output != null)
|
||||
if (output != null) {
|
||||
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);
|
||||
if (oprefmap != null)
|
||||
}
|
||||
if (oprefmap != null) {
|
||||
oprefmap.put(sq.getTime(), op);
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
private void readVarnodeXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("varnodes");
|
||||
while (parser.peek().isStart())
|
||||
while (parser.peek().isStart()) {
|
||||
Varnode.readXML(parser, this);
|
||||
}
|
||||
parser.end(el);
|
||||
}
|
||||
|
||||
|
@ -524,8 +550,9 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
|||
bl.insertEnd(op);
|
||||
}
|
||||
int index = bl.getIndex();
|
||||
while (bblocks.size() <= index)
|
||||
while (bblocks.size() <= index) {
|
||||
bblocks.add(null);
|
||||
}
|
||||
bblocks.set(index, bl);
|
||||
parser.end(el);
|
||||
}
|
||||
|
@ -542,17 +569,20 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
|||
|
||||
public void readXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("ast");
|
||||
if (!vbank.isEmpty())
|
||||
if (!vbank.isEmpty()) {
|
||||
clear();
|
||||
}
|
||||
readVarnodeXML(parser);
|
||||
buildVarnodeRefs(); // Build the HashMap
|
||||
BlockMap blockMap = new BlockMap(addrFactory);
|
||||
while (parser.peek().isStart()) {
|
||||
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
|
||||
else // Read block edges
|
||||
}
|
||||
else {
|
||||
readBlockEdgeXML(parser);
|
||||
}
|
||||
}
|
||||
parser.end(el);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue