Fix persistent global mapping

This commit is contained in:
2024-09-23 23:14:47 +08:00
parent 80c072e757
commit 3d9181f654
8 changed files with 226 additions and 44 deletions

View File

@@ -13,20 +13,16 @@ public class DumpCurrentFunction extends GhidraScript {
public void run() throws Exception {
RecompileConfig.INSTANCE = new RecompileConfig(this);
RecompileConfig.INSTANCE.createDirectories();
GlobalDumper globalDumper = new GlobalDumper(this);
try {
globalDumper.loadGlobalManifest();
} catch (Exception e) {
println("No global manifest found");
}
globalDumper.loadGlobalManifest();
FunctionDumper functionDumper = new FunctionDumper(this, globalDumper);
Function currentFunction = getFunctionContaining(currentAddress);
if (currentFunction != null) {
functionDumper.dump(currentFunction);
functionDumper.dump(currentFunction);
} else {
println("No function found at the current address.");
println("No function found at the current address.");
}
globalDumper.dumpGlobals();

View File

@@ -13,13 +13,22 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import javax.xml.datatype.DatatypeFactory;
import ghidra.app.script.GhidraScript;
import ghidra.app.services.DataTypeManagerService;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.AbstractStringDataType;
import ghidra.program.model.data.Array;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.DataTypePath;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.data.Undefined;
import ghidra.program.model.listing.Data;
import ghidra.program.model.pcode.HighSymbol;
import ghidra.util.data.DataTypeParser;
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
public class GlobalDumper {
@@ -44,26 +53,58 @@ public class GlobalDumper {
manifestFile = new File(RecompileConfig.INSTANCE.outputDir, "globals.txt");
}
public void loadGlobalManifest() throws Exception {
public boolean loadGlobalManifest() throws Exception {
// Globals are stored in the format of
// <address> || <name> || <type>
if (!manifestFile.exists()) {
script.println("Global manifest file not found: " + manifestFile);
return false;
}
// Get the dataTypeManagerService
DataTypeManagerService dataTypeManagerService = (DataTypeManagerService) script.getState().getTool()
.getService(DataTypeManagerService.class);
DataTypeManager dtm = script.getCurrentProgram().getDataTypeManager();
DataTypeParser dtp = new DataTypeParser(dataTypeManagerService, AllowedDataTypes.ALL);
try (BufferedReader reader = new BufferedReader(new FileReader(manifestFile))) {
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split(" || ");
if (parts.length == 3) {
String address = parts[0];
String name = parts[1];
String typeName = parts[2];
DataType type = script.getCurrentProgram().getDataTypeManager().getDataType(typeName);
globalAddrs.put(script.parseAddress(address), new GlobalRec(script.parseAddress(address), name, type));
String[] parts = line.split("\\|\\|");
if (parts.length == 4) {
Address address = script.parseAddress(parts[0].trim());
String name = parts[1].trim();
String categoryPath = parts[2].trim();
String dataTypePath = parts[3].trim();
DataTypePath typePath = new DataTypePath(categoryPath, dataTypePath);
DataType type = null;
type = dtm.getDataType(typePath);
if (type == null) {
// script.println("Parsing type: " + dataTypePath);
type = dtp.parse(dataTypePath);
}
if (type == null) {
script.println("WARNING: Failed to find type: " + dataTypePath + " for global: " + name + " at " + address);
continue;
}
globalAddrs.put(address, new GlobalRec(address, name, type));
} else {
script.println("Invalid global manifest line: " + line);
}
}
}
script.println("Loaded " + globalAddrs.size() + " globals from " + manifestFile);
return true;
}
public void addGlobal(Address addr, HighSymbol sym) {
globalAddrs.put(addr, new GlobalRec(addr, sym.getName(), sym.getDataType()));
DataType dt = sym.getDataType();
if (dt == null) {
script.println("WARNING: Missing type for global: " + sym.getName() + " at " + addr);
return;
}
globalAddrs.put(addr, new GlobalRec(addr, sym.getName(), dt));
}
String escapeCString(String str) {
@@ -172,12 +213,23 @@ public class GlobalDumper {
}
public void saveGlobalManifest() throws Exception {
File backupFile = new File(manifestFile.getParentFile(), manifestFile.getName() + ".bak");
if (backupFile.exists()) {
if (!backupFile.delete()) {
throw new Exception("Failed to delete backup file: " + backupFile + ", globals will not be saved!");
}
}
if (!manifestFile.renameTo(backupFile))
throw new Exception("Failed to rename manifest file: " + manifestFile + ", globals will not be saved!");
try (PrintWriter writer = new PrintWriter(manifestFile)) {
script.println("Saving global manifest to " + manifestFile);
GlobalRec[] globals = globalAddrs.values().toArray(new GlobalRec[0]);
Arrays.sort(globals, (a, b) -> a.address.compareTo(b.address));
for (GlobalRec global : globals) {
writer.println(global.address.toString() + " || " + global.name + " || " + global.type.getDisplayName());
DataTypePath path = global.type.getDataTypePath();
writer.println(global.address.toString() + " || " + global.name + " || " + path.getCategoryPath() + " || "
+ path.getDataTypeName());
}
}
}