diff --git a/ghidra/ghidra_scripts/EnhancedImport.java b/ghidra/ghidra_scripts/EnhancedImport.java new file mode 100644 index 0000000..3bdf040 --- /dev/null +++ b/ghidra/ghidra_scripts/EnhancedImport.java @@ -0,0 +1,102 @@ +// Imports data from a file produced by the EnhancedExport script. +// +// @category Import + +import ghidra.app.script.GhidraScript; +import ghidra.app.services.DataTypeQueryService; +import ghidra.program.model.address.Address; +import ghidra.program.model.data.DataType; +import ghidra.program.model.listing.Data; +import ghidra.program.model.listing.Function; +import ghidra.program.model.symbol.Namespace; +import ghidra.program.model.symbol.SourceType; +import ghidra.program.model.symbol.Symbol; + +import java.io.FileReader; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + + +public class EnhancedImport extends GhidraScript{ + @Override + public void run() throws Exception { + final FileReader in = new FileReader(askFile("Select input file", "OK")); + final List lines = in.readAllLines(); + in.close(); + + for (int i = 0; i < lines.size(); i++) { + final String[] parts = lines.get(i).split("\t");; + final Address addr = toAddr(parts[0]); + + switch (parts[1]) { + case "data": importData(addr, parts); break; + case "func": importFunc(addr, parts); break; + default: throw new Exception( + "Symbol type \"" + parts[1] + + "\" on line " + Integer.toString(i) + + " is not \"data\" or \"func\"" + ); + } + } + } + + private void importData( + final Address addr, + final String[] parts + ) throws Exception { + final String name = unqualified(parts[3]); + + print("Importing data symbol \"" + parts[3] + "\"..."); + + // Create symbol + final Namespace ns = importNamespace(parts[3]); + final Symbol s = Optional.ofNullable(getSymbolAt(addr)) + .orElse(createLabel(addr, name, ns, true, SourceType.USER_DEFINED)); + + // Create data (TODO: parse type name to get base name, then pass base type to PointerDataType and ArrayDataType constructors to create final type) + final List foundTypes = state.getTool() + .getService(DataTypeQueryService.class) + .findDataTypes(parts[2], null); + if (foundTypes.size() == 0) { + println(" can't find data type \"" + parts[2] + "\", skipping."); + return; + } + + final DataType t = foundTypes.get(0); // Boldly assume first is right + + clearListing(addr, addr.add(Math.max(t.getLength(), 1) - 1)); + currentProgram.getListing().createData(addr, t); + + println(" done."); + } + + private static String unqualified(final String qualifiedName) { + /* Strips the namespaces off of a qualified name */ + final String[] parts = qualifiedName.split("::"); + return parts[parts.length - 1]; + } + + private Namespace importNamespace(final String qualifiedName) throws Exception { + /* Creates namespaces from the given name, returning the deepest one + Returns null if the qualified name is in the global namespace. + */ + final String[] parts = qualifiedName.split("::"); + + if (parts.length < 2) return null; + + final String[] names = Arrays.copyOfRange(parts, 0, parts.length - 1); + + Namespace ns = null; + for (final String name : names) ns = createNamespace(ns, name); + + return ns; + } + + private void importFunc( + final Address addr, + final String[] parts + ) throws Exception { + println("TODO: function \"" + parts[6] + "\""); + } +}