populate HighFunctionShellSymbol in GlobalSymbolMap

This commit is contained in:
caheckman 2019-12-20 16:00:54 -05:00
parent 97b43b9470
commit 7b407f1965
11 changed files with 104 additions and 42 deletions

View file

@ -572,10 +572,12 @@ void FunctionSymbol::saveXml(ostream &s) const
{ {
if (fd != (Funcdata *)0) if (fd != (Funcdata *)0)
fd->saveXml(s,false); // Save the function itself fd->saveXml(s,symbolId,false); // Save the function itself
else { else {
s << "<functionshell"; s << "<functionshell";
a_v(s,"name",name); a_v(s,"name",name);
if (symbolId != 0)
a_v_u(s,"id",symbolId);
s << "/>\n"; s << "/>\n";
} }
} }
@ -585,7 +587,7 @@ void FunctionSymbol::restoreXml(const Element *el)
{ {
if (el->getName() == "function") { if (el->getName() == "function") {
fd = new Funcdata("",scope,Address()); fd = new Funcdata("",scope,Address());
fd->restoreXml(el); symbolId = fd->restoreXml(el);
name = fd->getName(); name = fd->getName();
if (consumeSize < fd->getSize()) { if (consumeSize < fd->getSize()) {
if ((fd->getSize()>1)&&(fd->getSize() <= 8)) if ((fd->getSize()>1)&&(fd->getSize() <= 8))
@ -593,7 +595,17 @@ void FunctionSymbol::restoreXml(const Element *el)
} }
} }
else { // functionshell else { // functionshell
name = el->getAttributeValue("name"); symbolId = 0;
for(int4 i=0;i<el->getNumAttributes();++i) {
const string &attrName(el->getAttributeName(i));
if (attrName == "name")
name = el->getAttributeValue(i);
else if (attrName == "id") {
istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> symbolId;
}
}
} }
} }

View file

@ -682,11 +682,14 @@ void Funcdata::saveXmlTree(ostream &s) const
/// If indicated by the caller, a description of the entire PcodeOp and Varnode /// If indicated by the caller, a description of the entire PcodeOp and Varnode
/// tree is also emitted. /// tree is also emitted.
/// \param s is the output stream /// \param s is the output stream
/// \param id is the unique id associated with the function symbol
/// \param savetree is \b true if the p-code tree should be emitted /// \param savetree is \b true if the p-code tree should be emitted
void Funcdata::saveXml(ostream &s,bool savetree) const void Funcdata::saveXml(ostream &s,uint8 id,bool savetree) const
{ {
s << "<function"; s << "<function";
if (id != 0)
a_v_u(s, "id", id);
a_v(s,"name",name); a_v(s,"name",name);
a_v_i(s,"size",size); a_v_i(s,"size",size);
if (hasNoCode()) if (hasNoCode())
@ -712,22 +715,30 @@ void Funcdata::saveXml(ostream &s,bool savetree) const
/// From an XML \<function> tag, recover the name, address, prototype, symbol, /// From an XML \<function> tag, recover the name, address, prototype, symbol,
/// jump-table, and override information for \b this function. /// jump-table, and override information for \b this function.
/// \param el is the root \<function> tag /// \param el is the root \<function> tag
void Funcdata::restoreXml(const Element *el) /// \return the symbol id associated with the function
uint8 Funcdata::restoreXml(const Element *el)
{ {
// clear(); // Shouldn't be needed // clear(); // Shouldn't be needed
name.clear(); name.clear();
size = -1; size = -1;
uint8 id = 0;
AddrSpace *stackid = glb->getStackSpace(); AddrSpace *stackid = glb->getStackSpace();
for(int4 i=0;i<el->getNumAttributes();++i) { for(int4 i=0;i<el->getNumAttributes();++i) {
if (el->getAttributeName(i) == "name") const string &attrName(el->getAttributeName(i));
if (attrName == "name")
name = el->getAttributeValue(i); name = el->getAttributeValue(i);
else if (el->getAttributeName(i) == "size") { else if (attrName == "size") {
istringstream s( el->getAttributeValue(i)); istringstream s( el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct); s.unsetf(ios::dec | ios::hex | ios::oct);
s >> size; s >> size;
} }
else if (el->getAttributeName(i) == "nocode") { else if (attrName == "id") {
istringstream s( el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> id;
}
else if (attrName == "nocode") {
if (xml_readbool(el->getAttributeValue(i))) if (xml_readbool(el->getAttributeValue(i)))
flags |= no_code; flags |= no_code;
} }
@ -779,6 +790,7 @@ void Funcdata::restoreXml(const Element *el)
funcp.setScope(localmap,baseaddr+ -1); funcp.setScope(localmap,baseaddr+ -1);
} }
localmap->resetLocalWindow(); localmap->resetLocalWindow();
return id;
} }
/// \brief Inject p-code from a \e payload into \b this live function /// \brief Inject p-code from a \e payload into \b this live function

View file

@ -171,8 +171,8 @@ public:
void printVarnodeTree(ostream &s) const; ///< Print a description of all Varnodes to a stream void printVarnodeTree(ostream &s) const; ///< Print a description of all Varnodes to a stream
void printBlockTree(ostream &s) const; ///< Print a description of control-flow structuring to a stream void printBlockTree(ostream &s) const; ///< Print a description of control-flow structuring to a stream
void printLocalRange(ostream &s) const; ///< Print description of memory ranges associated with local scopes void printLocalRange(ostream &s) const; ///< Print description of memory ranges associated with local scopes
void saveXml(ostream &s,bool savetree) const; ///< Emit an XML description of \b this function to stream void saveXml(ostream &s,uint8 id,bool savetree) const; ///< Emit an XML description of \b this function to stream
void restoreXml(const Element *el); ///< Restore the state of \b this function from an XML description uint8 restoreXml(const Element *el); ///< Restore the state of \b this function from an XML description
void saveXmlJumpTable(ostream &s) const; ///< Emit an XML description of jump-tables to stream void saveXmlJumpTable(ostream &s) const; ///< Emit an XML description of jump-tables to stream
void restoreXmlJumpTable(const Element *el); ///< Restore jump-tables from an XML description void restoreXmlJumpTable(const Element *el); ///< Restore jump-tables from an XML description
void saveXmlTree(ostream &s) const; ///< Save an XML description of the p-code tree to stream void saveXmlTree(ostream &s) const; ///< Save an XML description of the p-code tree to stream

View file

@ -314,7 +314,7 @@ void DecompileAt::rawAction(void)
ParamIDAnalysis pidanalysis( fd, false ); ParamIDAnalysis pidanalysis( fd, false );
pidanalysis.saveXml( sout, true ); pidanalysis.saveXml( sout, true );
} }
fd->saveXml(sout,ghidra->getSendSyntaxTree()); fd->saveXml(sout,0,ghidra->getSendSyntaxTree());
if (ghidra->getSendCCode()&& if (ghidra->getSendCCode()&&
(ghidra->allacts.getCurrentName() == "decompile")) (ghidra->allacts.getCurrentName() == "decompile"))
ghidra->print->docFunction(fd); ghidra->print->docFunction(fd);

View file

@ -672,7 +672,7 @@ public class DecompileCallback {
func = listing.getFunctionAt(extRef.getToAddress()); func = listing.getFunctionAt(extRef.getToAddress());
if (func == null) { if (func == null) {
HighSymbol shellSymbol = HighSymbol shellSymbol =
new HighFunctionShellSymbol(extRef.getLabel(), addr, dtmanage); new HighFunctionShellSymbol(0, extRef.getLabel(), addr, dtmanage);
return buildResult(shellSymbol, null); return buildResult(shellSymbol, null);
} }
} }

View file

@ -76,7 +76,7 @@ public class RenameVariableAction extends AbstractDecompilerAction {
} }
else { else {
GlobalSymbolMap gsym = hfunc.getGlobalSymbolMap(); GlobalSymbolMap gsym = hfunc.getGlobalSymbolMap();
HighCodeSymbol hsym = gsym.getSymbol(addr); HighSymbol hsym = gsym.getSymbol(addr);
if (hsym != null) { if (hsym != null) {
res = hsym.getHighVariable(); res = hsym.getHighVariable();
if (res == null) { if (res == null) {

View file

@ -19,6 +19,7 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import ghidra.program.database.symbol.CodeSymbol; import ghidra.program.database.symbol.CodeSymbol;
import ghidra.program.database.symbol.FunctionSymbol;
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.program.model.listing.Data; import ghidra.program.model.listing.Data;
@ -38,8 +39,8 @@ public class GlobalSymbolMap {
private Program program; private Program program;
private HighFunction func; // Is the full decompiler model of the function to which this belongs private HighFunction func; // Is the full decompiler model of the function to which this belongs
private SymbolTable symbolTable; // Used for cross-referencing with Ghidra's database backed Symbols private SymbolTable symbolTable; // Used for cross-referencing with Ghidra's database backed Symbols
private HashMap<Address, HighCodeSymbol> addrMappedSymbols; // Look up symbols by address private HashMap<Address, HighSymbol> addrMappedSymbols; // Look up symbols by address
private HashMap<Long, HighCodeSymbol> symbolMap; // Look up symbol by id private HashMap<Long, HighSymbol> symbolMap; // Look up symbol by id
private long uniqueSymbolId; // Next available symbol id private long uniqueSymbolId; // Next available symbol id
/** /**
@ -50,12 +51,12 @@ public class GlobalSymbolMap {
program = f.getFunction().getProgram(); program = f.getFunction().getProgram();
func = f; func = f;
symbolTable = program.getSymbolTable(); symbolTable = program.getSymbolTable();
addrMappedSymbols = new HashMap<Address, HighCodeSymbol>(); addrMappedSymbols = new HashMap<Address, HighSymbol>();
symbolMap = new HashMap<Long, HighCodeSymbol>(); symbolMap = new HashMap<Long, HighSymbol>();
uniqueSymbolId = 0; uniqueSymbolId = 0;
} }
private void insertSymbol(HighCodeSymbol sym, Address addr) { private void insertSymbol(HighSymbol sym, Address addr) {
long uniqueId = sym.getId(); long uniqueId = sym.getId();
if ((uniqueId >> 56) == (HighSymbol.ID_BASE >> 56)) { if ((uniqueId >> 56) == (HighSymbol.ID_BASE >> 56)) {
long val = uniqueId & 0x7fffffff; long val = uniqueId & 0x7fffffff;
@ -68,34 +69,44 @@ public class GlobalSymbolMap {
} }
/** /**
* Create a HighCodeSymbol based on the id of the underlying CodeSymbol. The CodeSymbol * Create a HighSymbol based on the id of the underlying Ghidra Symbol. The Symbol
* is looked up in the SymbolTable and then a HighSymbol is created with the name and * is looked up in the SymbolTable and then a HighSymbol is created with the name and
* dataType associated with the CodeSymbol. If a CodeSymbol cannot be found, null is returned. * dataType associated with the Symbol. If a Symbol cannot be found, null is returned.
* @param id is the database id of the CodeSymbol * @param id is the database id of the CodeSymbol
* @param dataType is the recovered data-type of the symbol * @param dataType is the recovered data-type of the symbol
* @param sz is the size in bytes of the desired symbol * @param sz is the size in bytes of the desired symbol
* @return the CodeSymbol wrapped as a HighSymbol or null * @return the CodeSymbol wrapped as a HighSymbol or null
*/ */
public HighCodeSymbol populateSymbol(long id, DataType dataType, int sz) { public HighSymbol populateSymbol(long id, DataType dataType, int sz) {
if ((id >> 56) == (HighSymbol.ID_BASE >> 56)) { if ((id >> 56) == (HighSymbol.ID_BASE >> 56)) {
return null; // This is an internal id, not a database key return null; // This is an internal id, not a database key
} }
Symbol symbol = symbolTable.getSymbol(id); Symbol symbol = symbolTable.getSymbol(id);
if (symbol == null || !(symbol instanceof CodeSymbol)) { if (symbol == null) {
return null; return null;
} }
if (dataType == null) { HighSymbol highSym = null;
Object dataObj = symbol.getObject(); if (symbol instanceof CodeSymbol) {
if (dataObj instanceof Data) { if (dataType == null) {
dataType = ((Data) dataObj).getDataType(); Object dataObj = symbol.getObject();
sz = dataType.getLength(); if (dataObj instanceof Data) {
} dataType = ((Data) dataObj).getDataType();
else { sz = dataType.getLength();
dataType = DataType.DEFAULT; }
sz = 1; else {
dataType = DataType.DEFAULT;
sz = 1;
}
} }
highSym = new HighCodeSymbol((CodeSymbol) symbol, dataType, sz, func);
}
else if (symbol instanceof FunctionSymbol) {
highSym = new HighFunctionShellSymbol(id, symbol.getName(), symbol.getAddress(),
func.getDataTypeManager());
}
else {
return null;
} }
HighCodeSymbol highSym = new HighCodeSymbol((CodeSymbol) symbol, dataType, sz, func);
insertSymbol(highSym, symbol.getAddress()); insertSymbol(highSym, symbol.getAddress());
return highSym; return highSym;
} }
@ -125,7 +136,7 @@ public class GlobalSymbolMap {
* @param id is the id * @param id is the id
* @return the matching HighSymbol or null * @return the matching HighSymbol or null
*/ */
public HighCodeSymbol getSymbol(long id) { public HighSymbol getSymbol(long id) {
return symbolMap.get(id); return symbolMap.get(id);
} }
@ -134,7 +145,7 @@ public class GlobalSymbolMap {
* @param addr is the given Address * @param addr is the given Address
* @return the matching HighSymbol or null * @return the matching HighSymbol or null
*/ */
public HighCodeSymbol getSymbol(Address addr) { public HighSymbol getSymbol(Address addr) {
return addrMappedSymbols.get(addr); return addrMappedSymbols.get(addr);
} }
@ -142,7 +153,7 @@ public class GlobalSymbolMap {
* Get an iterator over all HighSymbols in this container * Get an iterator over all HighSymbols in this container
* @return the iterator * @return the iterator
*/ */
public Iterator<HighCodeSymbol> getSymbols() { public Iterator<HighSymbol> getSymbols() {
return symbolMap.values().iterator(); return symbolMap.values().iterator();
} }
} }

View file

@ -21,6 +21,7 @@ import java.util.List;
import org.xml.sax.*; import org.xml.sax.*;
import ghidra.program.database.function.FunctionDB;
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;
@ -80,6 +81,17 @@ public class HighFunction extends PcodeSyntaxTree {
return func; return func;
} }
/**
* Get the id with the associated function symbol, if it exists
* @return the id or 0 otherwise
*/
public long getID() {
if (func instanceof FunctionDB) {
return func.getSymbol().getID();
}
return 0;
}
/** /**
* @return get the language parser used to disassemble * @return get the language parser used to disassemble
*/ */
@ -423,15 +435,19 @@ public class HighFunction extends PcodeSyntaxTree {
* this doesn't need to be strictly accurate as it is only used to associate the function with * this doesn't need to be strictly accurate as it is only used to associate the function with
* addresses near its entry point. * addresses near its entry point.
* *
* @param id is the id associated with the function symbol
* @param entryPoint pass null to use the function entryPoint, pass an address to force an entry point * @param entryPoint pass null to use the function entryPoint, pass an address to force an entry point
* @param size describes how many bytes the function occupies as code * @param size describes how many bytes the function occupies as code
* @return the XML string * @return the XML string
*/ */
public String buildFunctionXML(Address entryPoint, int size) { public String buildFunctionXML(long id, Address entryPoint, int size) {
// Functions aren't necessarily contiguous with the smallest address being the entry point // Functions aren't necessarily contiguous with the smallest address being the entry point
// So size needs to be smaller than size of the contiguous chunk containing the entry point // So size needs to be smaller than size of the contiguous chunk containing the entry point
StringBuilder resBuf = new StringBuilder(); StringBuilder resBuf = new StringBuilder();
resBuf.append("<function"); resBuf.append("<function");
if (id != 0) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", id);
}
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", func.getName(showNamespace)); SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", func.getName(showNamespace));
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
if (func.isInline()) { if (func.isInline()) {

View file

@ -29,12 +29,13 @@ public class HighFunctionShellSymbol extends HighSymbol {
/** /**
* Construct the function shell given a name and address * Construct the function shell given a name and address
* @param id is an id to associate with the new symbol
* @param nm is the given name * @param nm is the given name
* @param addr is the given address * @param addr is the given address
* @param manage is PcodeDataTypeManager to facilitate XML marshaling * @param manage is PcodeDataTypeManager to facilitate XML marshaling
*/ */
public HighFunctionShellSymbol(String nm, Address addr, PcodeDataTypeManager manage) { public HighFunctionShellSymbol(long id, String nm, Address addr, PcodeDataTypeManager manage) {
super(0, nm, DataType.DEFAULT, true, true, manage); super(id, nm, DataType.DEFAULT, true, true, manage);
VariableStorage store; VariableStorage store;
try { try {
store = new VariableStorage(getProgram(), addr, 1); store = new VariableStorage(getProgram(), addr, 1);
@ -46,6 +47,11 @@ public class HighFunctionShellSymbol extends HighSymbol {
addMapEntry(entry); addMapEntry(entry);
} }
@Override
public boolean isGlobal() {
return true;
}
@Override @Override
public void saveXML(StringBuilder buf) { public void saveXML(StringBuilder buf) {
buf.append("<function"); buf.append("<function");

View file

@ -37,7 +37,7 @@ public class HighFunctionSymbol extends HighSymbol {
* @param function is the decompiler model of the function * @param function is the decompiler model of the function
*/ */
public HighFunctionSymbol(Address addr, int size, HighFunction function) { public HighFunctionSymbol(Address addr, int size, HighFunction function) {
super(0, "", DataType.DEFAULT, function); super(function.getID(), "", DataType.DEFAULT, function);
VariableStorage store; VariableStorage store;
try { try {
store = new VariableStorage(getProgram(), addr, size); store = new VariableStorage(getProgram(), addr, size);
@ -49,11 +49,16 @@ public class HighFunctionSymbol extends HighSymbol {
addMapEntry(entry); addMapEntry(entry);
} }
@Override
public boolean isGlobal() {
return true;
}
@Override @Override
public void saveXML(StringBuilder buf) { public void saveXML(StringBuilder buf) {
MappedEntry entry = (MappedEntry) getFirstWholeMap(); MappedEntry entry = (MappedEntry) getFirstWholeMap();
String funcString = String funcString =
function.buildFunctionXML(entry.getStorage().getMinAddress(), entry.getSize()); function.buildFunctionXML(getId(), entry.getStorage().getMinAddress(), entry.getSize());
buf.append(funcString); buf.append(funcString);
} }
} }

View file

@ -28,7 +28,7 @@ import ghidra.xml.XmlPullParser;
*/ */
public class HighGlobal extends HighVariable { public class HighGlobal extends HighVariable {
private HighCodeSymbol symbol; private HighSymbol symbol;
/** /**
* Constructor for use with restoreXml * Constructor for use with restoreXml
@ -38,7 +38,7 @@ public class HighGlobal extends HighVariable {
super(high); super(high);
} }
public HighGlobal(HighCodeSymbol sym, Varnode vn, Varnode[] inst) { public HighGlobal(HighSymbol 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;
} }