// Decompile selected function recursively // @category _Reman3 // @menupath Reman3.Dump Current Function (recursive) import java.util.ArrayList; import java.util.List; import ghidra.app.script.GhidraScript; import ghidra.program.model.listing.Function; import re3lib.FunctionDumper; import re3lib.GlobalDumper; import re3lib.PCallTracer; import re3lib.RecompileConfig; import re3lib.TypeDumper; public class DumpCurrentFunctionRecursive extends GhidraScript { @Override public void run() throws Exception { RecompileConfig.INSTANCE = new RecompileConfig(this); RecompileConfig.INSTANCE.createDirectories(); GlobalDumper globalDumper = new GlobalDumper(this); globalDumper.loadGlobalManifest(); FunctionDumper functionDumper = new FunctionDumper(this, globalDumper); PCallTracer tracer = new PCallTracer(); tracer.setBlacklist(functionDumper.functionAddrBlackList); tracer.traceCalls(getFunctionContaining(currentAddress)); List functionsToDump = new ArrayList<>(); List functionsToDumpNew = new ArrayList<>(); for (Function func : tracer.out) { if (FunctionDumper.isDumpedFix(func)) continue; println("Dump: " + func.getName()); functionsToDump.add(func); if (!FunctionDumper.isDumpedAuto(func)) functionsToDumpNew.add(func); } if (!functionsToDump.isEmpty()) { String newOpt = "Only new (" + functionsToDumpNew.size() + ")"; String okOpt = "Yes (" + functionsToDump.size() + ")"; String choice = askChoice("Confirmation", "About to generate " + functionsToDump.size() + " functions (" + functionsToDumpNew.size() + " new), continue?", new ArrayList() { { add(okOpt); add(newOpt); add("No"); } }, okOpt); if (choice == okOpt) { } else if (choice == newOpt) { functionsToDump = functionsToDumpNew; } else { return; } for (Function func : functionsToDump) { functionDumper.dump(func); } if (functionDumper.createdFile) RecompileConfig.INSTANCE.touchCMakeTimestamp(); globalDumper.dumpGlobals(); globalDumper.saveGlobalManifest(); } // Dump types TypeDumper dumper = new TypeDumper(this); dumper.run(); } }