mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
Refactoring based on HighSymbol
This commit is contained in:
parent
d552aa4b82
commit
76d0f12bd3
28 changed files with 631 additions and 470 deletions
|
@ -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<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);
|
||||
|
|
|
@ -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<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 uint4 getMethodFromHash(uint8 h); ///< Retrieve the encoded method from a hash
|
||||
static OpCode getOpCodeFromHash(uint8 h); ///< Retrieve the encoded op-code from a hash
|
||||
|
|
|
@ -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 << "<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>";
|
||||
high->saveXml(s);
|
||||
}
|
||||
for(iter=beginLoc();iter!=endLoc();++iter) {
|
||||
vn = *iter;
|
||||
|
|
|
@ -315,6 +315,14 @@ HighVariable *Funcdata::findHigh(const string &name) const
|
|||
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;
|
||||
|
||||
|
|
|
@ -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 << "<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
|
||||
/// \brief Check that there are no internal Cover intersections within \b this
|
||||
///
|
||||
|
|
|
@ -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 \<high\> tag
|
||||
#ifdef MERGEMULTI_DEBUG
|
||||
void verifyCover(void) const;
|
||||
#endif
|
||||
|
|
|
@ -208,9 +208,10 @@ 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<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
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
protected void buildHashXML(StringBuilder buf) {
|
||||
for (Entry ref : refs) {
|
||||
buf.append("<hash val=\"0x").append(Long.toHexString(ref.hash)).append("\"/>");
|
||||
buildRangelistXML(buf, ref.pcaddr);
|
||||
}
|
||||
buf.append("<hash val=\"0x").append(Long.toHexString(hash)).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;
|
||||
parser.discardSubTree();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void restoreEntryXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
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);
|
||||
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("</symbol>\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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<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);
|
||||
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();
|
||||
|
|
|
@ -97,7 +97,7 @@ public class HighFunctionDBUtil {
|
|||
List<Parameter> params = new ArrayList<Parameter>();
|
||||
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<HighSymbol> 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<HighSymbol> 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) {
|
||||
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();
|
||||
|
|
|
@ -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 <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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 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());
|
||||
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);
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
throw new AssertException("Unexpected exception", e);
|
||||
restoreInstances(parser, el);
|
||||
symbol = function.getLocalSymbolMap().getSymbol(symref);
|
||||
if (symbol == null) {
|
||||
throw new PcodeXMLException("HighLocal is missing symbol");
|
||||
}
|
||||
if (offset < 0) {
|
||||
name = symbol.getName();
|
||||
}
|
||||
|
||||
if (symbol instanceof MappedSymbol) {
|
||||
return ((MappedSymbol) symbol).getStorage();
|
||||
else {
|
||||
name = "UNNAMED";
|
||||
}
|
||||
|
||||
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;
|
||||
symbol.setHighVariable(this);
|
||||
|
||||
parser.end(el);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 <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;
|
||||
}
|
||||
|
|
|
@ -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<MappedSymbol> parms = new ArrayList<MappedSymbol>();
|
||||
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<String, DynamicSymbol> 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<String, DynamicSymbol>();
|
||||
}
|
||||
newEquateSymbol(0, eq.getDisplayName(), eq.getValue(), element, defAddr, 0,
|
||||
newEquateSymbol(0, eq.getDisplayName(), eq.getValue(), element, defAddr,
|
||||
constantSymbolMap);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue