// Decompile selected function recursively (until a given number of new functions is reached) // @category _Reman3 // @menupath Reman3.Dump N Functions import java.util.ArrayList; import java.util.HashSet; import java.util.List; import ghidra.app.script.GhidraScript; import ghidra.pcodeCPort.address.Address; import ghidra.program.model.listing.Function; import re3lib.FunctionDumper; import re3lib.GlobalDumper; import re3lib.PCallTracer; import re3lib.RecompileConfig; import re3lib.TypeDumper; public class DumpCurrentFunctionN extends GhidraScript { final int NumFunctions = 8; class Entry { Function function; } class QueueEntry { Function function; List callees; } HashSet
visited = new HashSet<>(); QueueEntry enter(Function function) { if (visited.contains(function.getEntryPoint())) return null; visited.add(function.getEntryPoint()); QueueEntry entry = new QueueEntry(); entry.function = function; function.getCalledFunctions(monitor); } @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
queue = new ArrayList<>(); 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(); } }