diff --git a/ghidra/ghidra_scripts/EnhancedImport.java b/ghidra/ghidra_scripts/EnhancedImport.java index 3bdf040..00fcdcb 100644 --- a/ghidra/ghidra_scripts/EnhancedImport.java +++ b/ghidra/ghidra_scripts/EnhancedImport.java @@ -5,15 +5,20 @@ import ghidra.app.script.GhidraScript; import ghidra.app.services.DataTypeQueryService; import ghidra.program.model.address.Address; +import ghidra.program.model.data.ArrayDataType; import ghidra.program.model.data.DataType; +import ghidra.program.model.data.PointerDataType; 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 ghidra.util.StringUtilities; import java.io.FileReader; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -34,7 +39,7 @@ public class EnhancedImport extends GhidraScript{ case "func": importFunc(addr, parts); break; default: throw new Exception( "Symbol type \"" + parts[1] + - "\" on line " + Integer.toString(i) + + "\" on line " + String.valueOf(i) + " is not \"data\" or \"func\"" ); } @@ -45,7 +50,7 @@ public class EnhancedImport extends GhidraScript{ final Address addr, final String[] parts ) throws Exception { - final String name = unqualified(parts[3]); + final String name = unqualified(parts[3]); print("Importing data symbol \"" + parts[3] + "\"..."); @@ -54,21 +59,14 @@ public class EnhancedImport extends GhidraScript{ 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; - } + // Create data + final Optional t_maybe = makeType(parts[2]); + if (t_maybe.orElse(null) instanceof DataType t) { + clearListing(addr, addr.add(Math.max(t.getLength(), 1) - 1)); + currentProgram.getListing().createData(addr, t); - 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."); + println(" done."); + } else println(", skipping."); } private static String unqualified(final String qualifiedName) { @@ -93,6 +91,64 @@ public class EnhancedImport extends GhidraScript{ return ns; } + private Optional makeType(final String type) throws Exception { + /* Attempt to create the described type from a known base type */ + final String baseName = StringUtilities.findWord(type, 0); + final List foundTypes = state.getTool() + .getService(DataTypeQueryService.class) + .findDataTypes(baseName, null); + if (foundTypes.size() == 0) { + print(" can't find data type \"" + baseName + "\""); + return Optional.empty(); + } + + return Optional.of(derivedType( + foundTypes.get(0), // Boldly assume first is right + type.substring(baseName.length()) + )); + } + + private static DataType derivedType( + final DataType t, + final String modifiers + ) throws Exception { + /* Return the given datatype with given pointer/array modifiers */ + DataType ret = t; + for (int i = 0; i < modifiers.length(); i++) switch (modifiers.charAt(i)) { + case '*': + ret = new PointerDataType(ret); + continue; + + case '[': + // Read array dimensions + final ArrayList dims = new ArrayList<>(); + do { + final String n = StringUtilities.findWord(modifiers, i+1); + i += n.length() + 1; + + dims.add(Integer.valueOf(n)); + } while (modifiers.charAt(i) == '['); + + // Apply array + Collections.reverse(dims); + for (int dim : dims) ret = new ArrayDataType(ret, dim); + + continue; + + case ' ': + continue; + + default: + throw new Exception( + "Unexpected character \"" + + String.valueOf(modifiers.charAt(i)) + + "\" in type modifiers" + ); + } + + return ret; + } + private void importFunc( final Address addr, final String[] parts