mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +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 addr is the given address
|
||||||
/// \param h is the hash
|
/// \param h is the hash
|
||||||
/// \return the matching Varnode or NULL
|
/// \return the matching Varnode or NULL
|
||||||
Varnode *DynamicHash::findVarnode(Funcdata *fd,const Address &addr,uint8 h)
|
Varnode *DynamicHash::findVarnode(const Funcdata *fd,const Address &addr,uint8 h)
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 method = getMethodFromHash(h);
|
uint4 method = getMethodFromHash(h);
|
||||||
|
@ -423,7 +423,7 @@ Varnode *DynamicHash::findVarnode(Funcdata *fd,const Address &addr,uint8 h)
|
||||||
/// \param fd is the function holding the data-flow
|
/// \param fd is the function holding the data-flow
|
||||||
/// \param addr is the given address
|
/// \param addr is the given address
|
||||||
/// \param h is the given hash
|
/// \param h is the given hash
|
||||||
void DynamicHash::gatherFirstLevelVars(vector<Varnode *> &varlist,Funcdata *fd,const Address &addr,uint8 h)
|
void DynamicHash::gatherFirstLevelVars(vector<Varnode *> &varlist,const Funcdata *fd,const Address &addr,uint8 h)
|
||||||
|
|
||||||
{
|
{
|
||||||
OpCode opc = getOpCodeFromHash(h);
|
OpCode opc = getOpCodeFromHash(h);
|
||||||
|
|
|
@ -79,11 +79,11 @@ public:
|
||||||
void clear(void); ///< Called for each additional hash (after the first)
|
void clear(void); ///< Called for each additional hash (after the first)
|
||||||
void calcHash(const Varnode *root,uint4 method); ///< Calculate the hash for given Varnode and method
|
void calcHash(const Varnode *root,uint4 method); ///< Calculate the hash for given Varnode and method
|
||||||
void uniqueHash(const Varnode *root,Funcdata *fd); ///< Select a unique hash for the given Varnode
|
void uniqueHash(const Varnode *root,Funcdata *fd); ///< Select a unique hash for the given Varnode
|
||||||
Varnode *findVarnode(Funcdata *fd,const Address &addr,uint8 h);
|
Varnode *findVarnode(const Funcdata *fd,const Address &addr,uint8 h);
|
||||||
uint8 getHash(void) const { return hash; } ///< Get the (current) hash
|
uint8 getHash(void) const { return hash; } ///< Get the (current) hash
|
||||||
|
|
||||||
const Address &getAddress(void) const { return addrresult; } ///< Get the (current) address
|
const Address &getAddress(void) const { return addrresult; } ///< Get the (current) address
|
||||||
static void gatherFirstLevelVars(vector<Varnode *> &varlist,Funcdata *fd,const Address &addr,uint8 h);
|
static void gatherFirstLevelVars(vector<Varnode *> &varlist,const Funcdata *fd,const Address &addr,uint8 h);
|
||||||
static int4 getSlotFromHash(uint8 h); ///< Retrieve the encoded slot from a hash
|
static int4 getSlotFromHash(uint8 h); ///< Retrieve the encoded slot from a hash
|
||||||
static uint4 getMethodFromHash(uint8 h); ///< Retrieve the encoded method from a hash
|
static uint4 getMethodFromHash(uint8 h); ///< Retrieve the encoded method from a hash
|
||||||
static OpCode getOpCodeFromHash(uint8 h); ///< Retrieve the encoded op-code from a hash
|
static OpCode getOpCodeFromHash(uint8 h); ///< Retrieve the encoded op-code from a hash
|
||||||
|
|
|
@ -607,7 +607,6 @@ void Funcdata::saveVarnodeXml(ostream &s,VarnodeLocSet::const_iterator iter,Varn
|
||||||
void Funcdata::saveXmlHigh(ostream &s) const
|
void Funcdata::saveXmlHigh(ostream &s) const
|
||||||
|
|
||||||
{
|
{
|
||||||
int4 j;
|
|
||||||
Varnode *vn;
|
Varnode *vn;
|
||||||
HighVariable *high;
|
HighVariable *high;
|
||||||
|
|
||||||
|
@ -620,32 +619,7 @@ void Funcdata::saveXmlHigh(ostream &s) const
|
||||||
high = vn->getHigh();
|
high = vn->getHigh();
|
||||||
if (high->isMark()) continue;
|
if (high->isMark()) continue;
|
||||||
high->setMark();
|
high->setMark();
|
||||||
vn = high->getNameRepresentative(); // Get representative varnode
|
high->saveXml(s);
|
||||||
s << "<high ";
|
|
||||||
// a_v(s,"name",high->getName());
|
|
||||||
a_v_u(s,"repref",vn->getCreateIndex());
|
|
||||||
if (high->isSpacebase()||high->isImplied()) // This is a special variable
|
|
||||||
a_v(s,"class",string("other"));
|
|
||||||
else if (high->isPersist()&&high->isAddrTied()) // Global variable
|
|
||||||
a_v(s,"class",string("global"));
|
|
||||||
else if (high->isConstant())
|
|
||||||
a_v(s,"class",string("constant"));
|
|
||||||
else if (!high->isPersist())
|
|
||||||
a_v(s,"class",string("local"));
|
|
||||||
else
|
|
||||||
a_v(s,"class",string("other"));
|
|
||||||
if (high->isTypeLock())
|
|
||||||
a_v_b(s,"typelock",true);
|
|
||||||
if (high->getSymbol() != (Symbol *)0)
|
|
||||||
a_v_u(s,"symref",high->getSymbol()->getId());
|
|
||||||
s << '>';
|
|
||||||
high->getType()->saveXml(s);
|
|
||||||
for(j=0;j<high->numInstances();++j) {
|
|
||||||
s << "<addr ";
|
|
||||||
a_v_u(s,"ref",high->getInstance(j)->getCreateIndex());
|
|
||||||
s << "/>";
|
|
||||||
}
|
|
||||||
s << "</high>";
|
|
||||||
}
|
}
|
||||||
for(iter=beginLoc();iter!=endLoc();++iter) {
|
for(iter=beginLoc();iter!=endLoc();++iter) {
|
||||||
vn = *iter;
|
vn = *iter;
|
||||||
|
|
|
@ -315,6 +315,14 @@ HighVariable *Funcdata::findHigh(const string &name) const
|
||||||
Symbol *sym = symList[0];
|
Symbol *sym = symList[0];
|
||||||
SymbolEntry *entry = sym->getFirstWholeMap();
|
SymbolEntry *entry = sym->getFirstWholeMap();
|
||||||
|
|
||||||
|
if (entry->isDynamic()) {
|
||||||
|
DynamicHash dhash;
|
||||||
|
Varnode *vn = dhash.findVarnode(this, entry->getFirstUseAddress(), entry->getHash());
|
||||||
|
if (vn == (Varnode *)0 || vn->isAnnotation())
|
||||||
|
return (HighVariable *)0;
|
||||||
|
return vn->getHigh();
|
||||||
|
}
|
||||||
|
|
||||||
VarnodeLocSet::const_iterator iter,enditer;
|
VarnodeLocSet::const_iterator iter,enditer;
|
||||||
HighVariable *high;
|
HighVariable *high;
|
||||||
|
|
||||||
|
|
|
@ -359,6 +359,46 @@ int4 HighVariable::instanceIndex(const Varnode *vn) const
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \param s is the output stream to write XML to
|
||||||
|
void HighVariable::saveXml(ostream &s) const
|
||||||
|
|
||||||
|
{
|
||||||
|
Varnode *vn = getNameRepresentative(); // Get representative varnode
|
||||||
|
s << "<high ";
|
||||||
|
// a_v(s,"name",high->getName());
|
||||||
|
a_v_u(s,"repref",vn->getCreateIndex());
|
||||||
|
if (isSpacebase()||isImplied()) // This is a special variable
|
||||||
|
a_v(s,"class",string("other"));
|
||||||
|
else if (isPersist()&&isAddrTied()) // Global variable
|
||||||
|
a_v(s,"class",string("global"));
|
||||||
|
else if (isConstant())
|
||||||
|
a_v(s,"class",string("constant"));
|
||||||
|
else if (!isPersist() && (symbol != (Symbol *)0)) {
|
||||||
|
if (symbol->getCategory() == 0)
|
||||||
|
a_v(s,"class",string("param"));
|
||||||
|
else
|
||||||
|
a_v(s,"class",string("local"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a_v(s,"class",string("other"));
|
||||||
|
}
|
||||||
|
if (isTypeLock())
|
||||||
|
a_v_b(s,"typelock",true);
|
||||||
|
if (symbol != (Symbol *)0) {
|
||||||
|
a_v_u(s,"symref",symbol->getId());
|
||||||
|
if (symboloffset >= 0)
|
||||||
|
a_v_i(s, "offset", symboloffset);
|
||||||
|
}
|
||||||
|
s << '>';
|
||||||
|
getType()->saveXml(s);
|
||||||
|
for(int4 j=0;j<inst.size();++j) {
|
||||||
|
s << "<addr ";
|
||||||
|
a_v_u(s,"ref",inst[j]->getCreateIndex());
|
||||||
|
s << "/>";
|
||||||
|
}
|
||||||
|
s << "</high>";
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MERGEMULTI_DEBUG
|
#ifdef MERGEMULTI_DEBUG
|
||||||
/// \brief Check that there are no internal Cover intersections within \b this
|
/// \brief Check that there are no internal Cover intersections within \b this
|
||||||
///
|
///
|
||||||
|
|
|
@ -129,6 +129,7 @@ public:
|
||||||
bool isUnattached(void) const { return inst.empty(); } ///< Return \b true if \b this has no member Varnode
|
bool isUnattached(void) const { return inst.empty(); } ///< Return \b true if \b this has no member Varnode
|
||||||
bool isTypeLock(void) const { updateType(); return ((flags & Varnode::typelock)!=0); } ///< Return \b true if \b this is \e typelocked
|
bool isTypeLock(void) const { updateType(); return ((flags & Varnode::typelock)!=0); } ///< Return \b true if \b this is \e typelocked
|
||||||
bool isNameLock(void) const { updateFlags(); return ((flags & Varnode::namelock)!=0); } ///< Return \b true if \b this is \e namelocked
|
bool isNameLock(void) const { updateFlags(); return ((flags & Varnode::namelock)!=0); } ///< Return \b true if \b this is \e namelocked
|
||||||
|
void saveXml(ostream &s) const; ///< Save the variable to stream as an XML \<high\> tag
|
||||||
#ifdef MERGEMULTI_DEBUG
|
#ifdef MERGEMULTI_DEBUG
|
||||||
void verifyCover(void) const;
|
void verifyCover(void) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -208,8 +208,9 @@ public class DecompilerParameterIdCmd extends BackgroundCommand {
|
||||||
boolean commitReturn = true;
|
boolean commitReturn = true;
|
||||||
if (!commitVoidReturn) {
|
if (!commitVoidReturn) {
|
||||||
DataType returnType = hfunc.getFunctionPrototype().getReturnType();
|
DataType returnType = hfunc.getFunctionPrototype().getReturnType();
|
||||||
if (returnType instanceof VoidDataType)
|
if (returnType instanceof VoidDataType) {
|
||||||
commitReturn = false;
|
commitReturn = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (commitReturn) {
|
if (commitReturn) {
|
||||||
HighFunctionDBUtil.commitReturnToDatabase(hfunc, SourceType.ANALYSIS);
|
HighFunctionDBUtil.commitReturnToDatabase(hfunc, SourceType.ANALYSIS);
|
||||||
|
@ -274,7 +275,7 @@ public class DecompilerParameterIdCmd extends BackgroundCommand {
|
||||||
if (sym.getName().equals("in_FS_OFFSET")) {
|
if (sym.getName().equals("in_FS_OFFSET")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!sym.getHighVariable().getStorage().isRegisterStorage()) {
|
if (!sym.getStorage().isRegisterStorage()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,9 +64,5 @@ public class ClangVariableDecl extends ClangTokenGroup {
|
||||||
}
|
}
|
||||||
typevar = sym.getHighVariable();
|
typevar = sym.getHighVariable();
|
||||||
datatype = sym.getDataType();
|
datatype = sym.getDataType();
|
||||||
if (typevar == null) {
|
|
||||||
Msg.error(this, "High variable not found: " + sym.getName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ public class FillOutStructureCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (var == null) {
|
if (var == null || var.getSymbol() == null || var.getOffset() >= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +232,8 @@ public class FillOutStructureCmd extends BackgroundCommand {
|
||||||
private void commitVariable(HighVariable var, DataType newDt, boolean isThisParam) {
|
private void commitVariable(HighVariable var, DataType newDt, boolean isThisParam) {
|
||||||
if (!isThisParam) {
|
if (!isThisParam) {
|
||||||
try {
|
try {
|
||||||
HighFunctionDBUtil.updateDBVariable(var, null, newDt, SourceType.USER_DEFINED);
|
HighFunctionDBUtil.updateDBVariable(var.getSymbol(), null, newDt,
|
||||||
|
SourceType.USER_DEFINED);
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
throw new AssertException("Unexpected exception", e);
|
throw new AssertException("Unexpected exception", e);
|
||||||
|
|
|
@ -151,6 +151,9 @@ public class RenameVariableAction extends AbstractDecompilerAction {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (variable.getSymbol() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (variable instanceof HighLocal) {
|
if (variable instanceof HighLocal) {
|
||||||
getPopupMenuData().setMenuItemName("Rename Variable");
|
getPopupMenuData().setMenuItemName("Rename Variable");
|
||||||
return true;
|
return true;
|
||||||
|
@ -159,11 +162,6 @@ public class RenameVariableAction extends AbstractDecompilerAction {
|
||||||
getPopupMenuData().setMenuItemName("Rename Global");
|
getPopupMenuData().setMenuItemName("Rename Global");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//TODO: Constant equates do not work properly with decompiler
|
|
||||||
// else if (variable instanceof HighConstant) {
|
|
||||||
// getPopupMenuData().setMenuItemName("Rename Constant");
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,20 +177,18 @@ public class RenameVariableAction extends AbstractDecompilerAction {
|
||||||
variable = forgeHighVariable(addr, controller);
|
variable = forgeHighVariable(addr, controller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO: Constant equates do not work properly with decompiler
|
|
||||||
// if (variable instanceof HighConstant) {
|
|
||||||
// nameTask =
|
|
||||||
// new RenameConstantTask(tool, tokenAtCursor.getText(), (HighConstant) variable,
|
|
||||||
// controller.getProgram());
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
if (variable instanceof HighLocal) {
|
if (variable instanceof HighLocal) {
|
||||||
nameTask =
|
nameTask =
|
||||||
new RenameVariableTask(tool, variable.getName(), controller.getHighFunction(),
|
new RenameVariableTask(tool, variable.getSymbol().getName(),
|
||||||
variable, tokenAtCursor.getVarnode(), SourceType.USER_DEFINED);
|
controller.getHighFunction(), variable, tokenAtCursor.getVarnode(),
|
||||||
|
SourceType.USER_DEFINED);
|
||||||
}
|
}
|
||||||
else if (variable instanceof HighGlobal) {
|
else if (variable instanceof HighGlobal) {
|
||||||
Address addr = variable.getRepresentative().getAddress();
|
Address addr = null;
|
||||||
|
HighSymbol sym = variable.getSymbol();
|
||||||
|
if (sym instanceof HighCodeSymbol) {
|
||||||
|
addr = ((HighCodeSymbol) sym).getStorage().getMinAddress();
|
||||||
|
}
|
||||||
if (addr == null || !addr.isMemoryAddress()) {
|
if (addr == null || !addr.isMemoryAddress()) {
|
||||||
Msg.showError(this, tool.getToolFrame(), "Rename Failed",
|
Msg.showError(this, tool.getToolFrame(), "Rename Failed",
|
||||||
"Memory storage not found for global variable");
|
"Memory storage not found for global variable");
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class RenameVariableTask extends RenameTask {
|
||||||
HighFunctionDBUtil.commitReturnToDatabase(hfunction, signatureSrcType);
|
HighFunctionDBUtil.commitReturnToDatabase(hfunction, signatureSrcType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HighFunctionDBUtil.updateDBVariable(var, newName, null, srctype);
|
HighFunctionDBUtil.updateDBVariable(var.getSymbol(), newName, null, srctype);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -80,6 +80,10 @@ public class RenameVariableTask extends RenameTask {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (var.getSymbol() == null) {
|
||||||
|
errorMsg = "Rename Failed: No symbol";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,13 +129,6 @@ public class RetypeVariableAction extends AbstractDecompilerAction {
|
||||||
|
|
||||||
boolean commitRequired = checkFullCommit(var, hfunction);
|
boolean commitRequired = checkFullCommit(var, hfunction);
|
||||||
if (commitRequired) {
|
if (commitRequired) {
|
||||||
// int resp = OptionDialog.showOptionDialog(tool.getToolFrame(),
|
|
||||||
// "Parameter Commit Required",
|
|
||||||
// "Retyping a parameter requires all other parameters to be committed!\nContinue with retype?",
|
|
||||||
// "Continue");
|
|
||||||
// if (resp != OptionDialog.OPTION_ONE) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
exactSpot = null; // Don't try to split out if commit is required
|
exactSpot = null; // Don't try to split out if commit is required
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +169,7 @@ public class RetypeVariableAction extends AbstractDecompilerAction {
|
||||||
Msg.showError(this, null, "Parameter Commit Failed", e.getMessage());
|
Msg.showError(this, null, "Parameter Commit Failed", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HighFunctionDBUtil.updateDBVariable(var, null, dt, SourceType.USER_DEFINED);
|
HighFunctionDBUtil.updateDBVariable(var.getSymbol(), null, dt, SourceType.USER_DEFINED);
|
||||||
successfulMod = true;
|
successfulMod = true;
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
|
@ -298,7 +291,7 @@ public class RetypeVariableAction extends AbstractDecompilerAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < numParams; i++) {
|
for (int i = 0; i < numParams; i++) {
|
||||||
HighParam param = localSymbolMap.getParam(i);
|
MappedSymbol param = localSymbolMap.getParamSymbol(i);
|
||||||
if (param.getSlot() != i) {
|
if (param.getSlot() != i) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -350,11 +343,10 @@ public class RetypeVariableAction extends AbstractDecompilerAction {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (variable instanceof HighConstant) {
|
if (variable.getSymbol() == null) {
|
||||||
// getPopupMenuData().setMenuItemName("Retype Constant");
|
return false;
|
||||||
// return true;
|
|
||||||
}
|
}
|
||||||
else if (variable instanceof HighLocal) {
|
if (variable instanceof HighLocal) {
|
||||||
getPopupMenuData().setMenuItemName("Retype Variable");
|
getPopupMenuData().setMenuItemName("Retype Variable");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -412,7 +404,7 @@ public class RetypeVariableAction extends AbstractDecompilerAction {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
variable = RenameVariableAction.forgeHighVariable(addr, controller);
|
variable = RenameVariableAction.forgeHighVariable(addr, controller);
|
||||||
if (variable == null) {
|
if (variable == null || variable.getSymbol() == null || variable.getOffset() >= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,12 @@
|
||||||
package ghidra.program.model.pcode;
|
package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
|
import ghidra.util.exception.AssertException;
|
||||||
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
import ghidra.xml.XmlElement;
|
||||||
import ghidra.xml.XmlPullParser;
|
import ghidra.xml.XmlPullParser;
|
||||||
|
@ -26,53 +31,25 @@ import ghidra.xml.XmlPullParser;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DynamicSymbol extends HighSymbol {
|
public class DynamicSymbol extends HighSymbol {
|
||||||
public static class Entry {
|
protected long hash; // Hash encoding the specific Varnode
|
||||||
public final Address pcaddr;
|
|
||||||
public final long hash;
|
|
||||||
public final int format;
|
|
||||||
|
|
||||||
public Entry(Address addr,long h,int f) {
|
public DynamicSymbol(HighFunction func) { // For use with restoreXML
|
||||||
pcaddr = addr;
|
super(func);
|
||||||
hash = h;
|
|
||||||
format = f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Entry[] refs;
|
|
||||||
|
|
||||||
public DynamicSymbol() { // For use with restoreXML
|
|
||||||
refs = new Entry[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DynamicSymbol(long uniqueId, String nm, DataType tp, int size, HighFunction func,
|
public DynamicSymbol(long uniqueId, String nm, DataType tp, int size, HighFunction func,
|
||||||
Address addr, long hash, int format) {
|
Address addr, long hash) {
|
||||||
super(uniqueId, nm, tp, size, addr, func);
|
super(uniqueId, nm, tp, size, addr, func);
|
||||||
refs = new Entry[1];
|
this.hash = hash;
|
||||||
refs[0] = new Entry(addr,hash,format);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getHash() {
|
public long getHash() {
|
||||||
return refs[0].hash;
|
return hash;
|
||||||
}
|
|
||||||
|
|
||||||
public void addReference(Address addr,long hash,int format) {
|
|
||||||
Entry[] newrefs = new Entry[refs.length + 1];
|
|
||||||
for(int i=0;i<refs.length;++i) {
|
|
||||||
newrefs[i] = refs[i];
|
|
||||||
}
|
|
||||||
newrefs[refs.length] = new Entry(addr,hash,format);
|
|
||||||
refs = newrefs;
|
|
||||||
if (refs.length == 1)
|
|
||||||
{
|
|
||||||
pcaddr = addr; // Store first address as official pcaddr for symbol
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void buildHashXML(StringBuilder buf) {
|
protected void buildHashXML(StringBuilder buf) {
|
||||||
for (Entry ref : refs) {
|
buf.append("<hash val=\"0x").append(Long.toHexString(hash)).append("\"/>");
|
||||||
buf.append("<hash val=\"0x").append(Long.toHexString(ref.hash)).append("\"/>");
|
buildRangelistXML(buf, pcaddr);
|
||||||
buildRangelistXML(buf, ref.pcaddr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -88,25 +65,39 @@ public class DynamicSymbol extends HighSymbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
|
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
||||||
XmlElement symel = parser.start("symbol");
|
XmlElement symel = parser.start("symbol");
|
||||||
restoreSymbolXML(symel, func);
|
restoreSymbolXML(symel);
|
||||||
type = func.getDataTypeManager().readXMLDataType(parser);
|
type = function.getDataTypeManager().readXMLDataType(parser);
|
||||||
size = type.getLength();
|
size = type.getLength();
|
||||||
parser.end(symel);
|
parser.end(symel);
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
throw new PcodeXMLException("Invalid symbol 0-sized data-type: " + type.getName());
|
throw new PcodeXMLException("Invalid symbol 0-sized data-type: " + type.getName());
|
||||||
}
|
}
|
||||||
|
restoreEntryXML(parser);
|
||||||
while(parser.peek().isStart()) {
|
while(parser.peek().isStart()) {
|
||||||
long hash = 0;
|
parser.discardSubTree();
|
||||||
int format = 0;
|
}
|
||||||
XmlElement addrel = parser.start("hash");
|
}
|
||||||
hash = SpecXmlUtils.decodeLong(addrel.getAttribute("val"));
|
|
||||||
format = SpecXmlUtils.decodeInt(symel.getAttribute("format"));
|
@Override
|
||||||
parser.end(addrel);
|
protected void restoreEntryXML(XmlPullParser parser) throws PcodeXMLException {
|
||||||
Address addr = parseRangeList(parser);
|
XmlElement addrel = parser.start("hash");
|
||||||
addReference(addr,hash,format);
|
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("</symbol>\n");
|
res.append("</symbol>\n");
|
||||||
return res.toString();
|
return res.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build dynamic VariableStorage for a unique variable
|
||||||
|
* @param vn is the variable in the unique space
|
||||||
|
* @param high is the HighFunction containing the variable
|
||||||
|
* @return the dynamic VariableStorage
|
||||||
|
*/
|
||||||
|
public static VariableStorage buildDynamicStorage(Varnode vn, HighFunction high) {
|
||||||
|
DynamicHash dynamicHash = new DynamicHash(vn, high);
|
||||||
|
Program program = high.getFunction().getProgram();
|
||||||
|
long ourHash = dynamicHash.getHash();
|
||||||
|
try {
|
||||||
|
return new VariableStorage(program, AddressSpace.HASH_SPACE.getAddress(ourHash),
|
||||||
|
vn.getSize());
|
||||||
|
}
|
||||||
|
catch (InvalidInputException e) {
|
||||||
|
throw new AssertException("Unexpected exception", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,19 +33,20 @@ public class EquateSymbol extends DynamicSymbol {
|
||||||
private long value; // Value of the equate
|
private long value; // Value of the equate
|
||||||
private int convert; // Non-zero if this is a conversion equate
|
private int convert; // Non-zero if this is a conversion equate
|
||||||
|
|
||||||
public EquateSymbol() {
|
public EquateSymbol(HighFunction func) {
|
||||||
|
super(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EquateSymbol(long uniqueId, String nm, long val, HighFunction func, Address addr,
|
public EquateSymbol(long uniqueId, String nm, long val, HighFunction func, Address addr,
|
||||||
long hash, int format) {
|
long hash) {
|
||||||
super(uniqueId, nm, DataType.DEFAULT, 1, func, addr, hash, format);
|
super(uniqueId, nm, DataType.DEFAULT, 1, func, addr, hash);
|
||||||
value = val;
|
value = val;
|
||||||
convert = FORMAT_DEFAULT;
|
convert = FORMAT_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EquateSymbol(long uniqueId, int conv, long val, HighFunction func, Address addr,
|
public EquateSymbol(long uniqueId, int conv, long val, HighFunction func, Address addr,
|
||||||
long hash, int format) {
|
long hash) {
|
||||||
super(uniqueId, "", DataType.DEFAULT, 1, func, addr, hash, format);
|
super(uniqueId, "", DataType.DEFAULT, 1, func, addr, hash);
|
||||||
value = val;
|
value = val;
|
||||||
convert = conv;
|
convert = conv;
|
||||||
}
|
}
|
||||||
|
@ -53,9 +54,9 @@ public class EquateSymbol extends DynamicSymbol {
|
||||||
public long getValue() { return value; }
|
public long getValue() { return value; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
|
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
||||||
XmlElement symel = parser.start("equatesymbol");
|
XmlElement symel = parser.start("equatesymbol");
|
||||||
restoreSymbolXML(symel, func);
|
restoreSymbolXML(symel);
|
||||||
type = DataType.DEFAULT;
|
type = DataType.DEFAULT;
|
||||||
size = 1;
|
size = 1;
|
||||||
convert = FORMAT_DEFAULT;
|
convert = FORMAT_DEFAULT;
|
||||||
|
@ -84,15 +85,9 @@ public class EquateSymbol extends DynamicSymbol {
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
throw new PcodeXMLException("Invalid symbol 0-sized data-type: " + type.getName());
|
throw new PcodeXMLException("Invalid symbol 0-sized data-type: " + type.getName());
|
||||||
}
|
}
|
||||||
|
restoreEntryXML(parser);
|
||||||
while(parser.peek().isStart()) {
|
while(parser.peek().isStart()) {
|
||||||
long hash = 0;
|
parser.discardSubTree();
|
||||||
int format = 0;
|
|
||||||
XmlElement addrel = parser.start("hash");
|
|
||||||
hash = SpecXmlUtils.decodeLong(addrel.getAttribute("val"));
|
|
||||||
format = SpecXmlUtils.decodeInt(addrel.getAttribute("format"));
|
|
||||||
parser.end(addrel);
|
|
||||||
Address addr = parseRangeList(parser);
|
|
||||||
addReference(addr,hash,format);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -210,9 +210,9 @@ public class FunctionPrototype {
|
||||||
* @return the i'th HighParam to this function prototype or null
|
* @return the i'th HighParam to this function prototype or null
|
||||||
* if this prototype is not backed by a LocalSymbolMap
|
* if this prototype is not backed by a LocalSymbolMap
|
||||||
*/
|
*/
|
||||||
public HighParam getParam(int i) {
|
public HighSymbol getParam(int i) {
|
||||||
if (localsyms != null) {
|
if (localsyms != null) {
|
||||||
return localsyms.getParam(i);
|
return localsyms.getParamSymbol(i);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,10 @@ public class GlobalSymbolMap {
|
||||||
* @return the new HighSymbol or null
|
* @return the new HighSymbol or null
|
||||||
*/
|
*/
|
||||||
public HighCodeSymbol newSymbol(long id, Address addr, DataType dataType, int sz) {
|
public HighCodeSymbol newSymbol(long id, Address addr, DataType dataType, int sz) {
|
||||||
|
if (dataType == null) {
|
||||||
|
dataType = DataType.DEFAULT;
|
||||||
|
sz = 1;
|
||||||
|
}
|
||||||
HighCodeSymbol symbol = new HighCodeSymbol(id, addr, dataType, sz, func);
|
HighCodeSymbol symbol = new HighCodeSymbol(id, addr, dataType, sz, func);
|
||||||
insertSymbol(symbol, addr);
|
insertSymbol(symbol, addr);
|
||||||
return symbol;
|
return symbol;
|
||||||
|
|
|
@ -17,9 +17,13 @@ package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.database.symbol.CodeSymbol;
|
import ghidra.program.database.symbol.CodeSymbol;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressFactory;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.listing.Data;
|
import ghidra.program.model.listing.*;
|
||||||
|
import ghidra.program.model.symbol.Symbol;
|
||||||
import ghidra.program.model.symbol.SymbolUtilities;
|
import ghidra.program.model.symbol.SymbolUtilities;
|
||||||
|
import ghidra.util.exception.InvalidInputException;
|
||||||
|
import ghidra.xml.XmlElement;
|
||||||
import ghidra.xml.XmlPullParser;
|
import ghidra.xml.XmlPullParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,6 +33,7 @@ public class HighCodeSymbol extends HighSymbol {
|
||||||
|
|
||||||
private CodeSymbol symbol;
|
private CodeSymbol symbol;
|
||||||
private Data data;
|
private Data data;
|
||||||
|
private VariableStorage storage;
|
||||||
|
|
||||||
public HighCodeSymbol(CodeSymbol sym, DataType dataType, int sz, HighFunction func) {
|
public HighCodeSymbol(CodeSymbol sym, DataType dataType, int sz, HighFunction func) {
|
||||||
super(sym.getID(), sym.getName(), dataType, sz, null, func);
|
super(sym.getID(), sym.getName(), dataType, sz, null, func);
|
||||||
|
@ -43,6 +48,11 @@ public class HighCodeSymbol extends HighSymbol {
|
||||||
data = func.getFunction().getProgram().getListing().getDataAt(addr);
|
data = func.getFunction().getProgram().getListing().getDataAt(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGlobal() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public CodeSymbol getCodeSymbol() {
|
public CodeSymbol getCodeSymbol() {
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
@ -57,6 +67,26 @@ public class HighCodeSymbol extends HighSymbol {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VariableStorage getStorage() {
|
||||||
|
if (storage == null) {
|
||||||
|
Data dataObj = getData();
|
||||||
|
if (dataObj != null) {
|
||||||
|
try {
|
||||||
|
storage = new VariableStorage(function.getFunction().getProgram(),
|
||||||
|
dataObj.getAddress(), dataObj.getLength());
|
||||||
|
}
|
||||||
|
catch (InvalidInputException e) {
|
||||||
|
storage = VariableStorage.UNASSIGNED_STORAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
storage = VariableStorage.UNASSIGNED_STORAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return storage;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String buildXML() {
|
public String buildXML() {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
@ -64,8 +94,37 @@ public class HighCodeSymbol extends HighSymbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
|
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
||||||
// TODO Auto-generated method stub
|
XmlElement symel = parser.start("symbol");
|
||||||
|
restoreSymbolXML(symel);
|
||||||
|
Symbol tmpSymbol = function.getFunction().getProgram().getSymbolTable().getSymbol(getId());
|
||||||
|
if (tmpSymbol instanceof CodeSymbol) {
|
||||||
|
symbol = (CodeSymbol) tmpSymbol;
|
||||||
|
}
|
||||||
|
type = function.getDataTypeManager().readXMLDataType(parser);
|
||||||
|
size = type.getLength();
|
||||||
|
parser.end(symel);
|
||||||
|
restoreEntryXML(parser);
|
||||||
|
while (parser.peek().isStart()) {
|
||||||
|
parser.discardSubTree();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void restoreEntryXML(XmlPullParser parser) throws PcodeXMLException {
|
||||||
|
AddressFactory addrFactory = function.getAddressFactory();
|
||||||
|
|
||||||
|
XmlElement addrel = parser.start("addr");
|
||||||
|
int sz = type.getLength();
|
||||||
|
if (sz == 0) {
|
||||||
|
throw new PcodeXMLException("Invalid symbol 0-sized data-type: " + type.getName());
|
||||||
|
}
|
||||||
|
Address varAddr = Varnode.readXMLAddress(addrel, addrFactory);
|
||||||
|
parser.end(addrel);
|
||||||
|
pcaddr = parseRangeList(parser);
|
||||||
|
if (symbol == null) {
|
||||||
|
Program program = function.getFunction().getProgram();
|
||||||
|
data = program.getListing().getDataAt(varAddr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,11 @@ package ghidra.program.model.pcode;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.AbstractIntegerDataType;
|
import ghidra.program.model.data.AbstractIntegerDataType;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
|
import ghidra.xml.XmlElement;
|
||||||
|
import ghidra.xml.XmlPullParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -30,6 +34,14 @@ public class HighConstant extends HighVariable {
|
||||||
private DynamicSymbol symbol;
|
private DynamicSymbol symbol;
|
||||||
private Address pcaddr; // null or Address of PcodeOp which defines the representative
|
private Address pcaddr; // null or Address of PcodeOp which defines the representative
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for use with restoreXml
|
||||||
|
* @param func is the HighFunction this constant belongs to
|
||||||
|
*/
|
||||||
|
public HighConstant(HighFunction func) {
|
||||||
|
super(func);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a constant NOT associated with a symbol
|
* Construct a constant NOT associated with a symbol
|
||||||
* @param name name of variable
|
* @param name name of variable
|
||||||
|
@ -43,19 +55,6 @@ public class HighConstant extends HighVariable {
|
||||||
pcaddr = pc;
|
pcaddr = pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct constant associated with a dynamic symbol
|
|
||||||
* @param name name of variable
|
|
||||||
* @param type data type of variable
|
|
||||||
* @param vn constant varnode
|
|
||||||
* @param pc code unit address where constant is used
|
|
||||||
* @param sym associated dynamic symbol
|
|
||||||
*/
|
|
||||||
public HighConstant(String name, DataType type, Varnode vn, Address pc, DynamicSymbol sym) {
|
|
||||||
this(name, type, vn, pc, sym.getHighFunction());
|
|
||||||
symbol = sym;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HighSymbol getSymbol() {
|
public HighSymbol getSymbol() {
|
||||||
return symbol;
|
return symbol;
|
||||||
|
@ -88,4 +87,36 @@ public class HighConstant extends HighVariable {
|
||||||
return new Scalar(getSize() * 8, value, signed);
|
return new Scalar(getSize() * 8, value, signed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
||||||
|
XmlElement el = parser.start("high");
|
||||||
|
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
||||||
|
restoreInstances(parser, el);
|
||||||
|
pcaddr = function.getPCAddress(represent);
|
||||||
|
if (symref != 0) {
|
||||||
|
HighSymbol sym = function.getLocalSymbolMap().getSymbol(symref);
|
||||||
|
if (sym == null) {
|
||||||
|
sym = function.getGlobalSymbolMap().getSymbol(symref);
|
||||||
|
}
|
||||||
|
if (sym instanceof DynamicSymbol) {
|
||||||
|
symbol = (DynamicSymbol) sym;
|
||||||
|
name = sym.getName();
|
||||||
|
sym.setHighVariable(this);
|
||||||
|
}
|
||||||
|
else if (sym == null) {
|
||||||
|
GlobalSymbolMap globalMap = function.getGlobalSymbolMap();
|
||||||
|
Program program = function.getFunction().getProgram();
|
||||||
|
sym = globalMap.populateSymbol(symref, null, -1);
|
||||||
|
if (sym == null) {
|
||||||
|
PcodeOp op = ((VarnodeAST) represent).getLoneDescend();
|
||||||
|
Address addr = HighFunctionDBUtil.getSpacebaseReferenceAddress(program, op);
|
||||||
|
if (addr != null) {
|
||||||
|
sym = globalMap.newSymbol(symref, addr, DataType.DEFAULT, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parser.end(el);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.xml.sax.*;
|
||||||
import ghidra.program.database.symbol.CodeSymbol;
|
import ghidra.program.database.symbol.CodeSymbol;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressOutOfBoundsException;
|
import ghidra.program.model.address.AddressOutOfBoundsException;
|
||||||
import ghidra.program.model.data.DataType;
|
|
||||||
import ghidra.program.model.lang.CompilerSpec;
|
import ghidra.program.model.lang.CompilerSpec;
|
||||||
import ghidra.program.model.lang.Language;
|
import ghidra.program.model.lang.Language;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -209,41 +208,29 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readHighXML(XmlPullParser parser) throws PcodeXMLException {
|
private void readHighXML(XmlPullParser parser) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("high");
|
XmlElement el = parser.peek();
|
||||||
String classstring = el.getAttribute("class");
|
String classstring = el.getAttribute("class");
|
||||||
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
HighVariable var;
|
||||||
int repref = SpecXmlUtils.decodeInt(el.getAttribute("repref"));
|
switch (classstring.charAt(0)) {
|
||||||
Varnode rep = getRef(repref);
|
case 'o':
|
||||||
if (rep == null) {
|
var = new HighOther(this);
|
||||||
throw new PcodeXMLException("Undefined varnode reference");
|
break;
|
||||||
|
case 'g':
|
||||||
|
var = new HighGlobal(this);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
var = new HighLocal(this);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
var = new HighParam(this);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
var = new HighConstant(this);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new PcodeXMLException("Unknown HighVariable class string: " + classstring);
|
||||||
}
|
}
|
||||||
|
var.restoreXml(parser);
|
||||||
DataType type = null;
|
|
||||||
|
|
||||||
ArrayList<Varnode> vnlist = new ArrayList<Varnode>();
|
|
||||||
int sz = -1;
|
|
||||||
if (parser.peek().isStart()) {
|
|
||||||
type = getDataTypeManager().readXMLDataType(parser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == null) {
|
|
||||||
throw new PcodeXMLException("Missing <type> for HighVariable");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: I'm not sure the decompiler's type size is preserved
|
|
||||||
// by the conversion to a GHIDRA type
|
|
||||||
sz = type.getLength();
|
|
||||||
|
|
||||||
while (parser.peek().isStart()) {
|
|
||||||
Varnode vn = Varnode.readXML(parser, this);
|
|
||||||
vnlist.add(vn);
|
|
||||||
}
|
|
||||||
Varnode[] vnarray = new Varnode[vnlist.size()];
|
|
||||||
vnlist.toArray(vnarray);
|
|
||||||
// VARDO: does rep varnode size differ from type length ?
|
|
||||||
newHigh(symref, type, sz, vnarray, rep, classstring);
|
|
||||||
|
|
||||||
parser.end(el);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readHighlistXML(XmlPullParser parser) throws PcodeXMLException {
|
private void readHighlistXML(XmlPullParser parser) throws PcodeXMLException {
|
||||||
|
@ -329,97 +316,7 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||||
parser.end(el);
|
parser.end(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HighVariable newHigh(long symref, DataType tp, int sz, Varnode[] inst, Varnode rep,
|
protected Address getPCAddress(Varnode rep) {
|
||||||
String classstring) throws PcodeXMLException {
|
|
||||||
HighVariable var = null;
|
|
||||||
if (classstring.equals("local")) {
|
|
||||||
HighSymbol sym = null;
|
|
||||||
if (symref != 0) {
|
|
||||||
sym = localSymbols.getSymbol(symref);
|
|
||||||
}
|
|
||||||
if (sym != null) {
|
|
||||||
var = sym.getHighVariable();
|
|
||||||
}
|
|
||||||
if (var == null) {
|
|
||||||
if (sym instanceof DynamicSymbol) {
|
|
||||||
// establish HighLocal for DynamicSymbol
|
|
||||||
var = new HighLocal(tp, rep, inst, sym.getPCAddress(), sym);
|
|
||||||
sym.setHighVariable(var);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// The variable may be a partial, in which case
|
|
||||||
// we treat it as special
|
|
||||||
var = new HighOther(tp, rep, inst, getPCAddress(rep), this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (classstring.equals("constant")) {
|
|
||||||
HighSymbol sym = null;
|
|
||||||
if (symref != 0) {
|
|
||||||
sym = localSymbols.getSymbol(symref);
|
|
||||||
if (sym == null) {
|
|
||||||
sym = globalSymbols.getSymbol(symref);
|
|
||||||
}
|
|
||||||
if (sym instanceof DynamicSymbol) {
|
|
||||||
var = sym.getHighVariable();
|
|
||||||
var = new HighConstant(sym.getName(), tp, rep, getPCAddress(rep),
|
|
||||||
(DynamicSymbol) sym);
|
|
||||||
sym.setHighVariable(var);
|
|
||||||
}
|
|
||||||
else if (sym == null) {
|
|
||||||
sym = globalSymbols.populateSymbol(symref, null, -1);
|
|
||||||
if (sym == null) {
|
|
||||||
PcodeOp op = ((VarnodeAST) rep).getLoneDescend();
|
|
||||||
Address addr =
|
|
||||||
HighFunctionDBUtil.getSpacebaseReferenceAddress(func.getProgram(), op);
|
|
||||||
if (addr != null) {
|
|
||||||
sym = globalSymbols.newSymbol(symref, addr, DataType.DEFAULT, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (var == null) {
|
|
||||||
var = new HighConstant(null, tp, rep, getPCAddress(rep), this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (classstring.equals("global")) {
|
|
||||||
HighCodeSymbol sym = null;
|
|
||||||
if (symref != 0) {
|
|
||||||
sym = globalSymbols.getSymbol(symref);
|
|
||||||
}
|
|
||||||
if (sym == null) {
|
|
||||||
sym = globalSymbols.populateSymbol(symref, tp, sz);
|
|
||||||
if (sym == null) {
|
|
||||||
sym = globalSymbols.newSymbol(symref, rep.getAddress(), tp, sz);
|
|
||||||
if (sym == null) {
|
|
||||||
throw new PcodeXMLException(
|
|
||||||
"Bad global storage: " + rep.getAddress().toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var = new HighGlobal(sym, rep, inst);
|
|
||||||
sym.setHighVariable(var);
|
|
||||||
}
|
|
||||||
else if (classstring.equals("other")) {
|
|
||||||
// TODO: How do these compare with local ??
|
|
||||||
var = new HighOther(tp, rep, inst, getPCAddress(rep), this);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new PcodeXMLException("Bad class string: " + classstring);
|
|
||||||
}
|
|
||||||
if (rep.getSize() == var.getSize()) {
|
|
||||||
var.attachInstances(inst, rep);
|
|
||||||
}
|
|
||||||
else { // Make sure varnodes are linked to HighVariable even if not formal instances, why do we do this???
|
|
||||||
for (Varnode element : inst) {
|
|
||||||
((VarnodeAST) element).setHigh(var);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var.setHighOnInstances();
|
|
||||||
return var;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Address getPCAddress(Varnode rep) {
|
|
||||||
Address pcaddr = null;
|
Address pcaddr = null;
|
||||||
if (!rep.isAddrTied()) {
|
if (!rep.isAddrTied()) {
|
||||||
pcaddr = rep.getPCAddress();
|
pcaddr = rep.getPCAddress();
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class HighFunctionDBUtil {
|
||||||
List<Parameter> params = new ArrayList<Parameter>();
|
List<Parameter> params = new ArrayList<Parameter>();
|
||||||
int paramCnt = symbolMap.getNumParams();
|
int paramCnt = symbolMap.getNumParams();
|
||||||
for (int i = 0; i < paramCnt; ++i) {
|
for (int i = 0; i < paramCnt; ++i) {
|
||||||
HighParam param = symbolMap.getParam(i);
|
HighSymbol param = symbolMap.getParamSymbol(i);
|
||||||
String name = param.getName();
|
String name = param.getName();
|
||||||
DataType dataType;
|
DataType dataType;
|
||||||
if (useDataTypes) {
|
if (useDataTypes) {
|
||||||
|
@ -201,23 +201,20 @@ public class HighFunctionDBUtil {
|
||||||
Iterator<HighSymbol> iter = highFunction.getLocalSymbolMap().getSymbols();
|
Iterator<HighSymbol> iter = highFunction.getLocalSymbolMap().getSymbols();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
HighSymbol sym = iter.next();
|
HighSymbol sym = iter.next();
|
||||||
HighVariable high = sym.getHighVariable();
|
if (sym.isParameter() || sym.isGlobal()) {
|
||||||
if ((high instanceof HighParam) || !(high instanceof HighLocal)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
String name = sym.getName();
|
||||||
HighLocal local = (HighLocal) high;
|
|
||||||
String name = local.getName();
|
|
||||||
try {
|
try {
|
||||||
Variable var = clearConflictingLocalVariables(local);
|
Variable var = clearConflictingLocalVariables(sym);
|
||||||
if (var == null) {
|
if (var == null) {
|
||||||
var = createLocalVariable(local, null, null, source);
|
var = createLocalVariable(sym, null, null, source);
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
var.setName(name, source);
|
var.setName(name, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var.setDataType(local.getDataType(), local.getStorage(), false, source);
|
var.setDataType(sym.getDataType(), sym.getStorage(), false, source);
|
||||||
var.setName(name, source);
|
var.setName(name, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,28 +226,29 @@ public class HighFunctionDBUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a local DB variable with a default name
|
* Create a local DB variable with a default name. Storage and data-type for the variable
|
||||||
* @param local
|
* can be provided explicitly, or they can be taken from a decompiler symbol.
|
||||||
* @param dt data type or null to use local data type defined by local high variable
|
* @param symbol is the decompiler symbol
|
||||||
* @param storage storage or null to use storage defined by local high variable
|
* @param dt is the given data-type or null (to use the symbol's data-type)
|
||||||
* @param source
|
* @param storage is the given storage or null (to use the symbol's storage)
|
||||||
* @return
|
* @param source is the desired SourceType of the new variable
|
||||||
* @throws InvalidInputException
|
* @return the new local variable
|
||||||
* @throws DuplicateNameException
|
* @throws InvalidInputException is a valid variable can't be created
|
||||||
*/
|
*/
|
||||||
private static Variable createLocalVariable(HighLocal local, DataType dt,
|
private static Variable createLocalVariable(HighSymbol symbol, DataType dt,
|
||||||
VariableStorage storage, SourceType source) throws InvalidInputException {
|
VariableStorage storage, SourceType source) throws InvalidInputException {
|
||||||
Function function = local.getHighFunction().getFunction();
|
Function function = symbol.getHighFunction().getFunction();
|
||||||
Program program = function.getProgram();
|
Program program = function.getProgram();
|
||||||
if (storage == null || storage.isUniqueStorage()) {
|
if (storage == null || storage.isUniqueStorage()) {
|
||||||
storage = local.getStorage();
|
storage = symbol.getStorage();
|
||||||
}
|
}
|
||||||
if (dt == null) {
|
if (dt == null) {
|
||||||
dt = local.getDataType();
|
dt = symbol.getDataType();
|
||||||
}
|
}
|
||||||
Variable var = new LocalVariableImpl(null, local.getFirstUseOffset(), dt, storage, program);
|
Variable var =
|
||||||
|
new LocalVariableImpl(null, symbol.getFirstUseOffset(), dt, storage, program);
|
||||||
try {
|
try {
|
||||||
var = function.addLocalVariable(var, SourceType.ANALYSIS);
|
var = function.addLocalVariable(var, source);
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
throw new AssertException("Unexpected exception with default name", e);
|
throw new AssertException("Unexpected exception with default name", e);
|
||||||
|
@ -258,7 +256,7 @@ public class HighFunctionDBUtil {
|
||||||
|
|
||||||
Register reg = var.getRegister();
|
Register reg = var.getRegister();
|
||||||
if (reg != null) {
|
if (reg != null) {
|
||||||
program.getReferenceManager().addRegisterReference(local.getPCAddress(), -1, reg,
|
program.getReferenceManager().addRegisterReference(symbol.getPCAddress(), -1, reg,
|
||||||
RefType.WRITE, source);
|
RefType.WRITE, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,13 +280,15 @@ public class HighFunctionDBUtil {
|
||||||
long hash = var.getFirstStorageVarnode().getOffset();
|
long hash = var.getFirstStorageVarnode().getOffset();
|
||||||
Iterator<HighSymbol> symbols = highFunction.getLocalSymbolMap().getSymbols();
|
Iterator<HighSymbol> symbols = highFunction.getLocalSymbolMap().getSymbols();
|
||||||
while (symbols.hasNext()) {
|
while (symbols.hasNext()) {
|
||||||
HighVariable high = symbols.next().getHighVariable();
|
HighSymbol symbol = symbols.next();
|
||||||
if (!(high instanceof HighLocal)) {
|
if (!(symbol instanceof DynamicSymbol)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Note: assumes there is only one hash method used for unique locals
|
// Note: assumes there is only one hash method used for unique locals
|
||||||
if (((HighLocal) high).buildDynamicHash() == hash) {
|
if (((DynamicSymbol) symbol).getHash() == hash) {
|
||||||
return true;
|
if (symbol.getHighVariable() != null) {
|
||||||
|
return true; // Hash successfully attached to a variable
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -301,25 +301,22 @@ public class HighFunctionDBUtil {
|
||||||
* exists within the function at the same first-use-offset.
|
* exists within the function at the same first-use-offset.
|
||||||
* @return existing variable with identical storage and first-use offset or null
|
* @return existing variable with identical storage and first-use offset or null
|
||||||
*/
|
*/
|
||||||
private static Variable clearConflictingLocalVariables(HighLocal local) {
|
private static Variable clearConflictingLocalVariables(HighSymbol local) {
|
||||||
|
|
||||||
if (local instanceof HighParam) {
|
if (local instanceof MappedSymbol) {
|
||||||
throw new IllegalArgumentException();
|
if (((MappedSymbol) local).getSlot() >= 0) { // Don't clear parameters
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HighFunction highFunction = local.getHighFunction();
|
HighFunction highFunction = local.getHighFunction();
|
||||||
Function func = highFunction.getFunction();
|
Function func = highFunction.getFunction();
|
||||||
|
|
||||||
HighSymbol symbol = local.getSymbol();
|
|
||||||
VariableStorage storage = local.getStorage();
|
VariableStorage storage = local.getStorage();
|
||||||
int firstUseOffset = local.getFirstUseOffset();
|
int firstUseOffset = local.getFirstUseOffset();
|
||||||
if (symbol instanceof DynamicSymbol || storage.isUniqueStorage()) {
|
if (local instanceof DynamicSymbol) {
|
||||||
|
|
||||||
if (!(symbol instanceof DynamicSymbol)) {
|
DynamicSymbol dynamicSym = (DynamicSymbol) local;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicSymbol dynamicSym = (DynamicSymbol) symbol;
|
|
||||||
for (Variable ul : func.getLocalVariables(VariableFilter.UNIQUE_VARIABLE_FILTER)) {
|
for (Variable ul : func.getLocalVariables(VariableFilter.UNIQUE_VARIABLE_FILTER)) {
|
||||||
// Note: assumes there is only one hash method used for unique locals
|
// Note: assumes there is only one hash method used for unique locals
|
||||||
if (ul.getFirstStorageVarnode().getOffset() == dynamicSym.getHash()) {
|
if (ul.getFirstStorageVarnode().getOffset() == dynamicSym.getHash()) {
|
||||||
|
@ -352,15 +349,15 @@ public class HighFunctionDBUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get database parameter which corresponds to HighParam, where we anticipate that
|
* Get database parameter which corresponds to the given symbol, where we anticipate that
|
||||||
* the parameter will be modified to match the HighParam. The entire prototype is
|
* the parameter will be modified to match the symbol. The entire prototype is
|
||||||
* committed to the database if necessary. An exception is thrown if a modifiable parameter
|
* committed to the database if necessary. An exception is thrown if a modifiable parameter
|
||||||
* can't be found/created.
|
* can't be found/created.
|
||||||
* @param param is the HighParam describing the desired function parameter
|
* @param param is the HighSymbol describing the desired function parameter
|
||||||
* @return the matching parameter that can be modified
|
* @return the matching parameter that can be modified
|
||||||
* @throws InvalidInputException if the desired parameter cannot be modified
|
* @throws InvalidInputException if the desired parameter cannot be modified
|
||||||
*/
|
*/
|
||||||
private static Parameter getDatabaseParameter(HighParam param) throws InvalidInputException {
|
private static Parameter getDatabaseParameter(MappedSymbol param) throws InvalidInputException {
|
||||||
|
|
||||||
HighFunction highFunction = param.getHighFunction();
|
HighFunction highFunction = param.getHighFunction();
|
||||||
Function function = highFunction.getFunction();
|
Function function = highFunction.getFunction();
|
||||||
|
@ -392,10 +389,9 @@ public class HighFunctionDBUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retype the specified variable in the database. All parameters may be flushed
|
* Rename and/or retype the specified variable in the database. All parameters may be flushed
|
||||||
* to the database if typed parameter inconsistency detected.
|
* to the database if typed parameter inconsistency detected.
|
||||||
* Only variable types HighParam, HighLocal and HighGlobal are supported.
|
* @param variable is the symbol being updated
|
||||||
* @param variable
|
|
||||||
* @param name new variable name or null to use retain current variable name
|
* @param name new variable name or null to use retain current variable name
|
||||||
* @param dataType newly assigned data type or null to retain current variable datatype.
|
* @param dataType newly assigned data type or null to retain current variable datatype.
|
||||||
* Only a fixed-length data type may be specified. If size varies from the current size,
|
* Only a fixed-length data type may be specified. If size varies from the current size,
|
||||||
|
@ -407,7 +403,7 @@ public class HighFunctionDBUtil {
|
||||||
* variable/label within the function's namespace
|
* variable/label within the function's namespace
|
||||||
* @throws UnsupportedOperationException if unsupported variable type is specified
|
* @throws UnsupportedOperationException if unsupported variable type is specified
|
||||||
*/
|
*/
|
||||||
public static void updateDBVariable(HighVariable variable, String name, DataType dataType,
|
public static void updateDBVariable(HighSymbol variable, String name, DataType dataType,
|
||||||
SourceType source) throws InvalidInputException, DuplicateNameException {
|
SourceType source) throws InvalidInputException, DuplicateNameException {
|
||||||
|
|
||||||
HighFunction highFunction = variable.getHighFunction();
|
HighFunction highFunction = variable.getHighFunction();
|
||||||
|
@ -427,10 +423,11 @@ public class HighFunctionDBUtil {
|
||||||
|
|
||||||
boolean isRename = name != null;
|
boolean isRename = name != null;
|
||||||
|
|
||||||
if (variable instanceof HighParam) {
|
if (variable.isParameter()) {
|
||||||
HighParam param = (HighParam) variable;
|
MappedSymbol mappedSymbol = (MappedSymbol) variable;
|
||||||
Parameter dbParam = getDatabaseParameter(param);
|
|
||||||
VariableStorage storage = param.getStorage();
|
Parameter dbParam = getDatabaseParameter(mappedSymbol);
|
||||||
|
VariableStorage storage = mappedSymbol.getStorage();
|
||||||
if (dataType != null) {
|
if (dataType != null) {
|
||||||
if (resized && function.hasCustomVariableStorage()) {
|
if (resized && function.hasCustomVariableStorage()) {
|
||||||
VariableStorage newStorage =
|
VariableStorage newStorage =
|
||||||
|
@ -445,12 +442,20 @@ public class HighFunctionDBUtil {
|
||||||
dbParam.setName(name, source);
|
dbParam.setName(name, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (variable instanceof HighLocal) {
|
else if (!variable.isGlobal()) {
|
||||||
HighLocal local = (HighLocal) variable;
|
Variable var;
|
||||||
VariableStorage storage = local.getStorage();
|
VariableStorage storage;
|
||||||
|
HighVariable tmpHigh = variable.getHighVariable();
|
||||||
|
if (tmpHigh != null && tmpHigh.getRepresentative().isUnique()) {
|
||||||
|
storage =
|
||||||
|
DynamicSymbol.buildDynamicStorage(tmpHigh.getRepresentative(), highFunction);
|
||||||
|
var = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
storage = variable.getStorage();
|
||||||
|
var = clearConflictingLocalVariables(variable);
|
||||||
|
}
|
||||||
boolean usesHashStorage = storage.isHashStorage();
|
boolean usesHashStorage = storage.isHashStorage();
|
||||||
|
|
||||||
Variable var = clearConflictingLocalVariables(local);
|
|
||||||
if (dataType == null) {
|
if (dataType == null) {
|
||||||
if (var != null) {
|
if (var != null) {
|
||||||
dataType = var.getDataType(); // Use preexisting datatype if it fits in desired storage
|
dataType = var.getDataType(); // Use preexisting datatype if it fits in desired storage
|
||||||
|
@ -463,21 +468,21 @@ public class HighFunctionDBUtil {
|
||||||
if (resized) {
|
if (resized) {
|
||||||
if (usesHashStorage) {
|
if (usesHashStorage) {
|
||||||
throw new InvalidInputException(
|
throw new InvalidInputException(
|
||||||
"Variable size (" + local.getSize() + ") may not be changed: type '" +
|
"Variable size (" + variable.getSize() + ") may not be changed: type '" +
|
||||||
dataType.getName() + "' length is " + dataType.getLength());
|
dataType.getName() + "' length is " + dataType.getLength());
|
||||||
}
|
}
|
||||||
storage = VariableUtilities.resizeStorage(storage, dataType, true, function);
|
storage = VariableUtilities.resizeStorage(storage, dataType, true, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (var == null) {
|
if (var == null) {
|
||||||
var = createLocalVariable(local, dataType, storage, source);
|
var = createLocalVariable(variable, dataType, storage, source);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// fixup reused variable
|
// fixup reused variable
|
||||||
var.setDataType(dataType, storage, true, source);
|
var.setDataType(dataType, storage, true, source);
|
||||||
if (name == null) {
|
}
|
||||||
name = local.getName(); // must update name if not specified
|
if (name == null) {
|
||||||
}
|
name = variable.getName(); // must update name if not specified
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// must set/correct name
|
// must set/correct name
|
||||||
|
@ -499,7 +504,7 @@ public class HighFunctionDBUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (variable instanceof HighGlobal) {
|
else { // A global symbol
|
||||||
|
|
||||||
VariableStorage storage = variable.getStorage();
|
VariableStorage storage = variable.getStorage();
|
||||||
if (!storage.isMemoryStorage()) {
|
if (!storage.isMemoryStorage()) {
|
||||||
|
@ -507,21 +512,20 @@ public class HighFunctionDBUtil {
|
||||||
"Database supports global memory variables only");
|
"Database supports global memory variables only");
|
||||||
}
|
}
|
||||||
|
|
||||||
HighGlobal global = (HighGlobal) variable;
|
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
name = global.getName();
|
name = variable.getName();
|
||||||
if (name != null && SymbolUtilities.isDynamicSymbolPattern(name, true)) {
|
if (name != null && SymbolUtilities.isDynamicSymbolPattern(name, true)) {
|
||||||
name = null;
|
name = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataType != null) {
|
if (dataType != null) {
|
||||||
setGlobalDataType(global, dataType);
|
setGlobalDataType(variable, dataType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
try {
|
try {
|
||||||
setGlobalName((HighGlobal) variable, variable.getName(), source);
|
setGlobalName(variable, variable.getName(), source);
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
if (isRename) {
|
if (isRename) {
|
||||||
|
@ -530,13 +534,9 @@ public class HighFunctionDBUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Database support not provided for " + variable.getClass().getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setGlobalName(HighGlobal global, String name, SourceType source)
|
private static void setGlobalName(HighSymbol global, String name, SourceType source)
|
||||||
throws DuplicateNameException, InvalidInputException {
|
throws DuplicateNameException, InvalidInputException {
|
||||||
Program program = global.getHighFunction().getFunction().getProgram();
|
Program program = global.getHighFunction().getFunction().getProgram();
|
||||||
VariableStorage storage = global.getStorage();
|
VariableStorage storage = global.getStorage();
|
||||||
|
@ -554,7 +554,7 @@ public class HighFunctionDBUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Data setGlobalDataType(HighGlobal global, DataType dt)
|
private static Data setGlobalDataType(HighSymbol global, DataType dt)
|
||||||
throws InvalidInputException {
|
throws InvalidInputException {
|
||||||
Program program = global.getHighFunction().getFunction().getProgram();
|
Program program = global.getHighFunction().getFunction().getProgram();
|
||||||
VariableStorage storage = global.getStorage();
|
VariableStorage storage = global.getStorage();
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.pcode;
|
package ghidra.program.model.pcode;
|
||||||
|
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
|
import ghidra.xml.XmlElement;
|
||||||
|
import ghidra.xml.XmlPullParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -24,6 +30,14 @@ public class HighGlobal extends HighVariable {
|
||||||
|
|
||||||
private HighCodeSymbol symbol;
|
private HighCodeSymbol symbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for use with restoreXml
|
||||||
|
* @param high is the HighFunction this global is accessed by
|
||||||
|
*/
|
||||||
|
public HighGlobal(HighFunction high) {
|
||||||
|
super(high);
|
||||||
|
}
|
||||||
|
|
||||||
public HighGlobal(HighCodeSymbol sym, Varnode vn, Varnode[] inst) {
|
public HighGlobal(HighCodeSymbol sym, Varnode vn, Varnode[] inst) {
|
||||||
super(sym.getName(), sym.getDataType(), vn, inst, sym.getHighFunction());
|
super(sym.getName(), sym.getDataType(), vn, inst, sym.getHighFunction());
|
||||||
symbol = sym;
|
symbol = sym;
|
||||||
|
@ -33,4 +47,50 @@ public class HighGlobal extends HighVariable {
|
||||||
public HighSymbol getSymbol() {
|
public HighSymbol getSymbol() {
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
||||||
|
XmlElement el = parser.start("high");
|
||||||
|
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
||||||
|
String attrString = el.getAttribute("offset");
|
||||||
|
offset = -1;
|
||||||
|
if (attrString != null) {
|
||||||
|
offset = SpecXmlUtils.decodeInt(attrString);
|
||||||
|
}
|
||||||
|
restoreInstances(parser, el);
|
||||||
|
if (symref == 0) {
|
||||||
|
throw new PcodeXMLException("Missing symref attribute in <high> tag");
|
||||||
|
}
|
||||||
|
symbol = function.getGlobalSymbolMap().getSymbol(symref);
|
||||||
|
if (symbol == null) { // If we don't already have symbol, synthesize it
|
||||||
|
DataType symbolType;
|
||||||
|
int symbolSize;
|
||||||
|
if (offset < 0) { // Variable type and size matches symbol
|
||||||
|
symbolType = type;
|
||||||
|
symbolSize = getSize();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
symbolType = null;
|
||||||
|
symbolSize = -1;
|
||||||
|
}
|
||||||
|
GlobalSymbolMap globalMap = function.getGlobalSymbolMap();
|
||||||
|
symbol = globalMap.populateSymbol(symref, symbolType, symbolSize);
|
||||||
|
if (symbol == null) {
|
||||||
|
Address addr = represent.getAddress();
|
||||||
|
if (offset > 0) {
|
||||||
|
addr = addr.subtract(offset);
|
||||||
|
}
|
||||||
|
symbol = globalMap.newSymbol(symref, addr, symbolType, symbolSize);
|
||||||
|
if (symbol == null) {
|
||||||
|
throw new PcodeXMLException("Bad global storage: " + addr.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (offset < 0) {
|
||||||
|
name = symbol.getName();
|
||||||
|
}
|
||||||
|
symbol.setHighVariable(this);
|
||||||
|
|
||||||
|
parser.end(el);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,18 +16,23 @@
|
||||||
package ghidra.program.model.pcode;
|
package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSpace;
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.program.model.listing.VariableStorage;
|
import ghidra.xml.XmlElement;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.xml.XmlPullParser;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
|
||||||
|
|
||||||
public class HighLocal extends HighVariable {
|
public class HighLocal extends HighVariable {
|
||||||
|
|
||||||
private Address pcaddr; // null or Address of PcodeOp which defines the representative
|
private Address pcaddr; // null or Address of PcodeOp which defines the representative
|
||||||
private HighSymbol symbol;
|
private HighSymbol symbol;
|
||||||
private long hash = 0; // 60-bit hash value, 0 indicates not-yet-computed or not-applicable
|
|
||||||
|
/**
|
||||||
|
* Constructor for use with restoreXml
|
||||||
|
* @param high is the HighFunction containing this local variable
|
||||||
|
*/
|
||||||
|
public HighLocal(HighFunction high) {
|
||||||
|
super(high);
|
||||||
|
}
|
||||||
|
|
||||||
public HighLocal(DataType type, Varnode vn, Varnode[] inst, Address pc, HighSymbol sym) {
|
public HighLocal(DataType type, Varnode vn, Varnode[] inst, Address pc, HighSymbol sym) {
|
||||||
super(sym.getName(), type, vn, inst, sym.getHighFunction());
|
super(sym.getName(), type, vn, inst, sym.getHighFunction());
|
||||||
|
@ -47,51 +52,30 @@ public class HighLocal extends HighVariable {
|
||||||
return pcaddr;
|
return pcaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getFirstUseOffset() {
|
|
||||||
if (pcaddr == null || getRepresentative().getAddress().isStackAddress()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (int) pcaddr.subtract(getHighFunction().getFunction().getEntryPoint());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VariableStorage getStorage() {
|
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
||||||
|
XmlElement el = parser.start("high");
|
||||||
Program program = getHighFunction().getFunction().getProgram();
|
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
||||||
Varnode represent = getRepresentative();
|
offset = -1;
|
||||||
|
String attrString = el.getAttribute("offset");
|
||||||
if (symbol instanceof DynamicSymbol || represent.isUnique()) {
|
if (attrString != null) {
|
||||||
long ourHash = buildDynamicHash();
|
offset = SpecXmlUtils.decodeInt(attrString);
|
||||||
try {
|
|
||||||
return new VariableStorage(program, AddressSpace.HASH_SPACE.getAddress(ourHash),
|
|
||||||
represent.getSize());
|
|
||||||
}
|
|
||||||
catch (InvalidInputException e) {
|
|
||||||
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();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
name = "UNNAMED";
|
||||||
|
}
|
||||||
|
pcaddr = symbol.getPCAddress();
|
||||||
|
symbol.setHighVariable(this);
|
||||||
|
|
||||||
if (symbol instanceof MappedSymbol) {
|
parser.end(el);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@ package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
|
import ghidra.xml.XmlElement;
|
||||||
|
import ghidra.xml.XmlPullParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -26,8 +29,16 @@ import ghidra.program.model.data.DataType;
|
||||||
*/
|
*/
|
||||||
public class HighOther extends HighVariable {
|
public class HighOther extends HighVariable {
|
||||||
|
|
||||||
private DynamicSymbol symbol;
|
|
||||||
private Address pcaddr; // Address of PcodeOp which defines the representative
|
private Address pcaddr; // Address of PcodeOp which defines the representative
|
||||||
|
private HighSymbol symbol; // Possibly a dynamic global symbol
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for use with restoreXml
|
||||||
|
* @param high is the HighFunction containing the variable
|
||||||
|
*/
|
||||||
|
public HighOther(HighFunction high) {
|
||||||
|
super(high);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a unique high NOT associated with a symbol
|
* Construct a unique high NOT associated with a symbol
|
||||||
|
@ -42,14 +53,6 @@ public class HighOther extends HighVariable {
|
||||||
pcaddr = pc;
|
pcaddr = pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return associated dynamic symbol or null
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DynamicSymbol getSymbol() {
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return instruction address the variable comes into scope within the function
|
* @return instruction address the variable comes into scope within the function
|
||||||
*/
|
*/
|
||||||
|
@ -57,4 +60,31 @@ public class HighOther extends HighVariable {
|
||||||
return pcaddr;
|
return pcaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HighSymbol getSymbol() {
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
||||||
|
XmlElement el = parser.start("high");
|
||||||
|
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
||||||
|
offset = -1;
|
||||||
|
String attrString = el.getAttribute("offset");
|
||||||
|
restoreInstances(parser, el);
|
||||||
|
name = "UNNAMED";
|
||||||
|
pcaddr = function.getPCAddress(represent);
|
||||||
|
if (symref != 0) {
|
||||||
|
offset = -1;
|
||||||
|
if (attrString != null) {
|
||||||
|
offset = SpecXmlUtils.decodeInt(attrString);
|
||||||
|
}
|
||||||
|
symbol = function.getLocalSymbolMap().getSymbol(symref);
|
||||||
|
if (symbol != null && offset < 0) {
|
||||||
|
name = symbol.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.end(el);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.xml.XmlPullParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -26,6 +27,14 @@ import ghidra.program.model.data.DataType;
|
||||||
public class HighParam extends HighLocal {
|
public class HighParam extends HighLocal {
|
||||||
private int slot;
|
private int slot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for use with restoreXml
|
||||||
|
* @param high is the HighFunction containing this parameter
|
||||||
|
*/
|
||||||
|
public HighParam(HighFunction high) {
|
||||||
|
super(high);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tp data type of variable
|
* @param tp data type of variable
|
||||||
* @param rep is the representative input Varnode
|
* @param rep is the representative input Varnode
|
||||||
|
@ -46,8 +55,13 @@ public class HighParam extends HighLocal {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getFirstUseOffset() {
|
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
||||||
return 0;
|
super.restoreXml(parser);
|
||||||
|
slot = 0;
|
||||||
|
HighSymbol sym = getSymbol();
|
||||||
|
if (sym instanceof MappedSymbol) {
|
||||||
|
slot = ((MappedSymbol) sym).getSlot();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.program.model.pcode;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSpace;
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
import ghidra.xml.XmlElement;
|
||||||
import ghidra.xml.XmlPullParser;
|
import ghidra.xml.XmlPullParser;
|
||||||
|
@ -37,7 +38,8 @@ public abstract class HighSymbol {
|
||||||
|
|
||||||
private HighVariable highVariable;
|
private HighVariable highVariable;
|
||||||
|
|
||||||
public HighSymbol() { // For use with restoreXML
|
public HighSymbol(HighFunction func) { // For use with restoreXML
|
||||||
|
function = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HighSymbol(long uniqueId, String nm, DataType tp, int sz, Address pc,
|
public HighSymbol(long uniqueId, String nm, DataType tp, int sz, Address pc,
|
||||||
|
@ -80,6 +82,13 @@ public abstract class HighSymbol {
|
||||||
return pcaddr;
|
return pcaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected int getFirstUseOffset() {
|
||||||
|
if (pcaddr == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (int) pcaddr.subtract(getHighFunction().getFunction().getEntryPoint());
|
||||||
|
}
|
||||||
|
|
||||||
public HighFunction getHighFunction() {
|
public HighFunction getHighFunction() {
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
@ -108,13 +117,32 @@ public abstract class HighSymbol {
|
||||||
return readonly;
|
return readonly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this symbol a parameter for a function
|
||||||
|
* @return true if this is a parameter
|
||||||
|
*/
|
||||||
|
public boolean isParameter() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this symbol in the global scope or some other global namespace
|
||||||
|
* @return true if this is global
|
||||||
|
*/
|
||||||
|
public boolean isGlobal() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract VariableStorage getStorage();
|
||||||
|
|
||||||
public abstract String buildXML();
|
public abstract String buildXML();
|
||||||
|
|
||||||
public abstract void restoreXML(XmlPullParser parser, HighFunction func)
|
public abstract void restoreXML(XmlPullParser parser)
|
||||||
throws PcodeXMLException;
|
throws PcodeXMLException;
|
||||||
|
|
||||||
protected void restoreSymbolXML(XmlElement symel, HighFunction func) throws PcodeXMLException {
|
protected abstract void restoreEntryXML(XmlPullParser parser) throws PcodeXMLException;
|
||||||
function = func;
|
|
||||||
|
protected void restoreSymbolXML(XmlElement symel) throws PcodeXMLException {
|
||||||
id = SpecXmlUtils.decodeLong(symel.getAttribute("id"));
|
id = SpecXmlUtils.decodeLong(symel.getAttribute("id"));
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
throw new PcodeXMLException("missing unique symbol id");
|
throw new PcodeXMLException("missing unique symbol id");
|
||||||
|
|
|
@ -15,11 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.pcode;
|
package ghidra.program.model.pcode;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.program.model.listing.VariableStorage;
|
import ghidra.xml.XmlElement;
|
||||||
import ghidra.util.Msg;
|
import ghidra.xml.XmlPullParser;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -29,11 +30,20 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
*/
|
*/
|
||||||
public abstract class HighVariable {
|
public abstract class HighVariable {
|
||||||
|
|
||||||
private String name;
|
protected String name;
|
||||||
private DataType type;
|
protected DataType type;
|
||||||
private Varnode represent; // A representative varnode
|
protected Varnode represent; // A representative varnode
|
||||||
private Varnode[] instances; // Instances of this high-level variable
|
protected Varnode[] instances; // Instances of this high-level variable
|
||||||
private HighFunction function; // associated function
|
protected int offset = -1; // Offset (in bytes) into containing symbol (-1 indicates whole match)
|
||||||
|
protected HighFunction function; // associated function
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for use with restoreXml
|
||||||
|
* @param func is the HighFunction this variable belongs to
|
||||||
|
*/
|
||||||
|
protected HighVariable(HighFunction func) {
|
||||||
|
function = func;
|
||||||
|
}
|
||||||
|
|
||||||
protected HighVariable(String nm, DataType tp, Varnode rep, Varnode[] inst, HighFunction func) {
|
protected HighVariable(String nm, DataType tp, Varnode rep, Varnode[] inst, HighFunction func) {
|
||||||
name = nm;
|
name = nm;
|
||||||
|
@ -104,6 +114,15 @@ public abstract class HighVariable {
|
||||||
*/
|
*/
|
||||||
public abstract HighSymbol getSymbol();
|
public abstract HighSymbol getSymbol();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the offset of this variable into its containing HighSymbol. If the value
|
||||||
|
* is -1, this indicates that this HighVariable matches the size and storage of the symbol.
|
||||||
|
* @return the offset
|
||||||
|
*/
|
||||||
|
public int getOffset() {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach an instance or additional location the variable can be found in.
|
* Attach an instance or additional location the variable can be found in.
|
||||||
*
|
*
|
||||||
|
@ -121,16 +140,46 @@ public abstract class HighVariable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public VariableStorage getStorage() {
|
/**
|
||||||
Program program = getHighFunction().getFunction().getProgram();
|
* Restore the data-type and the Varnode instances of this HighVariable.
|
||||||
try {
|
* The "representative" Varnode is also populated.
|
||||||
if (represent != null && (represent.isAddress() || represent.isRegister())) {
|
* @param parser is the XML stream
|
||||||
return new VariableStorage(program, represent);
|
* @param el is the root <high> tag
|
||||||
}
|
* @throws PcodeXMLException if the XML is not valid
|
||||||
|
*/
|
||||||
|
protected void restoreInstances(XmlPullParser parser, XmlElement el)
|
||||||
|
throws PcodeXMLException {
|
||||||
|
int repref = SpecXmlUtils.decodeInt(el.getAttribute("repref"));
|
||||||
|
Varnode rep = function.getRef(repref);
|
||||||
|
if (rep == null) {
|
||||||
|
throw new PcodeXMLException("Undefined varnode reference");
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
|
||||||
Msg.error(this, "Failed to define variable storage: " + this, e);
|
type = null;
|
||||||
|
|
||||||
|
ArrayList<Varnode> vnlist = new ArrayList<Varnode>();
|
||||||
|
if (parser.peek().isStart()) {
|
||||||
|
type = function.getDataTypeManager().readXMLDataType(parser);
|
||||||
}
|
}
|
||||||
return VariableStorage.UNASSIGNED_STORAGE;
|
|
||||||
|
if (type == null) {
|
||||||
|
throw new PcodeXMLException("Missing <type> 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 <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;
|
HighSymbol sym;
|
||||||
if (storage.isHashStorage()) {
|
if (storage.isHashStorage()) {
|
||||||
sym = newDynamicSymbol(id, name, dt, sz, storage.getFirstVarnode().getOffset(),
|
sym = newDynamicSymbol(id, name, dt, sz, storage.getFirstVarnode().getOffset(),
|
||||||
defAddr, 0);
|
defAddr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sym = newMappedSymbol(id, name, dt, storage, defAddr, -1);
|
sym = newMappedSymbol(id, name, dt, storage, defAddr, -1);
|
||||||
|
@ -167,16 +167,16 @@ public class LocalSymbolMap {
|
||||||
String typename = node.getAttribute("type");
|
String typename = node.getAttribute("type");
|
||||||
HighSymbol res = null;
|
HighSymbol res = null;
|
||||||
if (typename == null) {
|
if (typename == null) {
|
||||||
res = new MappedSymbol();
|
res = new MappedSymbol(func);
|
||||||
}
|
}
|
||||||
else if (typename.equals("dynamic")) {
|
else if (typename.equals("dynamic")) {
|
||||||
res = new DynamicSymbol();
|
res = new DynamicSymbol(func);
|
||||||
}
|
}
|
||||||
else if (typename.equals("equate")) {
|
else if (typename.equals("equate")) {
|
||||||
res = new EquateSymbol();
|
res = new EquateSymbol(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.restoreXML(parser, func);
|
res.restoreXML(parser);
|
||||||
parser.end(node);
|
parser.end(node);
|
||||||
insertSymbol(res);
|
insertSymbol(res);
|
||||||
return res;
|
return res;
|
||||||
|
@ -225,7 +225,7 @@ public class LocalSymbolMap {
|
||||||
ArrayList<MappedSymbol> parms = new ArrayList<MappedSymbol>();
|
ArrayList<MappedSymbol> parms = new ArrayList<MappedSymbol>();
|
||||||
while (parser.peek().isStart()) {
|
while (parser.peek().isStart()) {
|
||||||
HighSymbol sym = parseSymbolXML(parser);
|
HighSymbol sym = parseSymbolXML(parser);
|
||||||
if (sym instanceof MappedSymbol && ((MappedSymbol) sym).isParameter()) {
|
if (sym.isParameter()) {
|
||||||
parms.add((MappedSymbol) sym);
|
parms.add((MappedSymbol) sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,11 +339,11 @@ public class LocalSymbolMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
public DynamicSymbol newDynamicSymbol(long id, String nm, DataType dt, int sz, long hash,
|
public DynamicSymbol newDynamicSymbol(long id, String nm, DataType dt, int sz, long hash,
|
||||||
Address pcaddr, int format) {
|
Address pcaddr) {
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
id = getNextId();
|
id = getNextId();
|
||||||
}
|
}
|
||||||
DynamicSymbol sym = new DynamicSymbol(id, nm, dt, sz, func, pcaddr, hash, format);
|
DynamicSymbol sym = new DynamicSymbol(id, nm, dt, sz, func, pcaddr, hash);
|
||||||
insertSymbol(sym);
|
insertSymbol(sym);
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
@ -365,23 +365,21 @@ public class LocalSymbolMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void newEquateSymbol(long uniqueId, String nm, long val, long hash, Address addr,
|
private void newEquateSymbol(long uniqueId, String nm, long val, long hash, Address addr,
|
||||||
int format,
|
|
||||||
TreeMap<String, DynamicSymbol> constantSymbolMap) {
|
TreeMap<String, DynamicSymbol> constantSymbolMap) {
|
||||||
DynamicSymbol eqSymbol = constantSymbolMap.get(nm);
|
DynamicSymbol eqSymbol = constantSymbolMap.get(nm);
|
||||||
if (eqSymbol != null) {
|
if (eqSymbol != null) {
|
||||||
eqSymbol.addReference(addr, hash, format); // New reference to same symbol
|
return; // New reference to same symbol
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (uniqueId == 0) {
|
if (uniqueId == 0) {
|
||||||
uniqueId = getNextId();
|
uniqueId = getNextId();
|
||||||
}
|
}
|
||||||
int conv = EquateSymbol.convertName(nm, val);
|
int conv = EquateSymbol.convertName(nm, val);
|
||||||
if (conv < 0) {
|
if (conv < 0) {
|
||||||
eqSymbol = new EquateSymbol(uniqueId, nm, val, func, addr, hash, format);
|
eqSymbol = new EquateSymbol(uniqueId, nm, val, func, addr, hash);
|
||||||
eqSymbol.setNameLock(true);
|
eqSymbol.setNameLock(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
eqSymbol = new EquateSymbol(uniqueId, conv, val, func, addr, hash, format);
|
eqSymbol = new EquateSymbol(uniqueId, conv, val, func, addr, hash);
|
||||||
}
|
}
|
||||||
//Do NOT setTypeLock
|
//Do NOT setTypeLock
|
||||||
constantSymbolMap.put(nm, eqSymbol);
|
constantSymbolMap.put(nm, eqSymbol);
|
||||||
|
@ -410,7 +408,7 @@ public class LocalSymbolMap {
|
||||||
if (constantSymbolMap == null) {
|
if (constantSymbolMap == null) {
|
||||||
constantSymbolMap = new TreeMap<String, DynamicSymbol>();
|
constantSymbolMap = new TreeMap<String, DynamicSymbol>();
|
||||||
}
|
}
|
||||||
newEquateSymbol(0, eq.getDisplayName(), eq.getValue(), element, defAddr, 0,
|
newEquateSymbol(0, eq.getDisplayName(), eq.getValue(), element, defAddr,
|
||||||
constantSymbolMap);
|
constantSymbolMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ public class MappedSymbol extends HighSymbol {
|
||||||
private VariableStorage storage;
|
private VariableStorage storage;
|
||||||
private int slot; // parameter slot, -1 for non-parameter
|
private int slot; // parameter slot, -1 for non-parameter
|
||||||
|
|
||||||
public MappedSymbol() { // For use with restoreXML
|
public MappedSymbol(HighFunction func) { // For use with restoreXML
|
||||||
|
super(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedSymbol(long uniqueId, String name, DataType dt, VariableStorage store,
|
public MappedSymbol(long uniqueId, String name, DataType dt, VariableStorage store,
|
||||||
|
@ -44,22 +45,14 @@ public class MappedSymbol extends HighSymbol {
|
||||||
}
|
}
|
||||||
this.storage = store;
|
this.storage = store;
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
Varnode rep = function.createFromStorage(null, storage, dt.getLength());
|
|
||||||
HighVariable var;
|
|
||||||
if (slot < 0) {
|
|
||||||
var = new HighLocal(type, rep, null, pcaddr, this);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var = new HighParam(type, rep, pcaddr, slot, this);
|
|
||||||
}
|
|
||||||
setHighVariable(var);
|
|
||||||
var.setHighOnInstances();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public VariableStorage getStorage() {
|
public VariableStorage getStorage() {
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isParameter() {
|
public boolean isParameter() {
|
||||||
return slot >= 0;
|
return slot >= 0;
|
||||||
}
|
}
|
||||||
|
@ -88,9 +81,9 @@ public class MappedSymbol extends HighSymbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXML(XmlPullParser parser, HighFunction func) throws PcodeXMLException {
|
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
||||||
XmlElement symel = parser.start("symbol");
|
XmlElement symel = parser.start("symbol");
|
||||||
restoreSymbolXML(symel, func);
|
restoreSymbolXML(symel);
|
||||||
slot = -1;
|
slot = -1;
|
||||||
int cat = -1;
|
int cat = -1;
|
||||||
if (symel.hasAttribute("cat")) {
|
if (symel.hasAttribute("cat")) {
|
||||||
|
@ -99,7 +92,7 @@ public class MappedSymbol extends HighSymbol {
|
||||||
slot = SpecXmlUtils.decodeInt(symel.getAttribute("index"));
|
slot = SpecXmlUtils.decodeInt(symel.getAttribute("index"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type = func.getDataTypeManager().readXMLDataType(parser);
|
type = function.getDataTypeManager().readXMLDataType(parser);
|
||||||
parser.end(symel);
|
parser.end(symel);
|
||||||
|
|
||||||
if (slot >= 0 && name.startsWith("$$undef")) {
|
if (slot >= 0 && name.startsWith("$$undef")) {
|
||||||
|
@ -107,10 +100,17 @@ public class MappedSymbol extends HighSymbol {
|
||||||
name = "param_" + Integer.toString(slot + 1);
|
name = "param_" + Integer.toString(slot + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restoreEntryXML(parser);
|
||||||
|
while (parser.peek().isStart()) {
|
||||||
|
parser.discardSubTree();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void restoreEntryXML(XmlPullParser parser) throws PcodeXMLException {
|
||||||
Program program = function.getFunction().getProgram();
|
Program program = function.getFunction().getProgram();
|
||||||
AddressFactory addrFactory = function.getAddressFactory();
|
AddressFactory addrFactory = function.getAddressFactory();
|
||||||
|
|
||||||
Address addr = null;
|
|
||||||
XmlElement addrel = parser.start("addr");
|
XmlElement addrel = parser.start("addr");
|
||||||
int sz = type.getLength();
|
int sz = type.getLength();
|
||||||
if (sz == 0) {
|
if (sz == 0) {
|
||||||
|
@ -123,8 +123,7 @@ public class MappedSymbol extends HighSymbol {
|
||||||
storage = new VariableStorage(program, varAddr, sz);
|
storage = new VariableStorage(program, varAddr, sz);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addr = varAddr;
|
storage = function.readXMLVarnodePieces(addrel, varAddr);
|
||||||
storage = func.readXMLVarnodePieces(addrel, varAddr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
|
@ -134,16 +133,6 @@ public class MappedSymbol extends HighSymbol {
|
||||||
parser.end(addrel);
|
parser.end(addrel);
|
||||||
|
|
||||||
pcaddr = parseRangeList(parser);
|
pcaddr = parseRangeList(parser);
|
||||||
Varnode rep = function.createFromStorage(addr, storage, sz);
|
|
||||||
HighVariable var;
|
|
||||||
if (slot < 0) {
|
|
||||||
var = new HighLocal(type, rep, null, pcaddr, this);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var = new HighParam(type, rep, pcaddr, slot, this);
|
|
||||||
}
|
|
||||||
setHighVariable(var);
|
|
||||||
var.setHighOnInstances();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String buildSymbolXML(PcodeDataTypeManager dtmanage, long uniqueId, String nm,
|
public static String buildSymbolXML(PcodeDataTypeManager dtmanage, long uniqueId, String nm,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue