mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch 'origin/caheckman_EquateDeindirect'
This commit is contained in:
commit
0d2df489ce
43 changed files with 1050 additions and 396 deletions
|
@ -51,22 +51,19 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
private GlobalSymbolMap globalSymbols;
|
||||
private List<JumpTable> jumpTables;
|
||||
private List<DataTypeSymbol> protoOverrides;
|
||||
private boolean showNamespace = true;
|
||||
|
||||
/**
|
||||
* @param function function associated with the higher level function abstraction.
|
||||
* @param language description of the processor language of the function
|
||||
* @param compilerSpec description of the compiler that produced the function
|
||||
* @param dtManager data type manager
|
||||
* @param showNamespace true signals to print function names with their namespace
|
||||
*/
|
||||
public HighFunction(Function function, Language language, CompilerSpec compilerSpec,
|
||||
PcodeDataTypeManager dtManager, boolean showNamespace) {
|
||||
PcodeDataTypeManager dtManager) {
|
||||
super(function.getProgram().getAddressFactory(), dtManager);
|
||||
func = function;
|
||||
this.language = language;
|
||||
this.compilerSpec = compilerSpec;
|
||||
this.showNamespace = showNamespace;
|
||||
localSymbols = new LocalSymbolMap(this, "stack");
|
||||
globalSymbols = new GlobalSymbolMap(this);
|
||||
proto = new FunctionPrototype(localSymbols, function);
|
||||
|
@ -260,9 +257,9 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
public void readXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement start = parser.start("function");
|
||||
String name = start.getAttribute("name");
|
||||
if (!func.getName(showNamespace).equals(name)) {
|
||||
if (!func.getName().equals(name)) {
|
||||
throw new PcodeXMLException(
|
||||
"Function name mismatch: " + func.getName(showNamespace) + " + " + name);
|
||||
"Function name mismatch: " + func.getName() + " + " + name);
|
||||
}
|
||||
while (!parser.peek().isEnd()) {
|
||||
XmlElement subel = parser.peek();
|
||||
|
@ -436,11 +433,12 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
* addresses near its entry point.
|
||||
*
|
||||
* @param id is the id associated with the function symbol
|
||||
* @param namespace is the namespace containing the function symbol
|
||||
* @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
|
||||
* @return the XML string
|
||||
*/
|
||||
public String buildFunctionXML(long id, Address entryPoint, int size) {
|
||||
public String buildFunctionXML(long id, Namespace namespace, Address entryPoint, int size) {
|
||||
// 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
|
||||
StringBuilder resBuf = new StringBuilder();
|
||||
|
@ -448,7 +446,7 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
if (id != 0) {
|
||||
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", id);
|
||||
}
|
||||
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", func.getName(showNamespace));
|
||||
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", func.getName());
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
|
||||
if (func.isInline()) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(resBuf, "inline", true);
|
||||
|
@ -463,12 +461,12 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
else {
|
||||
resBuf.append(Varnode.buildXMLAddress(entryPoint)); // Address is forced on XML
|
||||
}
|
||||
resBuf.append(localSymbols.buildLocalDbXML());
|
||||
localSymbols.buildLocalDbXML(resBuf, namespace);
|
||||
proto.buildPrototypeXML(resBuf, getDataTypeManager());
|
||||
if ((jumpTables != null) && (jumpTables.size() > 0)) {
|
||||
resBuf.append("<jumptablelist>\n");
|
||||
for (int i = 0; i < jumpTables.size(); ++i) {
|
||||
jumpTables.get(i).buildXml(resBuf);
|
||||
for (JumpTable jumpTable : jumpTables) {
|
||||
jumpTable.buildXml(resBuf);
|
||||
}
|
||||
resBuf.append("</jumptablelist>\n");
|
||||
}
|
||||
|
@ -478,8 +476,7 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
}
|
||||
if ((protoOverrides != null) && (protoOverrides.size() > 0)) {
|
||||
PcodeDataTypeManager dtmanage = getDataTypeManager();
|
||||
for (int i = 0; i < protoOverrides.size(); ++i) {
|
||||
DataTypeSymbol sym = protoOverrides.get(i);
|
||||
for (DataTypeSymbol sym : protoOverrides) {
|
||||
Address addr = sym.getAddress();
|
||||
FunctionPrototype fproto = new FunctionPrototype(
|
||||
(FunctionSignature) sym.getDataType(), compilerSpec, false);
|
||||
|
@ -618,22 +615,39 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
}
|
||||
}
|
||||
|
||||
static public void createNamespaceTag(StringBuilder buf, Namespace namespc) {
|
||||
if (namespc == null) {
|
||||
return;
|
||||
}
|
||||
ArrayList<String> arr = new ArrayList<String>();
|
||||
Namespace curspc = namespc;
|
||||
while (curspc != null) {
|
||||
arr.add(0, curspc.getName());
|
||||
curspc = curspc.getParentNamespace();
|
||||
}
|
||||
buf.append("<val/>\n"); // Force global scope to have empty name
|
||||
for (int i = 1; i < arr.size(); ++i) {
|
||||
buf.append("<val>");
|
||||
SpecXmlUtils.xmlEscape(buf, arr.get(i));
|
||||
buf.append("</val>\n");
|
||||
/**
|
||||
* Append an XML <parent> tag to the buffer describing the formal path elements
|
||||
* from the root (global) namespace up to the given namespace
|
||||
* @param buf is the buffer to write to
|
||||
* @param namespace is the namespace being described
|
||||
* @param includeId is true if the XML tag should include namespace ids
|
||||
*/
|
||||
static public void createNamespaceTag(StringBuilder buf, Namespace namespace,
|
||||
boolean includeId) {
|
||||
buf.append("<parent>\n");
|
||||
if (namespace != null) {
|
||||
ArrayList<Namespace> arr = new ArrayList<Namespace>();
|
||||
Namespace curspc = namespace;
|
||||
while (curspc != null) {
|
||||
arr.add(0, curspc);
|
||||
if (curspc instanceof Library) {
|
||||
break; // Treat library namespace as root
|
||||
}
|
||||
curspc = curspc.getParentNamespace();
|
||||
}
|
||||
buf.append("<val/>\n"); // Force global scope to have empty name
|
||||
for (int i = 1; i < arr.size(); ++i) {
|
||||
Namespace curScope = arr.get(i);
|
||||
buf.append("<val");
|
||||
if (includeId) {
|
||||
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "id", curScope.getID());
|
||||
}
|
||||
buf.append('>');
|
||||
SpecXmlUtils.xmlEscape(buf, curScope.getName());
|
||||
buf.append("</val>\n");
|
||||
}
|
||||
}
|
||||
buf.append("</parent>\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,7 +17,9 @@ package ghidra.program.model.pcode;
|
|||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.VariableStorage;
|
||||
import ghidra.program.model.symbol.Namespace;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
|
||||
/**
|
||||
|
@ -54,11 +56,25 @@ public class HighFunctionSymbol extends HighSymbol {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Namespace getNamespace() {
|
||||
Function func = function.getFunction();
|
||||
Namespace namespc = func.getParentNamespace();
|
||||
while (func.isThunk() && namespc.getID() == Namespace.GLOBAL_NAMESPACE_ID) {
|
||||
// Thunks can be in a different namespace than the thunked function.
|
||||
// We choose the thunk's namespace unless it is the global namespace
|
||||
func = func.getThunkedFunction(false);
|
||||
namespc = func.getParentNamespace();
|
||||
}
|
||||
return namespc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXML(StringBuilder buf) {
|
||||
MappedEntry entry = (MappedEntry) getFirstWholeMap();
|
||||
String funcString =
|
||||
function.buildFunctionXML(getId(), entry.getStorage().getMinAddress(), entry.getSize());
|
||||
function.buildFunctionXML(getId(), getNamespace(), entry.getStorage().getMinAddress(),
|
||||
entry.getSize());
|
||||
buf.append(funcString);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,23 +48,20 @@ public class HighParamID extends PcodeSyntaxTree {
|
|||
private Integer protoextrapop;
|
||||
private List<ParamMeasure> inputlist = new ArrayList<ParamMeasure>();
|
||||
private List<ParamMeasure> outputlist = new ArrayList<ParamMeasure>();
|
||||
private boolean showNamespace = true;
|
||||
|
||||
/**
|
||||
* @param function function associated with the higher level function abstraction.
|
||||
* @param language language parser used to disassemble/get info on the language.
|
||||
* @param compilerSpec the compiler spec.
|
||||
* @param dtManager data type manager.
|
||||
* @param showNamespace true to show the parameters namespace.
|
||||
*/
|
||||
public HighParamID(Function function, Language language, CompilerSpec compilerSpec,
|
||||
PcodeDataTypeManager dtManager, boolean showNamespace) {
|
||||
PcodeDataTypeManager dtManager) {
|
||||
super(function.getProgram().getAddressFactory(), dtManager);
|
||||
func = function;
|
||||
|
||||
modelname = null;
|
||||
protoextrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
|
||||
this.showNamespace = showNamespace;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,8 +134,8 @@ public class HighParamID extends PcodeSyntaxTree {
|
|||
public void readXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement start = parser.start("parammeasures");
|
||||
functionname = start.getAttribute("name");
|
||||
if (!func.getName(showNamespace).equals(functionname)) {
|
||||
throw new PcodeXMLException("Function name mismatch: " + func.getName(showNamespace) +
|
||||
if (!func.getName().equals(functionname)) {
|
||||
throw new PcodeXMLException("Function name mismatch: " + func.getName() +
|
||||
" + " + functionname);
|
||||
}
|
||||
while (!parser.peek().isEnd()) {
|
||||
|
@ -157,10 +154,12 @@ public class HighParamID extends PcodeSyntaxTree {
|
|||
subel = parser.start("proto");
|
||||
modelname = subel.getAttribute("model");
|
||||
String val = subel.getAttribute("extrapop");
|
||||
if (val.equals("unknown"))
|
||||
if (val.equals("unknown")) {
|
||||
protoextrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
|
||||
else
|
||||
}
|
||||
else {
|
||||
protoextrapop = SpecXmlUtils.decodeInt(val);
|
||||
}
|
||||
parser.end(subel);
|
||||
}
|
||||
else if (subel.getName().equals("input")) {
|
||||
|
@ -243,23 +242,28 @@ public class HighParamID extends PcodeSyntaxTree {
|
|||
try {
|
||||
//TODO: Currently, only storing one output, so looking for the best to report. When possible, change this to report all
|
||||
int best_index = 0;
|
||||
if (getNumOutputs() > 1)
|
||||
for (int i = 1; i < getNumOutputs(); i++)
|
||||
if (getNumOutputs() > 1) {
|
||||
for (int i = 1; i < getNumOutputs(); i++) {
|
||||
if (getOutput(i).getRank() < getOutput(best_index).getRank()) {//TODO: create mirror of ranks on high side (instead of using numbers?)
|
||||
best_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getNumOutputs() != 0) {
|
||||
ParamMeasure pm = getOutput(best_index);
|
||||
pm.getRank(); //TODO (maybe): this value is not used or stored on the java side at this point
|
||||
Varnode vn = pm.getVarnode();
|
||||
DataType dataType;
|
||||
if (storeDataTypes)
|
||||
if (storeDataTypes) {
|
||||
dataType = pm.getDataType();
|
||||
else
|
||||
}
|
||||
else {
|
||||
dataType = dtManage.findUndefined(vn.getSize());
|
||||
}
|
||||
//Msg.debug(this, "func: " + func.getName() + " -- type: " + dataType.getName());
|
||||
if (!(dataType == null || dataType instanceof VoidDataType))
|
||||
if (!(dataType == null || dataType instanceof VoidDataType)) {
|
||||
func.setReturn(dataType, buildStorage(vn), SourceType.ANALYSIS);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
|
@ -282,10 +286,12 @@ public class HighParamID extends PcodeSyntaxTree {
|
|||
DataType dataType;
|
||||
//Msg.debug(this, "function(" + func.getName() + ")--param size: " + vn.getSize() +
|
||||
// "--type before store: " + pm.getDataType().getName());
|
||||
if (storeDataTypes)
|
||||
if (storeDataTypes) {
|
||||
dataType = pm.getDataType();
|
||||
else
|
||||
}
|
||||
else {
|
||||
dataType = dtManage.findUndefined(vn.getSize());
|
||||
}
|
||||
Variable v =
|
||||
new ParameterImpl(null, dataType, buildStorage(vn),
|
||||
func.getProgram());
|
||||
|
|
|
@ -19,6 +19,7 @@ import ghidra.program.model.address.Address;
|
|||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.VariableStorage;
|
||||
import ghidra.program.model.symbol.Namespace;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
|
@ -130,6 +131,18 @@ public class HighSymbol {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the namespace owning this symbol, if it exists.
|
||||
* @return the Namespace object or null
|
||||
*/
|
||||
public Namespace getNamespace() {
|
||||
Symbol sym = getSymbol();
|
||||
if (sym != null) {
|
||||
return sym.getParentNamespace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a particular HighVariable with this symbol. This is used to link the symbol
|
||||
* into the decompiler's description of how a function manipulates a particular symbol.
|
||||
|
|
|
@ -17,8 +17,7 @@ package ghidra.program.model.pcode;
|
|||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressIterator;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Undefined;
|
||||
import ghidra.program.model.listing.*;
|
||||
|
@ -184,16 +183,18 @@ public class LocalSymbolMap {
|
|||
if (symbol != null) {
|
||||
id = symbol.getID();
|
||||
}
|
||||
Address defAddr = null;
|
||||
if (!storage.isStackStorage()) {
|
||||
defAddr = dbFunction.getEntryPoint().addWrap(local.getFirstUseOffset());
|
||||
}
|
||||
HighSymbol sym;
|
||||
if (storage.isHashStorage()) {
|
||||
Address defAddr = dbFunction.getEntryPoint().addWrap(local.getFirstUseOffset());
|
||||
sym =
|
||||
newDynamicSymbol(id, name, dt, storage.getFirstVarnode().getOffset(), defAddr);
|
||||
}
|
||||
else {
|
||||
Address defAddr = null;
|
||||
int addrType = storage.getFirstVarnode().getAddress().getAddressSpace().getType();
|
||||
if (addrType != AddressSpace.TYPE_STACK && addrType != AddressSpace.TYPE_RAM) {
|
||||
defAddr = dbFunction.getEntryPoint().addWrap(local.getFirstUseOffset());
|
||||
}
|
||||
sym = newMappedSymbol(id, name, dt, storage, defAddr, -1);
|
||||
}
|
||||
sym.setTypeLock(istypelock);
|
||||
|
@ -325,31 +326,29 @@ public class LocalSymbolMap {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return an XML document string representing this local variable map.
|
||||
* Output an XML document representing this local variable map.
|
||||
* @param resBuf is the buffer to write to
|
||||
* @param namespace if the namespace of the function
|
||||
*/
|
||||
public String buildLocalDbXML() { // Get memory mapped local variables
|
||||
StringBuilder res = new StringBuilder();
|
||||
res.append("<localdb");
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "lock", false);
|
||||
SpecXmlUtils.encodeStringAttribute(res, "main", spacename);
|
||||
res.append(">\n");
|
||||
res.append("<scope");
|
||||
SpecXmlUtils.xmlEscapeAttribute(res, "name", func.getFunction().getName());
|
||||
res.append(">\n");
|
||||
res.append("<parent>\n");
|
||||
HighFunction.createNamespaceTag(res, func.getFunction().getParentNamespace());
|
||||
res.append("</parent>\n");
|
||||
res.append("<rangelist/>\n"); // Empty address range
|
||||
res.append("<symbollist>\n");
|
||||
public void buildLocalDbXML(StringBuilder resBuf, Namespace namespace) { // Get memory mapped local variables
|
||||
resBuf.append("<localdb");
|
||||
SpecXmlUtils.encodeBooleanAttribute(resBuf, "lock", false);
|
||||
SpecXmlUtils.encodeStringAttribute(resBuf, "main", spacename);
|
||||
resBuf.append(">\n");
|
||||
resBuf.append("<scope");
|
||||
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", func.getFunction().getName());
|
||||
resBuf.append(">\n");
|
||||
HighFunction.createNamespaceTag(resBuf, namespace, false);
|
||||
resBuf.append("<rangelist/>\n"); // Empty address range
|
||||
resBuf.append("<symbollist>\n");
|
||||
Iterator<HighSymbol> iter = symbolMap.values().iterator();
|
||||
while (iter.hasNext()) {
|
||||
HighSymbol sym = iter.next();
|
||||
HighSymbol.buildMapSymXML(res, sym);
|
||||
HighSymbol.buildMapSymXML(resBuf, sym);
|
||||
}
|
||||
res.append("</symbollist>\n");
|
||||
res.append("</scope>\n");
|
||||
res.append("</localdb>\n");
|
||||
return res.toString();
|
||||
resBuf.append("</symbollist>\n");
|
||||
resBuf.append("</scope>\n");
|
||||
resBuf.append("</localdb>\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue