server-re/decomp/scripts/ExportDecomp.java
2026-10-14 16:45:19 -04:00

52 lines
2.6 KiB
Java

// Export Ghidra decompiler output for every non-external, non-thunk function.
// Usage (postScript): ExportDecomp.java <outDir>
// Writes <outDir>/functions/<addr>.c and <outDir>/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();
}
}