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 <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);

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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());
}

View file

@ -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");

View file

@ -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

View file

@ -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

View file

@ -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,8 +49,13 @@ public abstract class HighSymbol {
namelock = false;
typelock = false;
function = func;
id = uniqueId;
}
public long getId() {
return id;
}
public void setHighVariable(HighVariable high) {
this.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) {

View file

@ -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;
}
/**

View file

@ -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);

View file

@ -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);

View file

@ -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);
}