diff --git a/java/ghidra/DumpCurrentFunctionFix.java b/java/ghidra/DumpCurrentFunctionFix.java new file mode 100644 index 00000000..868d1a4a --- /dev/null +++ b/java/ghidra/DumpCurrentFunctionFix.java @@ -0,0 +1,40 @@ +// Script to export decompiled C code for selected function from Ghidra as Fix type +// @category _Reman3 +// @menupath Reman3.Dump Current Function (Fix) + +import ghidra.app.script.GhidraScript; +import ghidra.program.model.listing.Function; +import re3lib.FunctionDumper; +import re3lib.GlobalDumper; +import re3lib.RemanConfig; +import re3lib.FunctionDatabase; + +public class DumpCurrentFunctionFix extends GhidraScript { + @Override + public void run() throws Exception { + RemanConfig.INSTANCE = new RemanConfig(this); + RemanConfig.INSTANCE.createDirectories(); + + try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) { + GlobalDumper globalDumper = new GlobalDumper(this, functionDatabase); + globalDumper.loadGlobalManifest(); + FunctionDumper functionDumper = new FunctionDumper(this, functionDatabase, globalDumper); + + // Force Fix type instead of Auto + functionDumper.forceFixType = true; + + Function currentFunction = getFunctionContaining(currentAddress); + if (currentFunction != null) { + functionDumper.dump(currentFunction); + } else { + println("No function found at the current address."); + } + + if (functionDumper.createdFile) + RemanConfig.INSTANCE.touchCMakeTimestamp(); + + globalDumper.dumpGlobals(); + globalDumper.saveGlobalManifest(); + } + } +} \ No newline at end of file diff --git a/java/ghidra/re3lib/FunctionDumper.java b/java/ghidra/re3lib/FunctionDumper.java index 131b88ff..bb890e71 100644 --- a/java/ghidra/re3lib/FunctionDumper.java +++ b/java/ghidra/re3lib/FunctionDumper.java @@ -33,6 +33,9 @@ public class FunctionDumper { public boolean createdFile = false; // Collects functions called by the current function public HashSet functionReferences = new HashSet<>(); + + // Add flag to force Fix type + public boolean forceFixType = false; static final Pattern fieldAccessRegex = Pattern.compile("^_([0-9]+)_([0-9]+)_$"); @@ -112,13 +115,33 @@ public class FunctionDumper { Address entrypoint = function.getEntryPoint(); List entries = functionDatabase.findEntriesByAddress(entrypoint); FunctionDatabase.Type targetType = FunctionDatabase.Type.Auto; - for (FunctionDatabase.FunctionEntry entry : entries) { - script.println("Found existing decompiled entry at " + entry.file + " - " + entry.name); - if (targetType != FunctionDatabase.Type.Ref) { + + // Handle forceFixType flag + if (forceFixType) { + targetType = FunctionDatabase.Type.Fix; + + // Remove any existing Auto entries for this function + for (FunctionDatabase.FunctionEntry entry : entries) { + if (entry.type == FunctionDatabase.Type.Auto) { + script.println("Removing existing Auto entry: " + entry.file); + if (entry.file.exists()) { + entry.file.delete(); + } + functionDatabase.removeEntryAt(entry.file.toString()); + } + } + } else { + // Original logic for determining target type + for (FunctionDatabase.FunctionEntry entry : entries) { + script.println("Found existing decompiled entry at " + entry.file + " - " + entry.name); if (entry.type == FunctionDatabase.Type.Fix) { targetType = FunctionDatabase.Type.Ref; } } + } + + // Always remove stub entries regardless of mode + for (FunctionDatabase.FunctionEntry entry : entries) { if (entry.type == FunctionDatabase.Type.Stub) { // Remove the stub file, since we now use the decompiled file File stubFile = entry.file; @@ -134,10 +157,23 @@ public class FunctionDumper { File targetFilename = null; if (targetType == FunctionDatabase.Type.Ref) { targetFilename = new File(RemanConfig.INSTANCE.dirDecompRef, fileName); + } else if (targetType == FunctionDatabase.Type.Fix) { + targetFilename = new File(RemanConfig.INSTANCE.dirDecompFix, fileName); } else { targetFilename = new File(RemanConfig.INSTANCE.dirDecompAuto, fileName); } + + // Handle overwrite prompting for Fix type if (targetFilename.exists()) { + if (targetType == FunctionDatabase.Type.Fix) { + script.println("Fix file already exists: " + targetFilename); + boolean overwrite = script.askYesNo("Overwrite existing Fix file?", + "The Fix file " + targetFilename.getName() + " already exists. Do you want to overwrite it?"); + if (!overwrite) { + script.println("Aborted: User chose not to overwrite existing Fix file."); + return; + } + } targetFilename.delete(); script.println("Overwriting existing file " + targetFilename); } else {