52 lines
2.6 KiB
Java
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();
|
|
}
|
|
}
|