// Export Ghidra decompiler output for every non-external, non-thunk function. // Usage (postScript): ExportDecomp.java // Writes /functions/.c and /index.tsv // (address, namespace, name, body_bytes, status). Output is Ghidra pseudocode, not original source. import ghidra.app.script.GhidraScript; import ghidra.app.decompiler.*; import ghidra.program.model.listing.*; import java.io.*; import java.nio.file.*; public class ExportDecomp extends GhidraScript { @Override public void run() throws Exception { String[] args = getScriptArgs(); Path out = Paths.get(args[0]); Path fdir = out.resolve("functions"); Files.createDirectories(fdir); DecompInterface d = new DecompInterface(); DecompileOptions opts = new DecompileOptions(); d.setOptions(opts); d.toggleCCode(true); d.toggleSyntaxTree(false); d.openProgram(currentProgram); String sha = currentProgram.getExecutableSHA256(); try (PrintWriter idx = new PrintWriter(Files.newBufferedWriter(out.resolve("index.tsv")))) { idx.println("address\tnamespace\tname\tbody_bytes\tstatus"); FunctionIterator it = currentProgram.getFunctionManager().getFunctions(true); int n = 0; while (it.hasNext() && !monitor.isCancelled()) { Function f = it.next(); if (f.isExternal() || f.isThunk()) continue; String addr = "0x" + f.getEntryPoint().toString(); String ns = f.getParentNamespace().isGlobal() ? "" : f.getParentNamespace().getName(true); DecompileResults r = d.decompileFunction(f, 60, monitor); String status; if (r != null && r.decompileCompleted() && r.getDecompiledFunction() != null) { String hdr = "/* " + currentProgram.getName() + " sha256 " + sha + "\n * Ghidra " + getGhidraVersion() + " decompiler output for " + addr + " " + f.getName(true) + "\n * Pseudocode, not original source. */\n"; Files.writeString(fdir.resolve(addr + ".c"), hdr + r.getDecompiledFunction().getC()); status = "ok"; } else { status = "fail:" + (r == null ? "null" : r.getErrorMessage().replaceAll("\\s+", " ")); } idx.println(addr + "\t" + ns + "\t" + f.getName() + "\t" + f.getBody().getNumAddresses() + "\t" + status); if (++n % 500 == 0) println("exported " + n); } println("done " + n); } d.dispose(); } }