Refactoring based on HighSymbol

This commit is contained in:
caheckman 2019-12-06 12:12:58 -05:00
parent d552aa4b82
commit 76d0f12bd3
28 changed files with 631 additions and 470 deletions

View file

@ -393,7 +393,7 @@ void DynamicHash::uniqueHash(const Varnode *root,Funcdata *fd)
/// \param addr is the given address /// \param addr is the given address
/// \param h is the hash /// \param h is the hash
/// \return the matching Varnode or NULL /// \return the matching Varnode or NULL
Varnode *DynamicHash::findVarnode(Funcdata *fd,const Address &addr,uint8 h) Varnode *DynamicHash::findVarnode(const Funcdata *fd,const Address &addr,uint8 h)
{ {
uint4 method = getMethodFromHash(h); uint4 method = getMethodFromHash(h);
@ -423,7 +423,7 @@ Varnode *DynamicHash::findVarnode(Funcdata *fd,const Address &addr,uint8 h)
/// \param fd is the function holding the data-flow /// \param fd is the function holding the data-flow
/// \param addr is the given address /// \param addr is the given address
/// \param h is the given hash /// \param h is the given hash
void DynamicHash::gatherFirstLevelVars(vector<Varnode *> &varlist,Funcdata *fd,const Address &addr,uint8 h) void DynamicHash::gatherFirstLevelVars(vector<Varnode *> &varlist,const Funcdata *fd,const Address &addr,uint8 h)
{ {
OpCode opc = getOpCodeFromHash(h); OpCode opc = getOpCodeFromHash(h);

View file

@ -79,11 +79,11 @@ public:
void clear(void); ///< Called for each additional hash (after the first) void clear(void); ///< Called for each additional hash (after the first)
void calcHash(const Varnode *root,uint4 method); ///< Calculate the hash for given Varnode and method void calcHash(const Varnode *root,uint4 method); ///< Calculate the hash for given Varnode and method
void uniqueHash(const Varnode *root,Funcdata *fd); ///< Select a unique hash for the given Varnode void uniqueHash(const Varnode *root,Funcdata *fd); ///< Select a unique hash for the given Varnode
Varnode *findVarnode(Funcdata *fd,const Address &addr,uint8 h); Varnode *findVarnode(const Funcdata *fd,const Address &addr,uint8 h);
uint8 getHash(void) const { return hash; } ///< Get the (current) hash uint8 getHash(void) const { return hash; } ///< Get the (current) hash
const Address &getAddress(void) const { return addrresult; } ///< Get the (current) address const Address &getAddress(void) const { return addrresult; } ///< Get the (current) address
static void gatherFirstLevelVars(vector<Varnode *> &varlist,Funcdata *fd,const Address &addr,uint8 h); static void gatherFirstLevelVars(vector<Varnode *> &varlist,const Funcdata *fd,const Address &addr,uint8 h);
static int4 getSlotFromHash(uint8 h); ///< Retrieve the encoded slot from a hash static int4 getSlotFromHash(uint8 h); ///< Retrieve the encoded slot from a hash
static uint4 getMethodFromHash(uint8 h); ///< Retrieve the encoded method from a hash static uint4 getMethodFromHash(uint8 h); ///< Retrieve the encoded method from a hash
static OpCode getOpCodeFromHash(uint8 h); ///< Retrieve the encoded op-code from a hash static OpCode getOpCodeFromHash(uint8 h); ///< Retrieve the encoded op-code from a hash

View file

@ -607,7 +607,6 @@ void Funcdata::saveVarnodeXml(ostream &s,VarnodeLocSet::const_iterator iter,Varn
void Funcdata::saveXmlHigh(ostream &s) const void Funcdata::saveXmlHigh(ostream &s) const
{ {
int4 j;
Varnode *vn; Varnode *vn;
HighVariable *high; HighVariable *high;
@ -620,32 +619,7 @@ void Funcdata::saveXmlHigh(ostream &s) const
high = vn->getHigh(); high = vn->getHigh();
if (high->isMark()) continue; if (high->isMark()) continue;
high->setMark(); high->setMark();
vn = high->getNameRepresentative(); // Get representative varnode high->saveXml(s);
s << "<high ";
// a_v(s,"name",high->getName());
a_v_u(s,"repref",vn->getCreateIndex());
if (high->isSpacebase()||high->isImplied()) // This is a special variable
a_v(s,"class",string("other"));
else if (high->isPersist()&&high->isAddrTied()) // Global variable
a_v(s,"class",string("global"));
else if (high->isConstant())
a_v(s,"class",string("constant"));
else if (!high->isPersist())
a_v(s,"class",string("local"));
else
a_v(s,"class",string("other"));
if (high->isTypeLock())
a_v_b(s,"typelock",true);
if (high->getSymbol() != (Symbol *)0)
a_v_u(s,"symref",high->getSymbol()->getId());
s << '>';
high->getType()->saveXml(s);
for(j=0;j<high->numInstances();++j) {
s << "<addr ";
a_v_u(s,"ref",high->getInstance(j)->getCreateIndex());
s << "/>";
}
s << "</high>";
} }
for(iter=beginLoc();iter!=endLoc();++iter) { for(iter=beginLoc();iter!=endLoc();++iter) {
vn = *iter; vn = *iter;

View file

@ -315,6 +315,14 @@ HighVariable *Funcdata::findHigh(const string &name) const
Symbol *sym = symList[0]; Symbol *sym = symList[0];
SymbolEntry *entry = sym->getFirstWholeMap(); SymbolEntry *entry = sym->getFirstWholeMap();
if (entry->isDynamic()) {
DynamicHash dhash;
Varnode *vn = dhash.findVarnode(this, entry->getFirstUseAddress(), entry->getHash());
if (vn == (Varnode *)0 || vn->isAnnotation())
return (HighVariable *)0;
return vn->getHigh();
}
VarnodeLocSet::const_iterator iter,enditer; VarnodeLocSet::const_iterator iter,enditer;
HighVariable *high; HighVariable *high;

View file

@ -359,6 +359,46 @@ int4 HighVariable::instanceIndex(const Varnode *vn) const
return -1; return -1;
} }
/// \param s is the output stream to write XML to
void HighVariable::saveXml(ostream &s) const
{
Varnode *vn = getNameRepresentative(); // Get representative varnode
s << "<high ";
// a_v(s,"name",high->getName());
a_v_u(s,"repref",vn->getCreateIndex());
if (isSpacebase()||isImplied()) // This is a special variable
a_v(s,"class",string("other"));
else if (isPersist()&&isAddrTied()) // Global variable
a_v(s,"class",string("global"));
else if (isConstant())
a_v(s,"class",string("constant"));
else if (!isPersist() && (symbol != (Symbol *)0)) {
if (symbol->getCategory() == 0)
a_v(s,"class",string("param"));
else
a_v(s,"class",string("local"));
}
else {
a_v(s,"class",string("other"));
}
if (isTypeLock())
a_v_b(s,"typelock",true);
if (symbol != (Symbol *)0) {
a_v_u(s,"symref",symbol->getId());
if (symboloffset >= 0)
a_v_i(s, "offset", symboloffset);
}
s << '>';
getType()->saveXml(s);
for(int4 j=0;j<inst.size();++j) {
s << "<addr ";
a_v_u(s,"ref",inst[j]->getCreateIndex());
s << "/>";
}
s << "</high>";
}
#ifdef MERGEMULTI_DEBUG #ifdef MERGEMULTI_DEBUG
/// \brief Check that there are no internal Cover intersections within \b this /// \brief Check that there are no internal Cover intersections within \b this
/// ///

View file

@ -129,6 +129,7 @@ public:
bool isUnattached(void) const { return inst.empty(); } ///< Return \b true if \b this has no member Varnode bool isUnattached(void) const { return inst.empty(); } ///< Return \b true if \b this has no member Varnode
bool isTypeLock(void) const { updateType(); return ((flags & Varnode::typelock)!=0); } ///< Return \b true if \b this is \e typelocked bool isTypeLock(void) const { updateType(); return ((flags & Varnode::typelock)!=0); } ///< Return \b true if \b this is \e typelocked
bool isNameLock(void) const { updateFlags(); return ((flags & Varnode::namelock)!=0); } ///< Return \b true if \b this is \e namelocked bool isNameLock(void) const { updateFlags(); return ((flags & Varnode::namelock)!=0); } ///< Return \b true if \b this is \e namelocked
void saveXml(ostream &s) const; ///< Save the variable to stream as an XML \<high\> tag
#ifdef MERGEMULTI_DEBUG #ifdef MERGEMULTI_DEBUG
void verifyCover(void) const; void verifyCover(void) const;
#endif #endif

View file

@ -208,9 +208,10 @@ public class DecompilerParameterIdCmd extends BackgroundCommand {
boolean commitReturn = true; boolean commitReturn = true;
if (!commitVoidReturn) { if (!commitVoidReturn) {
DataType returnType = hfunc.getFunctionPrototype().getReturnType(); DataType returnType = hfunc.getFunctionPrototype().getReturnType();
if (returnType instanceof VoidDataType) if (returnType instanceof VoidDataType) {
commitReturn = false; commitReturn = false;
} }
}
if (commitReturn) { if (commitReturn) {
HighFunctionDBUtil.commitReturnToDatabase(hfunc, SourceType.ANALYSIS); HighFunctionDBUtil.commitReturnToDatabase(hfunc, SourceType.ANALYSIS);
} }
@ -274,7 +275,7 @@ public class DecompilerParameterIdCmd extends BackgroundCommand {
if (sym.getName().equals("in_FS_OFFSET")) { if (sym.getName().equals("in_FS_OFFSET")) {
continue; continue;
} }
if (!sym.getHighVariable().getStorage().isRegisterStorage()) { if (!sym.getStorage().isRegisterStorage()) {
continue; continue;
} }

View file

@ -64,9 +64,5 @@ public class ClangVariableDecl extends ClangTokenGroup {
} }
typevar = sym.getHighVariable(); typevar = sym.getHighVariable();
datatype = sym.getDataType(); datatype = sym.getDataType();
if (typevar == null) {
Msg.error(this, "High variable not found: " + sym.getName());
return;
}
} }
} }

View file

@ -130,7 +130,7 @@ public class FillOutStructureCmd extends BackgroundCommand {
} }
} }
if (var == null) { if (var == null || var.getSymbol() == null || var.getOffset() >= 0) {
return false; return false;
} }
@ -232,7 +232,8 @@ public class FillOutStructureCmd extends BackgroundCommand {
private void commitVariable(HighVariable var, DataType newDt, boolean isThisParam) { private void commitVariable(HighVariable var, DataType newDt, boolean isThisParam) {
if (!isThisParam) { if (!isThisParam) {
try { try {
HighFunctionDBUtil.updateDBVariable(var, null, newDt, SourceType.USER_DEFINED); HighFunctionDBUtil.updateDBVariable(var.getSymbol(), null, newDt,
SourceType.USER_DEFINED);
} }
catch (DuplicateNameException e) { catch (DuplicateNameException e) {
throw new AssertException("Unexpected exception", e); throw new AssertException("Unexpected exception", e);

View file

@ -151,6 +151,9 @@ public class RenameVariableAction extends AbstractDecompilerAction {
return false; return false;
} }
} }
if (variable.getSymbol() == null) {
return false;
}
if (variable instanceof HighLocal) { if (variable instanceof HighLocal) {
getPopupMenuData().setMenuItemName("Rename Variable"); getPopupMenuData().setMenuItemName("Rename Variable");
return true; return true;
@ -159,11 +162,6 @@ public class RenameVariableAction extends AbstractDecompilerAction {
getPopupMenuData().setMenuItemName("Rename Global"); getPopupMenuData().setMenuItemName("Rename Global");
return true; return true;
} }
//TODO: Constant equates do not work properly with decompiler
// else if (variable instanceof HighConstant) {
// getPopupMenuData().setMenuItemName("Rename Constant");
// return true;
// }
return false; return false;
} }
@ -179,20 +177,18 @@ public class RenameVariableAction extends AbstractDecompilerAction {
variable = forgeHighVariable(addr, controller); variable = forgeHighVariable(addr, controller);
} }
} }
//TODO: Constant equates do not work properly with decompiler
// if (variable instanceof HighConstant) {
// nameTask =
// new RenameConstantTask(tool, tokenAtCursor.getText(), (HighConstant) variable,
// controller.getProgram());
// }
// else
if (variable instanceof HighLocal) { if (variable instanceof HighLocal) {
nameTask = nameTask =
new RenameVariableTask(tool, variable.getName(), controller.getHighFunction(), new RenameVariableTask(tool, variable.getSymbol().getName(),
variable, tokenAtCursor.getVarnode(), SourceType.USER_DEFINED); controller.getHighFunction(), variable, tokenAtCursor.getVarnode(),
SourceType.USER_DEFINED);
} }
else if (variable instanceof HighGlobal) { else if (variable instanceof HighGlobal) {
Address addr = variable.getRepresentative().getAddress(); Address addr = null;
HighSymbol sym = variable.getSymbol();
if (sym instanceof HighCodeSymbol) {
addr = ((HighCodeSymbol) sym).getStorage().getMinAddress();
}
if (addr == null || !addr.isMemoryAddress()) { if (addr == null || !addr.isMemoryAddress()) {
Msg.showError(this, tool.getToolFrame(), "Rename Failed", Msg.showError(this, tool.getToolFrame(), "Rename Failed",
"Memory storage not found for global variable"); "Memory storage not found for global variable");

View file

@ -55,7 +55,7 @@ public class RenameVariableTask extends RenameTask {
HighFunctionDBUtil.commitReturnToDatabase(hfunction, signatureSrcType); HighFunctionDBUtil.commitReturnToDatabase(hfunction, signatureSrcType);
} }
} }
HighFunctionDBUtil.updateDBVariable(var, newName, null, srctype); HighFunctionDBUtil.updateDBVariable(var.getSymbol(), newName, null, srctype);
} }
@Override @Override
@ -80,6 +80,10 @@ public class RenameVariableTask extends RenameTask {
return false; return false;
} }
} }
if (var.getSymbol() == null) {
errorMsg = "Rename Failed: No symbol";
return false;
}
return true; return true;
} }

View file

@ -129,13 +129,6 @@ public class RetypeVariableAction extends AbstractDecompilerAction {
boolean commitRequired = checkFullCommit(var, hfunction); boolean commitRequired = checkFullCommit(var, hfunction);
if (commitRequired) { if (commitRequired) {
// int resp = OptionDialog.showOptionDialog(tool.getToolFrame(),
// "Parameter Commit Required",
// "Retyping a parameter requires all other parameters to be committed!\nContinue with retype?",
// "Continue");
// if (resp != OptionDialog.OPTION_ONE) {
// return;
// }
exactSpot = null; // Don't try to split out if commit is required exactSpot = null; // Don't try to split out if commit is required
} }
@ -176,7 +169,7 @@ public class RetypeVariableAction extends AbstractDecompilerAction {
Msg.showError(this, null, "Parameter Commit Failed", e.getMessage()); Msg.showError(this, null, "Parameter Commit Failed", e.getMessage());
} }
} }
HighFunctionDBUtil.updateDBVariable(var, null, dt, SourceType.USER_DEFINED); HighFunctionDBUtil.updateDBVariable(var.getSymbol(), null, dt, SourceType.USER_DEFINED);
successfulMod = true; successfulMod = true;
} }
catch (DuplicateNameException e) { catch (DuplicateNameException e) {
@ -298,7 +291,7 @@ public class RetypeVariableAction extends AbstractDecompilerAction {
} }
for (int i = 0; i < numParams; i++) { for (int i = 0; i < numParams; i++) {
HighParam param = localSymbolMap.getParam(i); MappedSymbol param = localSymbolMap.getParamSymbol(i);
if (param.getSlot() != i) { if (param.getSlot() != i) {
return true; return true;
} }
@ -350,11 +343,10 @@ public class RetypeVariableAction extends AbstractDecompilerAction {
return false; return false;
} }
} }
if (variable instanceof HighConstant) { if (variable.getSymbol() == null) {
// getPopupMenuData().setMenuItemName("Retype Constant"); return false;
// return true;
} }
else if (variable instanceof HighLocal) { if (variable instanceof HighLocal) {
getPopupMenuData().setMenuItemName("Retype Variable"); getPopupMenuData().setMenuItemName("Retype Variable");
return true; return true;
} }
@ -412,7 +404,7 @@ public class RetypeVariableAction extends AbstractDecompilerAction {
return; return;
} }
variable = RenameVariableAction.forgeHighVariable(addr, controller); variable = RenameVariableAction.forgeHighVariable(addr, controller);
if (variable == null) { if (variable == null || variable.getSymbol() == null || variable.getOffset() >= 0) {
return; return;
} }
} }

View file

@ -16,7 +16,12 @@
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.VariableStorage;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement; import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser; import ghidra.xml.XmlPullParser;
@ -26,53 +31,25 @@ import ghidra.xml.XmlPullParser;
* *
*/ */
public class DynamicSymbol extends HighSymbol { public class DynamicSymbol extends HighSymbol {
public static class Entry { protected long hash; // Hash encoding the specific Varnode
public final Address pcaddr;
public final long hash;
public final int format;
public Entry(Address addr,long h,int f) { public DynamicSymbol(HighFunction func) { // For use with restoreXML
pcaddr = addr; super(func);
hash = h;
format = f;
}
}
private Entry[] refs;
public DynamicSymbol() { // For use with restoreXML
refs = new Entry[0];
} }
public DynamicSymbol(long uniqueId, String nm, DataType tp, int size, HighFunction func, public DynamicSymbol(long uniqueId, String nm, DataType tp, int size, HighFunction func,
Address addr, long hash, int format) { Address addr, long hash) {
super(uniqueId, nm, tp, size, addr, func); super(uniqueId, nm, tp, size, addr, func);
refs = new Entry[1]; this.hash = hash;
refs[0] = new Entry(addr,hash,format);
} }
public long getHash() { public long getHash() {
return refs[0].hash; return hash;
}
public void addReference(Address addr,long hash,int format) {
Entry[] newrefs = new Entry[refs.length + 1];
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) { protected void buildHashXML(StringBuilder buf) {
for (Entry ref : refs) { buf.append("<hash val=\"0x").append(Long.toHexString(hash)).append("\"/>");
buf.append("<hash val=\"0x").append(Long.toHexString(ref.hash)).append("\"/>"); buildRangelistXML(buf, pcaddr);
buildRangelistXML(buf, ref.pcaddr);
}
} }
@Override @Override
@ -88,25 +65,39 @@ public class DynamicSymbol extends HighSymbol {
} }
@Override @Override
public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException { public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement symel = parser.start("symbol"); XmlElement symel = parser.start("symbol");
restoreSymbolXML(symel, func); restoreSymbolXML(symel);
type = func.getDataTypeManager().readXMLDataType(parser); type = function.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());
} }
restoreEntryXML(parser);
while(parser.peek().isStart()) { while(parser.peek().isStart()) {
long hash = 0; parser.discardSubTree();
int format = 0; }
}
@Override
protected void restoreEntryXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement addrel = parser.start("hash"); XmlElement addrel = parser.start("hash");
hash = SpecXmlUtils.decodeLong(addrel.getAttribute("val")); hash = SpecXmlUtils.decodeLong(addrel.getAttribute("val"));
format = SpecXmlUtils.decodeInt(symel.getAttribute("format"));
parser.end(addrel); parser.end(addrel);
Address addr = parseRangeList(parser); pcaddr = parseRangeList(parser);
addReference(addr,hash,format); }
@Override
public VariableStorage getStorage() {
Program program = function.getFunction().getProgram();
try {
return new VariableStorage(program, AddressSpace.HASH_SPACE.getAddress(getHash()),
getSize());
}
catch (InvalidInputException e) {
throw new AssertException("Unexpected exception", e);
} }
} }
@ -129,4 +120,23 @@ public class DynamicSymbol extends HighSymbol {
res.append("</symbol>\n"); res.append("</symbol>\n");
return res.toString(); return res.toString();
} }
/**
* Build dynamic VariableStorage for a unique variable
* @param vn is the variable in the unique space
* @param high is the HighFunction containing the variable
* @return the dynamic VariableStorage
*/
public static VariableStorage buildDynamicStorage(Varnode vn, HighFunction high) {
DynamicHash dynamicHash = new DynamicHash(vn, high);
Program program = high.getFunction().getProgram();
long ourHash = dynamicHash.getHash();
try {
return new VariableStorage(program, AddressSpace.HASH_SPACE.getAddress(ourHash),
vn.getSize());
}
catch (InvalidInputException e) {
throw new AssertException("Unexpected exception", e);
}
}
} }

View file

@ -33,19 +33,20 @@ public class EquateSymbol extends DynamicSymbol {
private long value; // Value of the equate private long value; // Value of the equate
private int convert; // Non-zero if this is a conversion equate private int convert; // Non-zero if this is a conversion equate
public EquateSymbol() { public EquateSymbol(HighFunction func) {
super(func);
} }
public EquateSymbol(long uniqueId, String nm, long val, HighFunction func, Address addr, public EquateSymbol(long uniqueId, String nm, long val, HighFunction func, Address addr,
long hash, int format) { long hash) {
super(uniqueId, nm, DataType.DEFAULT, 1, func, addr, hash, format); super(uniqueId, nm, DataType.DEFAULT, 1, func, addr, hash);
value = val; value = val;
convert = FORMAT_DEFAULT; convert = FORMAT_DEFAULT;
} }
public EquateSymbol(long uniqueId, int conv, long val, HighFunction func, Address addr, public EquateSymbol(long uniqueId, int conv, long val, HighFunction func, Address addr,
long hash, int format) { long hash) {
super(uniqueId, "", DataType.DEFAULT, 1, func, addr, hash, format); super(uniqueId, "", DataType.DEFAULT, 1, func, addr, hash);
value = val; value = val;
convert = conv; convert = conv;
} }
@ -53,9 +54,9 @@ public class EquateSymbol extends DynamicSymbol {
public long getValue() { return value; } public long getValue() { return value; }
@Override @Override
public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException { public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement symel = parser.start("equatesymbol"); XmlElement symel = parser.start("equatesymbol");
restoreSymbolXML(symel, func); restoreSymbolXML(symel);
type = DataType.DEFAULT; type = DataType.DEFAULT;
size = 1; size = 1;
convert = FORMAT_DEFAULT; convert = FORMAT_DEFAULT;
@ -84,15 +85,9 @@ public class EquateSymbol extends DynamicSymbol {
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());
} }
restoreEntryXML(parser);
while(parser.peek().isStart()) { while(parser.peek().isStart()) {
long hash = 0; parser.discardSubTree();
int format = 0;
XmlElement addrel = parser.start("hash");
hash = SpecXmlUtils.decodeLong(addrel.getAttribute("val"));
format = SpecXmlUtils.decodeInt(addrel.getAttribute("format"));
parser.end(addrel);
Address addr = parseRangeList(parser);
addReference(addr,hash,format);
} }
} }

View file

@ -210,9 +210,9 @@ public class FunctionPrototype {
* @return the i'th HighParam to this function prototype or null * @return the i'th HighParam to this function prototype or null
* if this prototype is not backed by a LocalSymbolMap * if this prototype is not backed by a LocalSymbolMap
*/ */
public HighParam getParam(int i) { public HighSymbol getParam(int i) {
if (localsyms != null) { if (localsyms != null) {
return localsyms.getParam(i); return localsyms.getParamSymbol(i);
} }
return null; return null;
} }

View file

@ -99,6 +99,10 @@ public class GlobalSymbolMap {
* @return the new HighSymbol or null * @return the new HighSymbol or null
*/ */
public HighCodeSymbol newSymbol(long id, Address addr, DataType dataType, int sz) { public HighCodeSymbol newSymbol(long id, Address addr, DataType dataType, int sz) {
if (dataType == null) {
dataType = DataType.DEFAULT;
sz = 1;
}
HighCodeSymbol symbol = new HighCodeSymbol(id, addr, dataType, sz, func); HighCodeSymbol symbol = new HighCodeSymbol(id, addr, dataType, sz, func);
insertSymbol(symbol, addr); insertSymbol(symbol, addr);
return symbol; return symbol;

View file

@ -17,9 +17,13 @@ package ghidra.program.model.pcode;
import ghidra.program.database.symbol.CodeSymbol; import ghidra.program.database.symbol.CodeSymbol;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Data; import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolUtilities; import ghidra.program.model.symbol.SymbolUtilities;
import ghidra.util.exception.InvalidInputException;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser; import ghidra.xml.XmlPullParser;
/** /**
@ -29,6 +33,7 @@ public class HighCodeSymbol extends HighSymbol {
private CodeSymbol symbol; private CodeSymbol symbol;
private Data data; private Data data;
private VariableStorage storage;
public HighCodeSymbol(CodeSymbol sym, DataType dataType, int sz, HighFunction func) { public HighCodeSymbol(CodeSymbol sym, DataType dataType, int sz, HighFunction func) {
super(sym.getID(), sym.getName(), dataType, sz, null, func); super(sym.getID(), sym.getName(), dataType, sz, null, func);
@ -43,6 +48,11 @@ public class HighCodeSymbol extends HighSymbol {
data = func.getFunction().getProgram().getListing().getDataAt(addr); data = func.getFunction().getProgram().getListing().getDataAt(addr);
} }
@Override
public boolean isGlobal() {
return true;
}
public CodeSymbol getCodeSymbol() { public CodeSymbol getCodeSymbol() {
return symbol; return symbol;
} }
@ -57,6 +67,26 @@ public class HighCodeSymbol extends HighSymbol {
return data; return data;
} }
@Override
public VariableStorage getStorage() {
if (storage == null) {
Data dataObj = getData();
if (dataObj != null) {
try {
storage = new VariableStorage(function.getFunction().getProgram(),
dataObj.getAddress(), dataObj.getLength());
}
catch (InvalidInputException e) {
storage = VariableStorage.UNASSIGNED_STORAGE;
}
}
else {
storage = VariableStorage.UNASSIGNED_STORAGE;
}
}
return storage;
}
@Override @Override
public String buildXML() { public String buildXML() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
@ -64,8 +94,37 @@ public class HighCodeSymbol extends HighSymbol {
} }
@Override @Override
public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException { public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
// TODO Auto-generated method stub XmlElement symel = parser.start("symbol");
restoreSymbolXML(symel);
Symbol tmpSymbol = function.getFunction().getProgram().getSymbolTable().getSymbol(getId());
if (tmpSymbol instanceof CodeSymbol) {
symbol = (CodeSymbol) tmpSymbol;
}
type = function.getDataTypeManager().readXMLDataType(parser);
size = type.getLength();
parser.end(symel);
restoreEntryXML(parser);
while (parser.peek().isStart()) {
parser.discardSubTree();
}
}
@Override
protected void restoreEntryXML(XmlPullParser parser) throws PcodeXMLException {
AddressFactory addrFactory = function.getAddressFactory();
XmlElement addrel = parser.start("addr");
int sz = type.getLength();
if (sz == 0) {
throw new PcodeXMLException("Invalid symbol 0-sized data-type: " + type.getName());
}
Address varAddr = Varnode.readXMLAddress(addrel, addrFactory);
parser.end(addrel);
pcaddr = parseRangeList(parser);
if (symbol == null) {
Program program = function.getFunction().getProgram();
data = program.getListing().getDataAt(varAddr);
}
} }
} }

View file

@ -18,7 +18,11 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.AbstractIntegerDataType; import ghidra.program.model.data.AbstractIntegerDataType;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Program;
import ghidra.program.model.scalar.Scalar; import ghidra.program.model.scalar.Scalar;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
* *
@ -30,6 +34,14 @@ public class HighConstant extends HighVariable {
private DynamicSymbol symbol; private DynamicSymbol symbol;
private Address pcaddr; // null or Address of PcodeOp which defines the representative private Address pcaddr; // null or Address of PcodeOp which defines the representative
/**
* Constructor for use with restoreXml
* @param func is the HighFunction this constant belongs to
*/
public HighConstant(HighFunction func) {
super(func);
}
/** /**
* Construct a constant NOT associated with a symbol * Construct a constant NOT associated with a symbol
* @param name name of variable * @param name name of variable
@ -43,19 +55,6 @@ public class HighConstant extends HighVariable {
pcaddr = pc; pcaddr = pc;
} }
/**
* Construct constant associated with a dynamic symbol
* @param name name of variable
* @param type data type of variable
* @param vn constant varnode
* @param pc code unit address where constant is used
* @param sym associated dynamic symbol
*/
public HighConstant(String name, DataType type, Varnode vn, Address pc, DynamicSymbol sym) {
this(name, type, vn, pc, sym.getHighFunction());
symbol = sym;
}
@Override @Override
public HighSymbol getSymbol() { public HighSymbol getSymbol() {
return symbol; return symbol;
@ -88,4 +87,36 @@ public class HighConstant extends HighVariable {
return new Scalar(getSize() * 8, value, signed); return new Scalar(getSize() * 8, value, signed);
} }
@Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("high");
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
restoreInstances(parser, el);
pcaddr = function.getPCAddress(represent);
if (symref != 0) {
HighSymbol sym = function.getLocalSymbolMap().getSymbol(symref);
if (sym == null) {
sym = function.getGlobalSymbolMap().getSymbol(symref);
}
if (sym instanceof DynamicSymbol) {
symbol = (DynamicSymbol) sym;
name = sym.getName();
sym.setHighVariable(this);
}
else if (sym == null) {
GlobalSymbolMap globalMap = function.getGlobalSymbolMap();
Program program = function.getFunction().getProgram();
sym = globalMap.populateSymbol(symref, null, -1);
if (sym == null) {
PcodeOp op = ((VarnodeAST) represent).getLoneDescend();
Address addr = HighFunctionDBUtil.getSpacebaseReferenceAddress(program, op);
if (addr != null) {
sym = globalMap.newSymbol(symref, addr, DataType.DEFAULT, 1);
}
}
}
}
parser.end(el);
}
} }

View file

@ -24,7 +24,6 @@ import org.xml.sax.*;
import ghidra.program.database.symbol.CodeSymbol; import ghidra.program.database.symbol.CodeSymbol;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOutOfBoundsException; import ghidra.program.model.address.AddressOutOfBoundsException;
import ghidra.program.model.data.DataType;
import ghidra.program.model.lang.CompilerSpec; import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Language;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
@ -209,41 +208,29 @@ public class HighFunction extends PcodeSyntaxTree {
} }
private void readHighXML(XmlPullParser parser) throws PcodeXMLException { private void readHighXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("high"); XmlElement el = parser.peek();
String classstring = el.getAttribute("class"); String classstring = el.getAttribute("class");
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref")); HighVariable var;
int repref = SpecXmlUtils.decodeInt(el.getAttribute("repref")); switch (classstring.charAt(0)) {
Varnode rep = getRef(repref); case 'o':
if (rep == null) { var = new HighOther(this);
throw new PcodeXMLException("Undefined varnode reference"); break;
case 'g':
var = new HighGlobal(this);
break;
case 'l':
var = new HighLocal(this);
break;
case 'p':
var = new HighParam(this);
break;
case 'c':
var = new HighConstant(this);
break;
default:
throw new PcodeXMLException("Unknown HighVariable class string: " + classstring);
} }
var.restoreXml(parser);
DataType type = null;
ArrayList<Varnode> vnlist = new ArrayList<Varnode>();
int sz = -1;
if (parser.peek().isStart()) {
type = getDataTypeManager().readXMLDataType(parser);
}
if (type == null) {
throw new PcodeXMLException("Missing <type> for HighVariable");
}
// TODO: I'm not sure the decompiler's type size is preserved
// by the conversion to a GHIDRA type
sz = type.getLength();
while (parser.peek().isStart()) {
Varnode vn = Varnode.readXML(parser, this);
vnlist.add(vn);
}
Varnode[] vnarray = new Varnode[vnlist.size()];
vnlist.toArray(vnarray);
// VARDO: does rep varnode size differ from type length ?
newHigh(symref, type, sz, vnarray, rep, classstring);
parser.end(el);
} }
private void readHighlistXML(XmlPullParser parser) throws PcodeXMLException { private void readHighlistXML(XmlPullParser parser) throws PcodeXMLException {
@ -329,97 +316,7 @@ public class HighFunction extends PcodeSyntaxTree {
parser.end(el); parser.end(el);
} }
private HighVariable newHigh(long symref, DataType tp, int sz, Varnode[] inst, Varnode rep, protected Address getPCAddress(Varnode rep) {
String classstring) throws PcodeXMLException {
HighVariable var = null;
if (classstring.equals("local")) {
HighSymbol sym = null;
if (symref != 0) {
sym = localSymbols.getSymbol(symref);
}
if (sym != null) {
var = sym.getHighVariable();
}
if (var == null) {
if (sym instanceof DynamicSymbol) {
// establish HighLocal for DynamicSymbol
var = new HighLocal(tp, rep, inst, sym.getPCAddress(), sym);
sym.setHighVariable(var);
}
else {
// The variable may be a partial, in which case
// we treat it as special
var = new HighOther(tp, rep, inst, getPCAddress(rep), this);
}
}
}
else if (classstring.equals("constant")) {
HighSymbol sym = null;
if (symref != 0) {
sym = localSymbols.getSymbol(symref);
if (sym == null) {
sym = globalSymbols.getSymbol(symref);
}
if (sym instanceof DynamicSymbol) {
var = sym.getHighVariable();
var = new HighConstant(sym.getName(), tp, rep, getPCAddress(rep),
(DynamicSymbol) sym);
sym.setHighVariable(var);
}
else if (sym == null) {
sym = globalSymbols.populateSymbol(symref, null, -1);
if (sym == null) {
PcodeOp op = ((VarnodeAST) rep).getLoneDescend();
Address addr =
HighFunctionDBUtil.getSpacebaseReferenceAddress(func.getProgram(), op);
if (addr != null) {
sym = globalSymbols.newSymbol(symref, addr, DataType.DEFAULT, 1);
}
}
}
}
if (var == null) {
var = new HighConstant(null, tp, rep, getPCAddress(rep), this);
}
}
else if (classstring.equals("global")) {
HighCodeSymbol sym = null;
if (symref != 0) {
sym = globalSymbols.getSymbol(symref);
}
if (sym == null) {
sym = globalSymbols.populateSymbol(symref, tp, sz);
if (sym == null) {
sym = globalSymbols.newSymbol(symref, rep.getAddress(), tp, sz);
if (sym == null) {
throw new PcodeXMLException(
"Bad global storage: " + rep.getAddress().toString());
}
}
}
var = new HighGlobal(sym, rep, inst);
sym.setHighVariable(var);
}
else if (classstring.equals("other")) {
// TODO: How do these compare with local ??
var = new HighOther(tp, rep, inst, getPCAddress(rep), this);
}
else {
throw new PcodeXMLException("Bad class string: " + classstring);
}
if (rep.getSize() == var.getSize()) {
var.attachInstances(inst, rep);
}
else { // Make sure varnodes are linked to HighVariable even if not formal instances, why do we do this???
for (Varnode element : inst) {
((VarnodeAST) element).setHigh(var);
}
}
var.setHighOnInstances();
return var;
}
private Address getPCAddress(Varnode rep) {
Address pcaddr = null; Address pcaddr = null;
if (!rep.isAddrTied()) { if (!rep.isAddrTied()) {
pcaddr = rep.getPCAddress(); pcaddr = rep.getPCAddress();

View file

@ -97,7 +97,7 @@ public class HighFunctionDBUtil {
List<Parameter> params = new ArrayList<Parameter>(); List<Parameter> params = new ArrayList<Parameter>();
int paramCnt = symbolMap.getNumParams(); int paramCnt = symbolMap.getNumParams();
for (int i = 0; i < paramCnt; ++i) { for (int i = 0; i < paramCnt; ++i) {
HighParam param = symbolMap.getParam(i); HighSymbol param = symbolMap.getParamSymbol(i);
String name = param.getName(); String name = param.getName();
DataType dataType; DataType dataType;
if (useDataTypes) { if (useDataTypes) {
@ -201,23 +201,20 @@ public class HighFunctionDBUtil {
Iterator<HighSymbol> iter = highFunction.getLocalSymbolMap().getSymbols(); Iterator<HighSymbol> iter = highFunction.getLocalSymbolMap().getSymbols();
while (iter.hasNext()) { while (iter.hasNext()) {
HighSymbol sym = iter.next(); HighSymbol sym = iter.next();
HighVariable high = sym.getHighVariable(); if (sym.isParameter() || sym.isGlobal()) {
if ((high instanceof HighParam) || !(high instanceof HighLocal)) {
continue; continue;
} }
String name = sym.getName();
HighLocal local = (HighLocal) high;
String name = local.getName();
try { try {
Variable var = clearConflictingLocalVariables(local); Variable var = clearConflictingLocalVariables(sym);
if (var == null) { if (var == null) {
var = createLocalVariable(local, null, null, source); var = createLocalVariable(sym, null, null, source);
if (name != null) { if (name != null) {
var.setName(name, source); var.setName(name, source);
} }
} }
else { else {
var.setDataType(local.getDataType(), local.getStorage(), false, source); var.setDataType(sym.getDataType(), sym.getStorage(), false, source);
var.setName(name, source); var.setName(name, source);
} }
} }
@ -229,28 +226,29 @@ public class HighFunctionDBUtil {
} }
/** /**
* Create a local DB variable with a default name * Create a local DB variable with a default name. Storage and data-type for the variable
* @param local * can be provided explicitly, or they can be taken from a decompiler symbol.
* @param dt data type or null to use local data type defined by local high variable * @param symbol is the decompiler symbol
* @param storage storage or null to use storage defined by local high variable * @param dt is the given data-type or null (to use the symbol's data-type)
* @param source * @param storage is the given storage or null (to use the symbol's storage)
* @return * @param source is the desired SourceType of the new variable
* @throws InvalidInputException * @return the new local variable
* @throws DuplicateNameException * @throws InvalidInputException is a valid variable can't be created
*/ */
private static Variable createLocalVariable(HighLocal local, DataType dt, private static Variable createLocalVariable(HighSymbol symbol, DataType dt,
VariableStorage storage, SourceType source) throws InvalidInputException { VariableStorage storage, SourceType source) throws InvalidInputException {
Function function = local.getHighFunction().getFunction(); Function function = symbol.getHighFunction().getFunction();
Program program = function.getProgram(); Program program = function.getProgram();
if (storage == null || storage.isUniqueStorage()) { if (storage == null || storage.isUniqueStorage()) {
storage = local.getStorage(); storage = symbol.getStorage();
} }
if (dt == null) { if (dt == null) {
dt = local.getDataType(); dt = symbol.getDataType();
} }
Variable var = new LocalVariableImpl(null, local.getFirstUseOffset(), dt, storage, program); Variable var =
new LocalVariableImpl(null, symbol.getFirstUseOffset(), dt, storage, program);
try { try {
var = function.addLocalVariable(var, SourceType.ANALYSIS); var = function.addLocalVariable(var, source);
} }
catch (DuplicateNameException e) { catch (DuplicateNameException e) {
throw new AssertException("Unexpected exception with default name", e); throw new AssertException("Unexpected exception with default name", e);
@ -258,7 +256,7 @@ public class HighFunctionDBUtil {
Register reg = var.getRegister(); Register reg = var.getRegister();
if (reg != null) { if (reg != null) {
program.getReferenceManager().addRegisterReference(local.getPCAddress(), -1, reg, program.getReferenceManager().addRegisterReference(symbol.getPCAddress(), -1, reg,
RefType.WRITE, source); RefType.WRITE, source);
} }
@ -282,13 +280,15 @@ public class HighFunctionDBUtil {
long hash = var.getFirstStorageVarnode().getOffset(); long hash = var.getFirstStorageVarnode().getOffset();
Iterator<HighSymbol> symbols = highFunction.getLocalSymbolMap().getSymbols(); Iterator<HighSymbol> symbols = highFunction.getLocalSymbolMap().getSymbols();
while (symbols.hasNext()) { while (symbols.hasNext()) {
HighVariable high = symbols.next().getHighVariable(); HighSymbol symbol = symbols.next();
if (!(high instanceof HighLocal)) { if (!(symbol instanceof DynamicSymbol)) {
continue; continue;
} }
// Note: assumes there is only one hash method used for unique locals // Note: assumes there is only one hash method used for unique locals
if (((HighLocal) high).buildDynamicHash() == hash) { if (((DynamicSymbol) symbol).getHash() == hash) {
return true; if (symbol.getHighVariable() != null) {
return true; // Hash successfully attached to a variable
}
} }
} }
return false; return false;
@ -301,25 +301,22 @@ public class HighFunctionDBUtil {
* exists within the function at the same first-use-offset. * exists within the function at the same first-use-offset.
* @return existing variable with identical storage and first-use offset or null * @return existing variable with identical storage and first-use offset or null
*/ */
private static Variable clearConflictingLocalVariables(HighLocal local) { private static Variable clearConflictingLocalVariables(HighSymbol local) {
if (local instanceof HighParam) { if (local instanceof MappedSymbol) {
if (((MappedSymbol) local).getSlot() >= 0) { // Don't clear parameters
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
}
HighFunction highFunction = local.getHighFunction(); HighFunction highFunction = local.getHighFunction();
Function func = highFunction.getFunction(); Function func = highFunction.getFunction();
HighSymbol symbol = local.getSymbol();
VariableStorage storage = local.getStorage(); VariableStorage storage = local.getStorage();
int firstUseOffset = local.getFirstUseOffset(); int firstUseOffset = local.getFirstUseOffset();
if (symbol instanceof DynamicSymbol || storage.isUniqueStorage()) { if (local instanceof DynamicSymbol) {
if (!(symbol instanceof DynamicSymbol)) { DynamicSymbol dynamicSym = (DynamicSymbol) local;
return null;
}
DynamicSymbol dynamicSym = (DynamicSymbol) symbol;
for (Variable ul : func.getLocalVariables(VariableFilter.UNIQUE_VARIABLE_FILTER)) { for (Variable ul : func.getLocalVariables(VariableFilter.UNIQUE_VARIABLE_FILTER)) {
// Note: assumes there is only one hash method used for unique locals // Note: assumes there is only one hash method used for unique locals
if (ul.getFirstStorageVarnode().getOffset() == dynamicSym.getHash()) { if (ul.getFirstStorageVarnode().getOffset() == dynamicSym.getHash()) {
@ -352,15 +349,15 @@ public class HighFunctionDBUtil {
} }
/** /**
* Get database parameter which corresponds to HighParam, where we anticipate that * Get database parameter which corresponds to the given symbol, where we anticipate that
* the parameter will be modified to match the HighParam. The entire prototype is * the parameter will be modified to match the symbol. The entire prototype is
* committed to the database if necessary. An exception is thrown if a modifiable parameter * committed to the database if necessary. An exception is thrown if a modifiable parameter
* can't be found/created. * can't be found/created.
* @param param is the HighParam describing the desired function parameter * @param param is the HighSymbol describing the desired function parameter
* @return the matching parameter that can be modified * @return the matching parameter that can be modified
* @throws InvalidInputException if the desired parameter cannot be modified * @throws InvalidInputException if the desired parameter cannot be modified
*/ */
private static Parameter getDatabaseParameter(HighParam param) throws InvalidInputException { private static Parameter getDatabaseParameter(MappedSymbol param) throws InvalidInputException {
HighFunction highFunction = param.getHighFunction(); HighFunction highFunction = param.getHighFunction();
Function function = highFunction.getFunction(); Function function = highFunction.getFunction();
@ -392,10 +389,9 @@ public class HighFunctionDBUtil {
} }
/** /**
* Retype the specified variable in the database. All parameters may be flushed * Rename and/or retype the specified variable in the database. All parameters may be flushed
* to the database if typed parameter inconsistency detected. * to the database if typed parameter inconsistency detected.
* Only variable types HighParam, HighLocal and HighGlobal are supported. * @param variable is the symbol being updated
* @param variable
* @param name new variable name or null to use retain current variable name * @param name new variable name or null to use retain current variable name
* @param dataType newly assigned data type or null to retain current variable datatype. * @param dataType newly assigned data type or null to retain current variable datatype.
* Only a fixed-length data type may be specified. If size varies from the current size, * Only a fixed-length data type may be specified. If size varies from the current size,
@ -407,7 +403,7 @@ public class HighFunctionDBUtil {
* variable/label within the function's namespace * variable/label within the function's namespace
* @throws UnsupportedOperationException if unsupported variable type is specified * @throws UnsupportedOperationException if unsupported variable type is specified
*/ */
public static void updateDBVariable(HighVariable variable, String name, DataType dataType, public static void updateDBVariable(HighSymbol variable, String name, DataType dataType,
SourceType source) throws InvalidInputException, DuplicateNameException { SourceType source) throws InvalidInputException, DuplicateNameException {
HighFunction highFunction = variable.getHighFunction(); HighFunction highFunction = variable.getHighFunction();
@ -427,10 +423,11 @@ public class HighFunctionDBUtil {
boolean isRename = name != null; boolean isRename = name != null;
if (variable instanceof HighParam) { if (variable.isParameter()) {
HighParam param = (HighParam) variable; MappedSymbol mappedSymbol = (MappedSymbol) variable;
Parameter dbParam = getDatabaseParameter(param);
VariableStorage storage = param.getStorage(); Parameter dbParam = getDatabaseParameter(mappedSymbol);
VariableStorage storage = mappedSymbol.getStorage();
if (dataType != null) { if (dataType != null) {
if (resized && function.hasCustomVariableStorage()) { if (resized && function.hasCustomVariableStorage()) {
VariableStorage newStorage = VariableStorage newStorage =
@ -445,12 +442,20 @@ public class HighFunctionDBUtil {
dbParam.setName(name, source); dbParam.setName(name, source);
} }
} }
else if (variable instanceof HighLocal) { else if (!variable.isGlobal()) {
HighLocal local = (HighLocal) variable; Variable var;
VariableStorage storage = local.getStorage(); VariableStorage storage;
HighVariable tmpHigh = variable.getHighVariable();
if (tmpHigh != null && tmpHigh.getRepresentative().isUnique()) {
storage =
DynamicSymbol.buildDynamicStorage(tmpHigh.getRepresentative(), highFunction);
var = null;
}
else {
storage = variable.getStorage();
var = clearConflictingLocalVariables(variable);
}
boolean usesHashStorage = storage.isHashStorage(); boolean usesHashStorage = storage.isHashStorage();
Variable var = clearConflictingLocalVariables(local);
if (dataType == null) { if (dataType == null) {
if (var != null) { if (var != null) {
dataType = var.getDataType(); // Use preexisting datatype if it fits in desired storage dataType = var.getDataType(); // Use preexisting datatype if it fits in desired storage
@ -463,21 +468,21 @@ public class HighFunctionDBUtil {
if (resized) { if (resized) {
if (usesHashStorage) { if (usesHashStorage) {
throw new InvalidInputException( throw new InvalidInputException(
"Variable size (" + local.getSize() + ") may not be changed: type '" + "Variable size (" + variable.getSize() + ") may not be changed: type '" +
dataType.getName() + "' length is " + dataType.getLength()); dataType.getName() + "' length is " + dataType.getLength());
} }
storage = VariableUtilities.resizeStorage(storage, dataType, true, function); storage = VariableUtilities.resizeStorage(storage, dataType, true, function);
} }
if (var == null) { if (var == null) {
var = createLocalVariable(local, dataType, storage, source); var = createLocalVariable(variable, dataType, storage, source);
} }
else { else {
// fixup reused variable // fixup reused variable
var.setDataType(dataType, storage, true, source); var.setDataType(dataType, storage, true, source);
if (name == null) {
name = local.getName(); // must update name if not specified
} }
if (name == null) {
name = variable.getName(); // must update name if not specified
} }
try { try {
// must set/correct name // must set/correct name
@ -499,7 +504,7 @@ public class HighFunctionDBUtil {
} }
} }
} }
else if (variable instanceof HighGlobal) { else { // A global symbol
VariableStorage storage = variable.getStorage(); VariableStorage storage = variable.getStorage();
if (!storage.isMemoryStorage()) { if (!storage.isMemoryStorage()) {
@ -507,21 +512,20 @@ public class HighFunctionDBUtil {
"Database supports global memory variables only"); "Database supports global memory variables only");
} }
HighGlobal global = (HighGlobal) variable;
if (name == null) { if (name == null) {
name = global.getName(); name = variable.getName();
if (name != null && SymbolUtilities.isDynamicSymbolPattern(name, true)) { if (name != null && SymbolUtilities.isDynamicSymbolPattern(name, true)) {
name = null; name = null;
} }
} }
if (dataType != null) { if (dataType != null) {
setGlobalDataType(global, dataType); setGlobalDataType(variable, dataType);
} }
if (name != null) { if (name != null) {
try { try {
setGlobalName((HighGlobal) variable, variable.getName(), source); setGlobalName(variable, variable.getName(), source);
} }
catch (DuplicateNameException e) { catch (DuplicateNameException e) {
if (isRename) { if (isRename) {
@ -530,13 +534,9 @@ public class HighFunctionDBUtil {
} }
} }
} }
else {
throw new UnsupportedOperationException(
"Database support not provided for " + variable.getClass().getSimpleName());
}
} }
private static void setGlobalName(HighGlobal global, String name, SourceType source) private static void setGlobalName(HighSymbol global, String name, SourceType source)
throws DuplicateNameException, InvalidInputException { throws DuplicateNameException, InvalidInputException {
Program program = global.getHighFunction().getFunction().getProgram(); Program program = global.getHighFunction().getFunction().getProgram();
VariableStorage storage = global.getStorage(); VariableStorage storage = global.getStorage();
@ -554,7 +554,7 @@ public class HighFunctionDBUtil {
} }
} }
private static Data setGlobalDataType(HighGlobal global, DataType dt) private static Data setGlobalDataType(HighSymbol global, DataType dt)
throws InvalidInputException { throws InvalidInputException {
Program program = global.getHighFunction().getFunction().getProgram(); Program program = global.getHighFunction().getFunction().getProgram();
VariableStorage storage = global.getStorage(); VariableStorage storage = global.getStorage();

View file

@ -15,6 +15,12 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
* *
* *
@ -24,6 +30,14 @@ public class HighGlobal extends HighVariable {
private HighCodeSymbol symbol; private HighCodeSymbol symbol;
/**
* Constructor for use with restoreXml
* @param high is the HighFunction this global is accessed by
*/
public HighGlobal(HighFunction high) {
super(high);
}
public HighGlobal(HighCodeSymbol sym, Varnode vn, Varnode[] inst) { public HighGlobal(HighCodeSymbol sym, Varnode vn, Varnode[] inst) {
super(sym.getName(), sym.getDataType(), vn, inst, sym.getHighFunction()); super(sym.getName(), sym.getDataType(), vn, inst, sym.getHighFunction());
symbol = sym; symbol = sym;
@ -33,4 +47,50 @@ public class HighGlobal extends HighVariable {
public HighSymbol getSymbol() { public HighSymbol getSymbol() {
return symbol; return symbol;
} }
@Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("high");
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
String attrString = el.getAttribute("offset");
offset = -1;
if (attrString != null) {
offset = SpecXmlUtils.decodeInt(attrString);
}
restoreInstances(parser, el);
if (symref == 0) {
throw new PcodeXMLException("Missing symref attribute in <high> tag");
}
symbol = function.getGlobalSymbolMap().getSymbol(symref);
if (symbol == null) { // If we don't already have symbol, synthesize it
DataType symbolType;
int symbolSize;
if (offset < 0) { // Variable type and size matches symbol
symbolType = type;
symbolSize = getSize();
}
else {
symbolType = null;
symbolSize = -1;
}
GlobalSymbolMap globalMap = function.getGlobalSymbolMap();
symbol = globalMap.populateSymbol(symref, symbolType, symbolSize);
if (symbol == null) {
Address addr = represent.getAddress();
if (offset > 0) {
addr = addr.subtract(offset);
}
symbol = globalMap.newSymbol(symref, addr, symbolType, symbolSize);
if (symbol == null) {
throw new PcodeXMLException("Bad global storage: " + addr.toString());
}
}
}
if (offset < 0) {
name = symbol.getName();
}
symbol.setHighVariable(this);
parser.end(el);
}
} }

View file

@ -16,18 +16,23 @@
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Program; import ghidra.util.xml.SpecXmlUtils;
import ghidra.program.model.listing.VariableStorage; import ghidra.xml.XmlElement;
import ghidra.util.exception.AssertException; import ghidra.xml.XmlPullParser;
import ghidra.util.exception.InvalidInputException;
public class HighLocal extends HighVariable { public class HighLocal extends HighVariable {
private Address pcaddr; // null or Address of PcodeOp which defines the representative private Address pcaddr; // null or Address of PcodeOp which defines the representative
private HighSymbol symbol; private HighSymbol symbol;
private long hash = 0; // 60-bit hash value, 0 indicates not-yet-computed or not-applicable
/**
* Constructor for use with restoreXml
* @param high is the HighFunction containing this local variable
*/
public HighLocal(HighFunction high) {
super(high);
}
public HighLocal(DataType type, Varnode vn, Varnode[] inst, Address pc, HighSymbol sym) { public HighLocal(DataType type, Varnode vn, Varnode[] inst, Address pc, HighSymbol sym) {
super(sym.getName(), type, vn, inst, sym.getHighFunction()); super(sym.getName(), type, vn, inst, sym.getHighFunction());
@ -47,51 +52,30 @@ public class HighLocal extends HighVariable {
return pcaddr; return pcaddr;
} }
protected int getFirstUseOffset() {
if (pcaddr == null || getRepresentative().getAddress().isStackAddress()) {
return 0;
}
return (int) pcaddr.subtract(getHighFunction().getFunction().getEntryPoint());
}
@Override @Override
public VariableStorage getStorage() { public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("high");
Program program = getHighFunction().getFunction().getProgram(); long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
Varnode represent = getRepresentative(); offset = -1;
String attrString = el.getAttribute("offset");
if (symbol instanceof DynamicSymbol || represent.isUnique()) { if (attrString != null) {
long ourHash = buildDynamicHash(); offset = SpecXmlUtils.decodeInt(attrString);
try {
return new VariableStorage(program, AddressSpace.HASH_SPACE.getAddress(ourHash),
represent.getSize());
} }
catch (InvalidInputException e) { restoreInstances(parser, el);
throw new AssertException("Unexpected exception", e); symbol = function.getLocalSymbolMap().getSymbol(symref);
if (symbol == null) {
throw new PcodeXMLException("HighLocal is missing symbol");
} }
if (offset < 0) {
name = symbol.getName();
} }
else {
if (symbol instanceof MappedSymbol) { name = "UNNAMED";
return ((MappedSymbol) symbol).getStorage();
} }
return super.getStorage();
}
public long buildDynamicHash() {
if (hash != 0) {
return hash;
}
if (symbol instanceof DynamicSymbol) {
hash = ((DynamicSymbol) symbol).getHash();
pcaddr = symbol.getPCAddress(); pcaddr = symbol.getPCAddress();
} symbol.setHighVariable(this);
else if (getRepresentative().isUnique()) {
DynamicHash dynamicHash = new DynamicHash(getRepresentative(), getHighFunction()); parser.end(el);
hash = dynamicHash.getHash();
pcaddr = dynamicHash.getAddress();
}
return hash;
} }
} }

View file

@ -17,6 +17,9 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
* *
@ -26,8 +29,16 @@ import ghidra.program.model.data.DataType;
*/ */
public class HighOther extends HighVariable { public class HighOther extends HighVariable {
private DynamicSymbol symbol;
private Address pcaddr; // Address of PcodeOp which defines the representative private Address pcaddr; // Address of PcodeOp which defines the representative
private HighSymbol symbol; // Possibly a dynamic global symbol
/**
* Constructor for use with restoreXml
* @param high is the HighFunction containing the variable
*/
public HighOther(HighFunction high) {
super(high);
}
/** /**
* Construct a unique high NOT associated with a symbol * Construct a unique high NOT associated with a symbol
@ -42,14 +53,6 @@ public class HighOther extends HighVariable {
pcaddr = pc; pcaddr = pc;
} }
/**
* @return associated dynamic symbol or null
*/
@Override
public DynamicSymbol getSymbol() {
return symbol;
}
/** /**
* @return instruction address the variable comes into scope within the function * @return instruction address the variable comes into scope within the function
*/ */
@ -57,4 +60,31 @@ public class HighOther extends HighVariable {
return pcaddr; return pcaddr;
} }
@Override
public HighSymbol getSymbol() {
return symbol;
}
@Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("high");
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
offset = -1;
String attrString = el.getAttribute("offset");
restoreInstances(parser, el);
name = "UNNAMED";
pcaddr = function.getPCAddress(represent);
if (symref != 0) {
offset = -1;
if (attrString != null) {
offset = SpecXmlUtils.decodeInt(attrString);
}
symbol = function.getLocalSymbolMap().getSymbol(symref);
if (symbol != null && offset < 0) {
name = symbol.getName();
}
}
parser.end(el);
}
} }

View file

@ -17,6 +17,7 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.xml.XmlPullParser;
/** /**
* *
@ -26,6 +27,14 @@ import ghidra.program.model.data.DataType;
public class HighParam extends HighLocal { public class HighParam extends HighLocal {
private int slot; private int slot;
/**
* Constructor for use with restoreXml
* @param high is the HighFunction containing this parameter
*/
public HighParam(HighFunction high) {
super(high);
}
/** /**
* @param tp data type of variable * @param tp data type of variable
* @param rep is the representative input Varnode * @param rep is the representative input Varnode
@ -46,8 +55,13 @@ public class HighParam extends HighLocal {
} }
@Override @Override
protected int getFirstUseOffset() { public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
return 0; super.restoreXml(parser);
slot = 0;
HighSymbol sym = getSymbol();
if (sym instanceof MappedSymbol) {
slot = ((MappedSymbol) sym).getSlot();
}
} }
} }

View file

@ -18,6 +18,7 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.VariableStorage;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement; import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser; import ghidra.xml.XmlPullParser;
@ -37,7 +38,8 @@ public abstract class HighSymbol {
private HighVariable highVariable; private HighVariable highVariable;
public HighSymbol() { // For use with restoreXML public HighSymbol(HighFunction func) { // For use with restoreXML
function = func;
} }
public HighSymbol(long uniqueId, String nm, DataType tp, int sz, Address pc, public HighSymbol(long uniqueId, String nm, DataType tp, int sz, Address pc,
@ -80,6 +82,13 @@ public abstract class HighSymbol {
return pcaddr; return pcaddr;
} }
protected int getFirstUseOffset() {
if (pcaddr == null) {
return 0;
}
return (int) pcaddr.subtract(getHighFunction().getFunction().getEntryPoint());
}
public HighFunction getHighFunction() { public HighFunction getHighFunction() {
return function; return function;
} }
@ -108,13 +117,32 @@ public abstract class HighSymbol {
return readonly; return readonly;
} }
/**
* Is this symbol a parameter for a function
* @return true if this is a parameter
*/
public boolean isParameter() {
return false;
}
/**
* Is this symbol in the global scope or some other global namespace
* @return true if this is global
*/
public boolean isGlobal() {
return false;
}
public abstract VariableStorage getStorage();
public abstract String buildXML(); public abstract String buildXML();
public abstract void restoreXML(XmlPullParser parser, HighFunction func) public abstract void restoreXML(XmlPullParser parser)
throws PcodeXMLException; throws PcodeXMLException;
protected void restoreSymbolXML(XmlElement symel, HighFunction func) throws PcodeXMLException { protected abstract void restoreEntryXML(XmlPullParser parser) throws PcodeXMLException;
function = func;
protected void restoreSymbolXML(XmlElement symel) throws PcodeXMLException {
id = SpecXmlUtils.decodeLong(symel.getAttribute("id")); id = SpecXmlUtils.decodeLong(symel.getAttribute("id"));
if (id == 0) { if (id == 0) {
throw new PcodeXMLException("missing unique symbol id"); throw new PcodeXMLException("missing unique symbol id");

View file

@ -15,11 +15,12 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.util.ArrayList;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Program; import ghidra.util.xml.SpecXmlUtils;
import ghidra.program.model.listing.VariableStorage; import ghidra.xml.XmlElement;
import ghidra.util.Msg; import ghidra.xml.XmlPullParser;
import ghidra.util.exception.InvalidInputException;
/** /**
* *
@ -29,11 +30,20 @@ import ghidra.util.exception.InvalidInputException;
*/ */
public abstract class HighVariable { public abstract class HighVariable {
private String name; protected String name;
private DataType type; protected DataType type;
private Varnode represent; // A representative varnode protected Varnode represent; // A representative varnode
private Varnode[] instances; // Instances of this high-level variable protected Varnode[] instances; // Instances of this high-level variable
private HighFunction function; // associated function protected int offset = -1; // Offset (in bytes) into containing symbol (-1 indicates whole match)
protected HighFunction function; // associated function
/**
* Constructor for use with restoreXml
* @param func is the HighFunction this variable belongs to
*/
protected HighVariable(HighFunction func) {
function = func;
}
protected HighVariable(String nm, DataType tp, Varnode rep, Varnode[] inst, HighFunction func) { protected HighVariable(String nm, DataType tp, Varnode rep, Varnode[] inst, HighFunction func) {
name = nm; name = nm;
@ -104,6 +114,15 @@ public abstract class HighVariable {
*/ */
public abstract HighSymbol getSymbol(); public abstract HighSymbol getSymbol();
/**
* Get the offset of this variable into its containing HighSymbol. If the value
* is -1, this indicates that this HighVariable matches the size and storage of the symbol.
* @return the offset
*/
public int getOffset() {
return offset;
}
/** /**
* Attach an instance or additional location the variable can be found in. * Attach an instance or additional location the variable can be found in.
* *
@ -121,16 +140,46 @@ public abstract class HighVariable {
} }
} }
public VariableStorage getStorage() { /**
Program program = getHighFunction().getFunction().getProgram(); * Restore the data-type and the Varnode instances of this HighVariable.
try { * The "representative" Varnode is also populated.
if (represent != null && (represent.isAddress() || represent.isRegister())) { * @param parser is the XML stream
return new VariableStorage(program, represent); * @param el is the root <high> tag
* @throws PcodeXMLException if the XML is not valid
*/
protected void restoreInstances(XmlPullParser parser, XmlElement el)
throws PcodeXMLException {
int repref = SpecXmlUtils.decodeInt(el.getAttribute("repref"));
Varnode rep = function.getRef(repref);
if (rep == null) {
throw new PcodeXMLException("Undefined varnode reference");
} }
type = null;
ArrayList<Varnode> vnlist = new ArrayList<Varnode>();
if (parser.peek().isStart()) {
type = function.getDataTypeManager().readXMLDataType(parser);
} }
catch (InvalidInputException e) {
Msg.error(this, "Failed to define variable storage: " + this, e); if (type == null) {
throw new PcodeXMLException("Missing <type> for HighVariable");
} }
return VariableStorage.UNASSIGNED_STORAGE;
while (parser.peek().isStart()) {
Varnode vn = Varnode.readXML(parser, function);
vnlist.add(vn);
} }
Varnode[] vnarray = new Varnode[vnlist.size()];
vnlist.toArray(vnarray);
attachInstances(vnarray, rep);
setHighOnInstances();
}
/**
* Restore this HighVariable from a <high> XML tag
* @param parser is the XML stream
* @throws PcodeXMLException if the XML is not valid
*/
public abstract void restoreXml(XmlPullParser parser) throws PcodeXMLException;
} }

View file

@ -101,7 +101,7 @@ public class LocalSymbolMap {
HighSymbol sym; HighSymbol sym;
if (storage.isHashStorage()) { if (storage.isHashStorage()) {
sym = newDynamicSymbol(id, name, dt, sz, storage.getFirstVarnode().getOffset(), sym = newDynamicSymbol(id, name, dt, sz, storage.getFirstVarnode().getOffset(),
defAddr, 0); defAddr);
} }
else { else {
sym = newMappedSymbol(id, name, dt, storage, defAddr, -1); sym = newMappedSymbol(id, name, dt, storage, defAddr, -1);
@ -167,16 +167,16 @@ public class LocalSymbolMap {
String typename = node.getAttribute("type"); String typename = node.getAttribute("type");
HighSymbol res = null; HighSymbol res = null;
if (typename == null) { if (typename == null) {
res = new MappedSymbol(); res = new MappedSymbol(func);
} }
else if (typename.equals("dynamic")) { else if (typename.equals("dynamic")) {
res = new DynamicSymbol(); res = new DynamicSymbol(func);
} }
else if (typename.equals("equate")) { else if (typename.equals("equate")) {
res = new EquateSymbol(); res = new EquateSymbol(func);
} }
res.restoreXML(parser, func); res.restoreXML(parser);
parser.end(node); parser.end(node);
insertSymbol(res); insertSymbol(res);
return res; return res;
@ -225,7 +225,7 @@ public class LocalSymbolMap {
ArrayList<MappedSymbol> parms = new ArrayList<MappedSymbol>(); ArrayList<MappedSymbol> parms = new ArrayList<MappedSymbol>();
while (parser.peek().isStart()) { while (parser.peek().isStart()) {
HighSymbol sym = parseSymbolXML(parser); HighSymbol sym = parseSymbolXML(parser);
if (sym instanceof MappedSymbol && ((MappedSymbol) sym).isParameter()) { if (sym.isParameter()) {
parms.add((MappedSymbol) sym); parms.add((MappedSymbol) sym);
} }
} }
@ -339,11 +339,11 @@ public class LocalSymbolMap {
} }
public DynamicSymbol newDynamicSymbol(long id, 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) { Address pcaddr) {
if (id == 0) { if (id == 0) {
id = getNextId(); id = getNextId();
} }
DynamicSymbol sym = new DynamicSymbol(id, nm, dt, sz, func, pcaddr, hash, format); DynamicSymbol sym = new DynamicSymbol(id, nm, dt, sz, func, pcaddr, hash);
insertSymbol(sym); insertSymbol(sym);
return sym; return sym;
} }
@ -365,23 +365,21 @@ public class LocalSymbolMap {
} }
private void newEquateSymbol(long uniqueId, String nm, long val, long hash, Address addr, 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 return; // New reference to same symbol
return;
} }
if (uniqueId == 0) { if (uniqueId == 0) {
uniqueId = getNextId(); uniqueId = getNextId();
} }
int conv = EquateSymbol.convertName(nm, val); int conv = EquateSymbol.convertName(nm, val);
if (conv < 0) { if (conv < 0) {
eqSymbol = new EquateSymbol(uniqueId, nm, val, func, addr, hash, format); eqSymbol = new EquateSymbol(uniqueId, nm, val, func, addr, hash);
eqSymbol.setNameLock(true); eqSymbol.setNameLock(true);
} }
else { else {
eqSymbol = new EquateSymbol(uniqueId, conv, val, func, addr, hash, format); eqSymbol = new EquateSymbol(uniqueId, conv, val, func, addr, hash);
} }
//Do NOT setTypeLock //Do NOT setTypeLock
constantSymbolMap.put(nm, eqSymbol); constantSymbolMap.put(nm, eqSymbol);
@ -410,7 +408,7 @@ public class LocalSymbolMap {
if (constantSymbolMap == null) { if (constantSymbolMap == null) {
constantSymbolMap = new TreeMap<String, DynamicSymbol>(); constantSymbolMap = new TreeMap<String, DynamicSymbol>();
} }
newEquateSymbol(0, eq.getDisplayName(), eq.getValue(), element, defAddr, 0, newEquateSymbol(0, eq.getDisplayName(), eq.getValue(), element, defAddr,
constantSymbolMap); constantSymbolMap);
} }
} }

View file

@ -30,7 +30,8 @@ public class MappedSymbol extends HighSymbol {
private VariableStorage storage; private VariableStorage storage;
private int slot; // parameter slot, -1 for non-parameter private int slot; // parameter slot, -1 for non-parameter
public MappedSymbol() { // For use with restoreXML public MappedSymbol(HighFunction func) { // For use with restoreXML
super(func);
} }
public MappedSymbol(long uniqueId, String name, DataType dt, VariableStorage store, public MappedSymbol(long uniqueId, String name, DataType dt, VariableStorage store,
@ -44,22 +45,14 @@ public class MappedSymbol extends HighSymbol {
} }
this.storage = store; this.storage = store;
this.slot = slot; this.slot = slot;
Varnode rep = function.createFromStorage(null, storage, dt.getLength());
HighVariable var;
if (slot < 0) {
var = new HighLocal(type, rep, null, pcaddr, this);
}
else {
var = new HighParam(type, rep, pcaddr, slot, this);
}
setHighVariable(var);
var.setHighOnInstances();
} }
@Override
public VariableStorage getStorage() { public VariableStorage getStorage() {
return storage; return storage;
} }
@Override
public boolean isParameter() { public boolean isParameter() {
return slot >= 0; return slot >= 0;
} }
@ -88,9 +81,9 @@ public class MappedSymbol extends HighSymbol {
} }
@Override @Override
public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException { public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement symel = parser.start("symbol"); XmlElement symel = parser.start("symbol");
restoreSymbolXML(symel, func); restoreSymbolXML(symel);
slot = -1; slot = -1;
int cat = -1; int cat = -1;
if (symel.hasAttribute("cat")) { if (symel.hasAttribute("cat")) {
@ -99,7 +92,7 @@ public class MappedSymbol extends HighSymbol {
slot = SpecXmlUtils.decodeInt(symel.getAttribute("index")); slot = SpecXmlUtils.decodeInt(symel.getAttribute("index"));
} }
} }
type = func.getDataTypeManager().readXMLDataType(parser); type = function.getDataTypeManager().readXMLDataType(parser);
parser.end(symel); parser.end(symel);
if (slot >= 0 && name.startsWith("$$undef")) { if (slot >= 0 && name.startsWith("$$undef")) {
@ -107,10 +100,17 @@ public class MappedSymbol extends HighSymbol {
name = "param_" + Integer.toString(slot + 1); name = "param_" + Integer.toString(slot + 1);
} }
restoreEntryXML(parser);
while (parser.peek().isStart()) {
parser.discardSubTree();
}
}
@Override
protected void restoreEntryXML(XmlPullParser parser) throws PcodeXMLException {
Program program = function.getFunction().getProgram(); Program program = function.getFunction().getProgram();
AddressFactory addrFactory = function.getAddressFactory(); AddressFactory addrFactory = function.getAddressFactory();
Address addr = null;
XmlElement addrel = parser.start("addr"); XmlElement addrel = parser.start("addr");
int sz = type.getLength(); int sz = type.getLength();
if (sz == 0) { if (sz == 0) {
@ -123,8 +123,7 @@ public class MappedSymbol extends HighSymbol {
storage = new VariableStorage(program, varAddr, sz); storage = new VariableStorage(program, varAddr, sz);
} }
else { else {
addr = varAddr; storage = function.readXMLVarnodePieces(addrel, varAddr);
storage = func.readXMLVarnodePieces(addrel, varAddr);
} }
} }
catch (InvalidInputException e) { catch (InvalidInputException e) {
@ -134,16 +133,6 @@ public class MappedSymbol extends HighSymbol {
parser.end(addrel); parser.end(addrel);
pcaddr = parseRangeList(parser); pcaddr = parseRangeList(parser);
Varnode rep = function.createFromStorage(addr, storage, sz);
HighVariable var;
if (slot < 0) {
var = new HighLocal(type, rep, null, pcaddr, this);
}
else {
var = new HighParam(type, rep, pcaddr, slot, this);
}
setHighVariable(var);
var.setHighOnInstances();
} }
public static String buildSymbolXML(PcodeDataTypeManager dtmanage, long uniqueId, String nm, public static String buildSymbolXML(PcodeDataTypeManager dtmanage, long uniqueId, String nm,