diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.cc index e0c3febd07..d503de1955 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.cc @@ -393,7 +393,7 @@ void DynamicHash::uniqueHash(const Varnode *root,Funcdata *fd) /// \param addr is the given address /// \param h is the hash /// \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); @@ -423,7 +423,7 @@ Varnode *DynamicHash::findVarnode(Funcdata *fd,const Address &addr,uint8 h) /// \param fd is the function holding the data-flow /// \param addr is the given address /// \param h is the given hash -void DynamicHash::gatherFirstLevelVars(vector &varlist,Funcdata *fd,const Address &addr,uint8 h) +void DynamicHash::gatherFirstLevelVars(vector &varlist,const Funcdata *fd,const Address &addr,uint8 h) { OpCode opc = getOpCodeFromHash(h); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.hh index 805be4067a..d84d0e017f 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.hh @@ -79,11 +79,11 @@ public: 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 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 const Address &getAddress(void) const { return addrresult; } ///< Get the (current) address - static void gatherFirstLevelVars(vector &varlist,Funcdata *fd,const Address &addr,uint8 h); + static void gatherFirstLevelVars(vector &varlist,const Funcdata *fd,const Address &addr,uint8 h); 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 OpCode getOpCodeFromHash(uint8 h); ///< Retrieve the encoded op-code from a hash diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc index 58fa7b7087..665c9bcaf1 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc @@ -607,7 +607,6 @@ void Funcdata::saveVarnodeXml(ostream &s,VarnodeLocSet::const_iterator iter,Varn void Funcdata::saveXmlHigh(ostream &s) const { - int4 j; Varnode *vn; HighVariable *high; @@ -620,32 +619,7 @@ void Funcdata::saveXmlHigh(ostream &s) const high = vn->getHigh(); if (high->isMark()) continue; high->setMark(); - vn = high->getNameRepresentative(); // Get representative varnode - s << "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;jnumInstances();++j) { - s << "getInstance(j)->getCreateIndex()); - s << "/>"; - } - s << ""; + high->saveXml(s); } for(iter=beginLoc();iter!=endLoc();++iter) { vn = *iter; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc index 9a80ec7762..788540fbe7 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_varnode.cc @@ -314,7 +314,15 @@ HighVariable *Funcdata::findHigh(const string &name) const if (symList.empty()) return (HighVariable *)0; Symbol *sym = symList[0]; 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; HighVariable *high; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/variable.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/variable.cc index 42a7cf13da..10242b9e71 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/variable.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/variable.cc @@ -359,6 +359,46 @@ int4 HighVariable::instanceIndex(const Varnode *vn) const 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 << "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;jgetCreateIndex()); + s << "/>"; + } + s << ""; +} + #ifdef MERGEMULTI_DEBUG /// \brief Check that there are no internal Cover intersections within \b this /// diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/variable.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/variable.hh index 07f8f3332e..60883f5eba 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/variable.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/variable.hh @@ -129,6 +129,7 @@ public: 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 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 \ tag #ifdef MERGEMULTI_DEBUG void verifyCover(void) const; #endif diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/cmd/function/DecompilerParameterIdCmd.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/cmd/function/DecompilerParameterIdCmd.java index 820eb6c94a..c35f6eef1f 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/cmd/function/DecompilerParameterIdCmd.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/cmd/function/DecompilerParameterIdCmd.java @@ -208,8 +208,9 @@ public class DecompilerParameterIdCmd extends BackgroundCommand { boolean commitReturn = true; if (!commitVoidReturn) { DataType returnType = hfunc.getFunctionPrototype().getReturnType(); - if (returnType instanceof VoidDataType) + if (returnType instanceof VoidDataType) { commitReturn = false; + } } if (commitReturn) { HighFunctionDBUtil.commitReturnToDatabase(hfunc, SourceType.ANALYSIS); @@ -274,7 +275,7 @@ public class DecompilerParameterIdCmd extends BackgroundCommand { if (sym.getName().equals("in_FS_OFFSET")) { continue; } - if (!sym.getHighVariable().getStorage().isRegisterStorage()) { + if (!sym.getStorage().isRegisterStorage()) { continue; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableDecl.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableDecl.java index aceb3d414a..ee41f0c1ad 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableDecl.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableDecl.java @@ -64,9 +64,5 @@ public class ClangVariableDecl extends ClangTokenGroup { } typevar = sym.getHighVariable(); datatype = sym.getDataType(); - if (typevar == null) { - Msg.error(this, "High variable not found: " + sym.getName()); - return; - } } } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java index d3f4711db0..fed8008ce0 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java @@ -130,7 +130,7 @@ public class FillOutStructureCmd extends BackgroundCommand { } } - if (var == null) { + if (var == null || var.getSymbol() == null || var.getOffset() >= 0) { return false; } @@ -232,7 +232,8 @@ public class FillOutStructureCmd extends BackgroundCommand { private void commitVariable(HighVariable var, DataType newDt, boolean isThisParam) { if (!isThisParam) { try { - HighFunctionDBUtil.updateDBVariable(var, null, newDt, SourceType.USER_DEFINED); + HighFunctionDBUtil.updateDBVariable(var.getSymbol(), null, newDt, + SourceType.USER_DEFINED); } catch (DuplicateNameException e) { throw new AssertException("Unexpected exception", e); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameVariableAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameVariableAction.java index 6e00b90655..68445aeabc 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameVariableAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameVariableAction.java @@ -151,6 +151,9 @@ public class RenameVariableAction extends AbstractDecompilerAction { return false; } } + if (variable.getSymbol() == null) { + return false; + } if (variable instanceof HighLocal) { getPopupMenuData().setMenuItemName("Rename Variable"); return true; @@ -159,11 +162,6 @@ public class RenameVariableAction extends AbstractDecompilerAction { getPopupMenuData().setMenuItemName("Rename Global"); return true; } -//TODO: Constant equates do not work properly with decompiler -// else if (variable instanceof HighConstant) { -// getPopupMenuData().setMenuItemName("Rename Constant"); -// return true; -// } return false; } @@ -179,20 +177,18 @@ public class RenameVariableAction extends AbstractDecompilerAction { 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) { nameTask = - new RenameVariableTask(tool, variable.getName(), controller.getHighFunction(), - variable, tokenAtCursor.getVarnode(), SourceType.USER_DEFINED); + new RenameVariableTask(tool, variable.getSymbol().getName(), + controller.getHighFunction(), variable, tokenAtCursor.getVarnode(), + SourceType.USER_DEFINED); } 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()) { Msg.showError(this, tool.getToolFrame(), "Rename Failed", "Memory storage not found for global variable"); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameVariableTask.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameVariableTask.java index 0a2e9181c1..68f5fb039e 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameVariableTask.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameVariableTask.java @@ -55,7 +55,7 @@ public class RenameVariableTask extends RenameTask { HighFunctionDBUtil.commitReturnToDatabase(hfunction, signatureSrcType); } } - HighFunctionDBUtil.updateDBVariable(var, newName, null, srctype); + HighFunctionDBUtil.updateDBVariable(var.getSymbol(), newName, null, srctype); } @Override @@ -80,6 +80,10 @@ public class RenameVariableTask extends RenameTask { return false; } } + if (var.getSymbol() == null) { + errorMsg = "Rename Failed: No symbol"; + return false; + } return true; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeVariableAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeVariableAction.java index 17a4f4644b..eaba37170a 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeVariableAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeVariableAction.java @@ -129,13 +129,6 @@ public class RetypeVariableAction extends AbstractDecompilerAction { boolean commitRequired = checkFullCommit(var, hfunction); 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 } @@ -176,7 +169,7 @@ public class RetypeVariableAction extends AbstractDecompilerAction { 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; } catch (DuplicateNameException e) { @@ -298,7 +291,7 @@ public class RetypeVariableAction extends AbstractDecompilerAction { } for (int i = 0; i < numParams; i++) { - HighParam param = localSymbolMap.getParam(i); + MappedSymbol param = localSymbolMap.getParamSymbol(i); if (param.getSlot() != i) { return true; } @@ -350,11 +343,10 @@ public class RetypeVariableAction extends AbstractDecompilerAction { return false; } } - if (variable instanceof HighConstant) { -// getPopupMenuData().setMenuItemName("Retype Constant"); -// return true; + if (variable.getSymbol() == null) { + return false; } - else if (variable instanceof HighLocal) { + if (variable instanceof HighLocal) { getPopupMenuData().setMenuItemName("Retype Variable"); return true; } @@ -412,7 +404,7 @@ public class RetypeVariableAction extends AbstractDecompilerAction { return; } variable = RenameVariableAction.forgeHighVariable(addr, controller); - if (variable == null) { + if (variable == null || variable.getSymbol() == null || variable.getOffset() >= 0) { return; } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicSymbol.java index e50dca0592..d60baf4b34 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicSymbol.java @@ -16,7 +16,12 @@ package ghidra.program.model.pcode; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSpace; 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.xml.XmlElement; import ghidra.xml.XmlPullParser; @@ -26,53 +31,25 @@ import ghidra.xml.XmlPullParser; * */ public class DynamicSymbol extends HighSymbol { - public static class Entry { - public final Address pcaddr; - public final long hash; - public final int format; + protected long hash; // Hash encoding the specific Varnode - public Entry(Address addr,long h,int f) { - pcaddr = addr; - hash = h; - format = f; - } - } - - private Entry[] refs; - - public DynamicSymbol() { // For use with restoreXML - refs = new Entry[0]; + public DynamicSymbol(HighFunction func) { // For use with restoreXML + super(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); - refs = new Entry[1]; - refs[0] = new Entry(addr,hash,format); + this.hash = hash; } public long getHash() { - return refs[0].hash; - } - - public void addReference(Address addr,long hash,int format) { - Entry[] newrefs = new Entry[refs.length + 1]; - for(int i=0;i"); - buildRangelistXML(buf, ref.pcaddr); - } + buf.append(""); + buildRangelistXML(buf, pcaddr); } @Override @@ -88,25 +65,39 @@ public class DynamicSymbol extends HighSymbol { } @Override - public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException { + public void restoreXML(XmlPullParser parser) throws PcodeXMLException { XmlElement symel = parser.start("symbol"); - restoreSymbolXML(symel, func); - type = func.getDataTypeManager().readXMLDataType(parser); + restoreSymbolXML(symel); + type = function.getDataTypeManager().readXMLDataType(parser); size = type.getLength(); parser.end(symel); if (size == 0) { throw new PcodeXMLException("Invalid symbol 0-sized data-type: " + type.getName()); } + restoreEntryXML(parser); while(parser.peek().isStart()) { - long hash = 0; - int format = 0; - XmlElement addrel = parser.start("hash"); - hash = SpecXmlUtils.decodeLong(addrel.getAttribute("val")); - format = SpecXmlUtils.decodeInt(symel.getAttribute("format")); - parser.end(addrel); - Address addr = parseRangeList(parser); - addReference(addr,hash,format); + parser.discardSubTree(); + } + } + + @Override + protected void restoreEntryXML(XmlPullParser parser) throws PcodeXMLException { + XmlElement addrel = parser.start("hash"); + hash = SpecXmlUtils.decodeLong(addrel.getAttribute("val")); + parser.end(addrel); + pcaddr = parseRangeList(parser); + } + + @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("\n"); 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); + } + } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/EquateSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/EquateSymbol.java index 5599483906..6c71a1a0d8 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/EquateSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/EquateSymbol.java @@ -33,19 +33,20 @@ public class EquateSymbol extends DynamicSymbol { private long value; // Value of the 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, - long hash, int format) { - super(uniqueId, nm, DataType.DEFAULT, 1, func, addr, hash, format); + long hash) { + super(uniqueId, nm, DataType.DEFAULT, 1, func, addr, hash); value = val; convert = FORMAT_DEFAULT; } 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); + long hash) { + super(uniqueId, "", DataType.DEFAULT, 1, func, addr, hash); value = val; convert = conv; } @@ -53,9 +54,9 @@ public class EquateSymbol extends DynamicSymbol { public long getValue() { return value; } @Override - public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException { + public void restoreXML(XmlPullParser parser) throws PcodeXMLException { XmlElement symel = parser.start("equatesymbol"); - restoreSymbolXML(symel, func); + restoreSymbolXML(symel); type = DataType.DEFAULT; size = 1; convert = FORMAT_DEFAULT; @@ -84,15 +85,9 @@ public class EquateSymbol extends DynamicSymbol { if (size == 0) { throw new PcodeXMLException("Invalid symbol 0-sized data-type: " + type.getName()); } + restoreEntryXML(parser); while(parser.peek().isStart()) { - long hash = 0; - 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); + parser.discardSubTree(); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/FunctionPrototype.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/FunctionPrototype.java index 4896a67280..091e1e6162 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/FunctionPrototype.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/FunctionPrototype.java @@ -210,9 +210,9 @@ public class FunctionPrototype { * @return the i'th HighParam to this function prototype or null * if this prototype is not backed by a LocalSymbolMap */ - public HighParam getParam(int i) { + public HighSymbol getParam(int i) { if (localsyms != null) { - return localsyms.getParam(i); + return localsyms.getParamSymbol(i); } return null; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/GlobalSymbolMap.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/GlobalSymbolMap.java index 8347761358..a7414645ef 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/GlobalSymbolMap.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/GlobalSymbolMap.java @@ -99,6 +99,10 @@ public class GlobalSymbolMap { * @return the new HighSymbol or null */ 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); insertSymbol(symbol, addr); return symbol; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighCodeSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighCodeSymbol.java index fea400be3f..9dbdd000f5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighCodeSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighCodeSymbol.java @@ -17,9 +17,13 @@ package ghidra.program.model.pcode; import ghidra.program.database.symbol.CodeSymbol; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressFactory; 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.util.exception.InvalidInputException; +import ghidra.xml.XmlElement; import ghidra.xml.XmlPullParser; /** @@ -29,6 +33,7 @@ public class HighCodeSymbol extends HighSymbol { private CodeSymbol symbol; private Data data; + private VariableStorage storage; public HighCodeSymbol(CodeSymbol sym, DataType dataType, int sz, HighFunction 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); } + @Override + public boolean isGlobal() { + return true; + } + public CodeSymbol getCodeSymbol() { return symbol; } @@ -57,6 +67,26 @@ public class HighCodeSymbol extends HighSymbol { 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 public String buildXML() { // TODO Auto-generated method stub @@ -64,8 +94,37 @@ public class HighCodeSymbol extends HighSymbol { } @Override - public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException { - // TODO Auto-generated method stub + public void restoreXML(XmlPullParser parser) throws PcodeXMLException { + 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); + } } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighConstant.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighConstant.java index 95d6d32c70..5c0f1314b3 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighConstant.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighConstant.java @@ -18,7 +18,11 @@ package ghidra.program.model.pcode; import ghidra.program.model.address.Address; import ghidra.program.model.data.AbstractIntegerDataType; import ghidra.program.model.data.DataType; +import ghidra.program.model.listing.Program; 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 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 * @param name name of variable @@ -43,19 +55,6 @@ public class HighConstant extends HighVariable { 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 public HighSymbol getSymbol() { return symbol; @@ -88,4 +87,36 @@ public class HighConstant extends HighVariable { 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); + } + } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java index 3d85795afc..e0e022fd3e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java @@ -24,7 +24,6 @@ import org.xml.sax.*; import ghidra.program.database.symbol.CodeSymbol; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressOutOfBoundsException; -import ghidra.program.model.data.DataType; import ghidra.program.model.lang.CompilerSpec; import ghidra.program.model.lang.Language; import ghidra.program.model.listing.*; @@ -209,41 +208,29 @@ public class HighFunction extends PcodeSyntaxTree { } private void readHighXML(XmlPullParser parser) throws PcodeXMLException { - XmlElement el = parser.start("high"); + XmlElement el = parser.peek(); String classstring = el.getAttribute("class"); - long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref")); - int repref = SpecXmlUtils.decodeInt(el.getAttribute("repref")); - Varnode rep = getRef(repref); - if (rep == null) { - throw new PcodeXMLException("Undefined varnode reference"); + HighVariable var; + switch (classstring.charAt(0)) { + case 'o': + var = new HighOther(this); + 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); } - - DataType type = null; - - ArrayList vnlist = new ArrayList(); - int sz = -1; - if (parser.peek().isStart()) { - type = getDataTypeManager().readXMLDataType(parser); - } - - if (type == null) { - throw new PcodeXMLException("Missing 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); + var.restoreXml(parser); } private void readHighlistXML(XmlPullParser parser) throws PcodeXMLException { @@ -329,97 +316,7 @@ public class HighFunction extends PcodeSyntaxTree { parser.end(el); } - private HighVariable newHigh(long symref, DataType tp, int sz, Varnode[] inst, 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) { + protected Address getPCAddress(Varnode rep) { Address pcaddr = null; if (!rep.isAddrTied()) { pcaddr = rep.getPCAddress(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java index 2b079358d1..68c8907d9b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java @@ -97,7 +97,7 @@ public class HighFunctionDBUtil { List params = new ArrayList(); int paramCnt = symbolMap.getNumParams(); for (int i = 0; i < paramCnt; ++i) { - HighParam param = symbolMap.getParam(i); + HighSymbol param = symbolMap.getParamSymbol(i); String name = param.getName(); DataType dataType; if (useDataTypes) { @@ -201,23 +201,20 @@ public class HighFunctionDBUtil { Iterator iter = highFunction.getLocalSymbolMap().getSymbols(); while (iter.hasNext()) { HighSymbol sym = iter.next(); - HighVariable high = sym.getHighVariable(); - if ((high instanceof HighParam) || !(high instanceof HighLocal)) { + if (sym.isParameter() || sym.isGlobal()) { continue; } - - HighLocal local = (HighLocal) high; - String name = local.getName(); + String name = sym.getName(); try { - Variable var = clearConflictingLocalVariables(local); + Variable var = clearConflictingLocalVariables(sym); if (var == null) { - var = createLocalVariable(local, null, null, source); + var = createLocalVariable(sym, null, null, source); if (name != null) { var.setName(name, source); } } else { - var.setDataType(local.getDataType(), local.getStorage(), false, source); + var.setDataType(sym.getDataType(), sym.getStorage(), false, source); var.setName(name, source); } } @@ -229,28 +226,29 @@ public class HighFunctionDBUtil { } /** - * Create a local DB variable with a default name - * @param local - * @param dt data type or null to use local data type defined by local high variable - * @param storage storage or null to use storage defined by local high variable - * @param source - * @return - * @throws InvalidInputException - * @throws DuplicateNameException + * Create a local DB variable with a default name. Storage and data-type for the variable + * can be provided explicitly, or they can be taken from a decompiler symbol. + * @param symbol is the decompiler symbol + * @param dt is the given data-type or null (to use the symbol's data-type) + * @param storage is the given storage or null (to use the symbol's storage) + * @param source is the desired SourceType of the new variable + * @return the new local variable + * @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 { - Function function = local.getHighFunction().getFunction(); + Function function = symbol.getHighFunction().getFunction(); Program program = function.getProgram(); if (storage == null || storage.isUniqueStorage()) { - storage = local.getStorage(); + storage = symbol.getStorage(); } 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 { - var = function.addLocalVariable(var, SourceType.ANALYSIS); + var = function.addLocalVariable(var, source); } catch (DuplicateNameException e) { throw new AssertException("Unexpected exception with default name", e); @@ -258,7 +256,7 @@ public class HighFunctionDBUtil { Register reg = var.getRegister(); if (reg != null) { - program.getReferenceManager().addRegisterReference(local.getPCAddress(), -1, reg, + program.getReferenceManager().addRegisterReference(symbol.getPCAddress(), -1, reg, RefType.WRITE, source); } @@ -282,13 +280,15 @@ public class HighFunctionDBUtil { long hash = var.getFirstStorageVarnode().getOffset(); Iterator symbols = highFunction.getLocalSymbolMap().getSymbols(); while (symbols.hasNext()) { - HighVariable high = symbols.next().getHighVariable(); - if (!(high instanceof HighLocal)) { + HighSymbol symbol = symbols.next(); + if (!(symbol instanceof DynamicSymbol)) { continue; } // Note: assumes there is only one hash method used for unique locals - if (((HighLocal) high).buildDynamicHash() == hash) { - return true; + if (((DynamicSymbol) symbol).getHash() == hash) { + if (symbol.getHighVariable() != null) { + return true; // Hash successfully attached to a variable + } } } return false; @@ -301,25 +301,22 @@ public class HighFunctionDBUtil { * exists within the function at the same first-use-offset. * @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) { - throw new IllegalArgumentException(); + if (local instanceof MappedSymbol) { + if (((MappedSymbol) local).getSlot() >= 0) { // Don't clear parameters + throw new IllegalArgumentException(); + } } HighFunction highFunction = local.getHighFunction(); Function func = highFunction.getFunction(); - HighSymbol symbol = local.getSymbol(); VariableStorage storage = local.getStorage(); int firstUseOffset = local.getFirstUseOffset(); - if (symbol instanceof DynamicSymbol || storage.isUniqueStorage()) { + if (local instanceof DynamicSymbol) { - if (!(symbol instanceof DynamicSymbol)) { - return null; - } - - DynamicSymbol dynamicSym = (DynamicSymbol) symbol; + DynamicSymbol dynamicSym = (DynamicSymbol) local; for (Variable ul : func.getLocalVariables(VariableFilter.UNIQUE_VARIABLE_FILTER)) { // Note: assumes there is only one hash method used for unique locals if (ul.getFirstStorageVarnode().getOffset() == dynamicSym.getHash()) { @@ -352,15 +349,15 @@ public class HighFunctionDBUtil { } /** - * Get database parameter which corresponds to HighParam, where we anticipate that - * the parameter will be modified to match the HighParam. The entire prototype is + * Get database parameter which corresponds to the given symbol, where we anticipate that + * 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 * 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 * @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(); 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. - * Only variable types HighParam, HighLocal and HighGlobal are supported. - * @param variable + * @param variable is the symbol being updated * @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. * 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 * @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 { HighFunction highFunction = variable.getHighFunction(); @@ -427,10 +423,11 @@ public class HighFunctionDBUtil { boolean isRename = name != null; - if (variable instanceof HighParam) { - HighParam param = (HighParam) variable; - Parameter dbParam = getDatabaseParameter(param); - VariableStorage storage = param.getStorage(); + if (variable.isParameter()) { + MappedSymbol mappedSymbol = (MappedSymbol) variable; + + Parameter dbParam = getDatabaseParameter(mappedSymbol); + VariableStorage storage = mappedSymbol.getStorage(); if (dataType != null) { if (resized && function.hasCustomVariableStorage()) { VariableStorage newStorage = @@ -445,12 +442,20 @@ public class HighFunctionDBUtil { dbParam.setName(name, source); } } - else if (variable instanceof HighLocal) { - HighLocal local = (HighLocal) variable; - VariableStorage storage = local.getStorage(); + else if (!variable.isGlobal()) { + Variable var; + 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(); - - Variable var = clearConflictingLocalVariables(local); if (dataType == null) { if (var != null) { dataType = var.getDataType(); // Use preexisting datatype if it fits in desired storage @@ -463,21 +468,21 @@ public class HighFunctionDBUtil { if (resized) { if (usesHashStorage) { 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()); } storage = VariableUtilities.resizeStorage(storage, dataType, true, function); } if (var == null) { - var = createLocalVariable(local, dataType, storage, source); + var = createLocalVariable(variable, dataType, storage, source); } else { // fixup reused variable 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 { // must set/correct name @@ -499,7 +504,7 @@ public class HighFunctionDBUtil { } } } - else if (variable instanceof HighGlobal) { + else { // A global symbol VariableStorage storage = variable.getStorage(); if (!storage.isMemoryStorage()) { @@ -507,21 +512,20 @@ public class HighFunctionDBUtil { "Database supports global memory variables only"); } - HighGlobal global = (HighGlobal) variable; if (name == null) { - name = global.getName(); + name = variable.getName(); if (name != null && SymbolUtilities.isDynamicSymbolPattern(name, true)) { name = null; } } if (dataType != null) { - setGlobalDataType(global, dataType); + setGlobalDataType(variable, dataType); } if (name != null) { try { - setGlobalName((HighGlobal) variable, variable.getName(), source); + setGlobalName(variable, variable.getName(), source); } catch (DuplicateNameException e) { 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 { Program program = global.getHighFunction().getFunction().getProgram(); 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 { Program program = global.getHighFunction().getFunction().getProgram(); VariableStorage storage = global.getStorage(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighGlobal.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighGlobal.java index f5f3608df1..b66eb73332 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighGlobal.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighGlobal.java @@ -15,6 +15,12 @@ */ 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; + /** + * 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) { super(sym.getName(), sym.getDataType(), vn, inst, sym.getHighFunction()); symbol = sym; @@ -33,4 +47,50 @@ public class HighGlobal extends HighVariable { 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")); + 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 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); + } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighLocal.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighLocal.java index 0573fd6b5a..2ff6b83a71 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighLocal.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighLocal.java @@ -16,18 +16,23 @@ package ghidra.program.model.pcode; import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressSpace; 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.xml.XmlElement; +import ghidra.xml.XmlPullParser; 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 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) { super(sym.getName(), type, vn, inst, sym.getHighFunction()); @@ -47,51 +52,30 @@ public class HighLocal extends HighVariable { return pcaddr; } - protected int getFirstUseOffset() { - if (pcaddr == null || getRepresentative().getAddress().isStackAddress()) { - return 0; - } - return (int) pcaddr.subtract(getHighFunction().getFunction().getEntryPoint()); - } - @Override - public VariableStorage getStorage() { - - Program program = getHighFunction().getFunction().getProgram(); - Varnode represent = getRepresentative(); - - if (symbol instanceof DynamicSymbol || represent.isUnique()) { - long ourHash = buildDynamicHash(); - try { - return new VariableStorage(program, AddressSpace.HASH_SPACE.getAddress(ourHash), - represent.getSize()); - } - catch (InvalidInputException e) { - throw new AssertException("Unexpected exception", e); - } + 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"); + if (attrString != null) { + offset = SpecXmlUtils.decodeInt(attrString); } + restoreInstances(parser, el); + symbol = function.getLocalSymbolMap().getSymbol(symref); + if (symbol == null) { + throw new PcodeXMLException("HighLocal is missing symbol"); + } + if (offset < 0) { + name = symbol.getName(); + } + else { + name = "UNNAMED"; + } + pcaddr = symbol.getPCAddress(); + symbol.setHighVariable(this); - if (symbol instanceof MappedSymbol) { - 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(); - } - else if (getRepresentative().isUnique()) { - DynamicHash dynamicHash = new DynamicHash(getRepresentative(), getHighFunction()); - hash = dynamicHash.getHash(); - pcaddr = dynamicHash.getAddress(); - } - return hash; + parser.end(el); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighOther.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighOther.java index 4d23124553..53741e7da1 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighOther.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighOther.java @@ -17,6 +17,9 @@ 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; /** * @@ -26,8 +29,16 @@ import ghidra.program.model.data.DataType; */ public class HighOther extends HighVariable { - private DynamicSymbol symbol; 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 @@ -42,14 +53,6 @@ public class HighOther extends HighVariable { 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 */ @@ -57,4 +60,31 @@ public class HighOther extends HighVariable { 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); + } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighParam.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighParam.java index 6dd6e8d818..9b9b3b311c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighParam.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighParam.java @@ -17,6 +17,7 @@ package ghidra.program.model.pcode; import ghidra.program.model.address.Address; 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 { 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 rep is the representative input Varnode @@ -46,8 +55,13 @@ public class HighParam extends HighLocal { } @Override - protected int getFirstUseOffset() { - return 0; + public void restoreXml(XmlPullParser parser) throws PcodeXMLException { + super.restoreXml(parser); + slot = 0; + HighSymbol sym = getSymbol(); + if (sym instanceof MappedSymbol) { + slot = ((MappedSymbol) sym).getSlot(); + } } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java index f051b5087f..c7d644b43c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java @@ -18,6 +18,7 @@ package ghidra.program.model.pcode; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.data.DataType; +import ghidra.program.model.listing.VariableStorage; import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.XmlElement; import ghidra.xml.XmlPullParser; @@ -37,7 +38,8 @@ public abstract class HighSymbol { 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, @@ -80,6 +82,13 @@ public abstract class HighSymbol { return pcaddr; } + protected int getFirstUseOffset() { + if (pcaddr == null) { + return 0; + } + return (int) pcaddr.subtract(getHighFunction().getFunction().getEntryPoint()); + } + public HighFunction getHighFunction() { return function; } @@ -108,13 +117,32 @@ public abstract class HighSymbol { 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 void restoreXML(XmlPullParser parser, HighFunction func) + public abstract void restoreXML(XmlPullParser parser) throws PcodeXMLException; - - protected void restoreSymbolXML(XmlElement symel, HighFunction func) throws PcodeXMLException { - function = func; + + protected abstract void restoreEntryXML(XmlPullParser parser) throws PcodeXMLException; + + protected void restoreSymbolXML(XmlElement symel) throws PcodeXMLException { id = SpecXmlUtils.decodeLong(symel.getAttribute("id")); if (id == 0) { throw new PcodeXMLException("missing unique symbol id"); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighVariable.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighVariable.java index ae24433b4c..22fbdeb36b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighVariable.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighVariable.java @@ -15,11 +15,12 @@ */ package ghidra.program.model.pcode; +import java.util.ArrayList; + import ghidra.program.model.data.DataType; -import ghidra.program.model.listing.Program; -import ghidra.program.model.listing.VariableStorage; -import ghidra.util.Msg; -import ghidra.util.exception.InvalidInputException; +import ghidra.util.xml.SpecXmlUtils; +import ghidra.xml.XmlElement; +import ghidra.xml.XmlPullParser; /** * @@ -29,11 +30,20 @@ import ghidra.util.exception.InvalidInputException; */ public abstract class HighVariable { - private String name; - private DataType type; - private Varnode represent; // A representative varnode - private Varnode[] instances; // Instances of this high-level variable - private HighFunction function; // associated function + protected String name; + protected DataType type; + protected Varnode represent; // A representative varnode + protected Varnode[] instances; // Instances of this high-level variable + 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) { name = nm; @@ -104,6 +114,15 @@ public abstract class HighVariable { */ 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. * @@ -121,16 +140,46 @@ public abstract class HighVariable { } } - public VariableStorage getStorage() { - Program program = getHighFunction().getFunction().getProgram(); - try { - if (represent != null && (represent.isAddress() || represent.isRegister())) { - return new VariableStorage(program, represent); - } + /** + * Restore the data-type and the Varnode instances of this HighVariable. + * The "representative" Varnode is also populated. + * @param parser is the XML stream + * @param el is the root 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"); } - catch (InvalidInputException e) { - Msg.error(this, "Failed to define variable storage: " + this, e); + + type = null; + + ArrayList vnlist = new ArrayList(); + if (parser.peek().isStart()) { + type = function.getDataTypeManager().readXMLDataType(parser); } - return VariableStorage.UNASSIGNED_STORAGE; + + if (type == null) { + throw new PcodeXMLException("Missing for HighVariable"); + } + + 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 XML tag + * @param parser is the XML stream + * @throws PcodeXMLException if the XML is not valid + */ + public abstract void restoreXml(XmlPullParser parser) throws PcodeXMLException; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java index 111b97292a..070116effb 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java @@ -101,7 +101,7 @@ public class LocalSymbolMap { HighSymbol sym; if (storage.isHashStorage()) { sym = newDynamicSymbol(id, name, dt, sz, storage.getFirstVarnode().getOffset(), - defAddr, 0); + defAddr); } else { sym = newMappedSymbol(id, name, dt, storage, defAddr, -1); @@ -167,16 +167,16 @@ public class LocalSymbolMap { String typename = node.getAttribute("type"); HighSymbol res = null; if (typename == null) { - res = new MappedSymbol(); + res = new MappedSymbol(func); } else if (typename.equals("dynamic")) { - res = new DynamicSymbol(); + res = new DynamicSymbol(func); } else if (typename.equals("equate")) { - res = new EquateSymbol(); + res = new EquateSymbol(func); } - res.restoreXML(parser, func); + res.restoreXML(parser); parser.end(node); insertSymbol(res); return res; @@ -225,7 +225,7 @@ public class LocalSymbolMap { ArrayList parms = new ArrayList(); while (parser.peek().isStart()) { HighSymbol sym = parseSymbolXML(parser); - if (sym instanceof MappedSymbol && ((MappedSymbol) sym).isParameter()) { + if (sym.isParameter()) { parms.add((MappedSymbol) sym); } } @@ -339,11 +339,11 @@ public class LocalSymbolMap { } public DynamicSymbol newDynamicSymbol(long id, String nm, DataType dt, int sz, long hash, - Address pcaddr, int format) { + Address pcaddr) { if (id == 0) { 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); return sym; } @@ -365,23 +365,21 @@ public class LocalSymbolMap { } private void newEquateSymbol(long uniqueId, String nm, long val, long hash, Address addr, - int format, TreeMap constantSymbolMap) { DynamicSymbol eqSymbol = constantSymbolMap.get(nm); if (eqSymbol != null) { - eqSymbol.addReference(addr, hash, format); // New reference to same symbol - return; + return; // New reference to same symbol } if (uniqueId == 0) { uniqueId = getNextId(); } int conv = EquateSymbol.convertName(nm, val); 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); } else { - eqSymbol = new EquateSymbol(uniqueId, conv, val, func, addr, hash, format); + eqSymbol = new EquateSymbol(uniqueId, conv, val, func, addr, hash); } //Do NOT setTypeLock constantSymbolMap.put(nm, eqSymbol); @@ -410,7 +408,7 @@ public class LocalSymbolMap { if (constantSymbolMap == null) { constantSymbolMap = new TreeMap(); } - newEquateSymbol(0, eq.getDisplayName(), eq.getValue(), element, defAddr, 0, + newEquateSymbol(0, eq.getDisplayName(), eq.getValue(), element, defAddr, constantSymbolMap); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/MappedSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/MappedSymbol.java index 45f7f1c872..ea75a74707 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/MappedSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/MappedSymbol.java @@ -30,7 +30,8 @@ public class MappedSymbol extends HighSymbol { private VariableStorage storage; 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, @@ -44,22 +45,14 @@ public class MappedSymbol extends HighSymbol { } this.storage = store; 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() { return storage; } + @Override public boolean isParameter() { return slot >= 0; } @@ -88,9 +81,9 @@ public class MappedSymbol extends HighSymbol { } @Override - public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException { + public void restoreXML(XmlPullParser parser) throws PcodeXMLException { XmlElement symel = parser.start("symbol"); - restoreSymbolXML(symel, func); + restoreSymbolXML(symel); slot = -1; int cat = -1; if (symel.hasAttribute("cat")) { @@ -99,7 +92,7 @@ public class MappedSymbol extends HighSymbol { slot = SpecXmlUtils.decodeInt(symel.getAttribute("index")); } } - type = func.getDataTypeManager().readXMLDataType(parser); + type = function.getDataTypeManager().readXMLDataType(parser); parser.end(symel); if (slot >= 0 && name.startsWith("$$undef")) { @@ -107,10 +100,17 @@ public class MappedSymbol extends HighSymbol { 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(); AddressFactory addrFactory = function.getAddressFactory(); - Address addr = null; XmlElement addrel = parser.start("addr"); int sz = type.getLength(); if (sz == 0) { @@ -123,8 +123,7 @@ public class MappedSymbol extends HighSymbol { storage = new VariableStorage(program, varAddr, sz); } else { - addr = varAddr; - storage = func.readXMLVarnodePieces(addrel, varAddr); + storage = function.readXMLVarnodePieces(addrel, varAddr); } } catch (InvalidInputException e) { @@ -134,16 +133,6 @@ public class MappedSymbol extends HighSymbol { parser.end(addrel); 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,