Files
tdkpin/original/tools/ExportDecompilation.java
T
2026-08-22 15:52:52 +02:00

82 lines
3.7 KiB
Java

// Export every function in the current Ghidra program as one traceable C-like file.
// @category TDKPIN
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;
import ghidra.app.decompiler.DecompInterface;
import ghidra.app.decompiler.DecompileResults;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionIterator;
import ghidra.program.model.mem.MemoryBlock;
public class ExportDecompilation extends GhidraScript {
@Override
public void run() throws Exception {
String[] args = getScriptArgs();
if (args.length != 2) {
throw new IllegalArgumentException("usage: ExportDecompilation.java OUTPUT_C OUTPUT_TSV");
}
DecompInterface decompiler = new DecompInterface();
decompiler.toggleCCode(true);
decompiler.toggleSyntaxTree(true);
if (!decompiler.openProgram(currentProgram)) {
throw new IllegalStateException("cannot open program in decompiler");
}
int total = 0;
int internal = 0;
int external = 0;
int succeeded = 0;
int failed = 0;
try (PrintWriter c = new PrintWriter(new BufferedWriter(new FileWriter(args[0])));
PrintWriter ledger = new PrintWriter(new BufferedWriter(new FileWriter(args[1])))) {
c.println("/*");
c.println(" * Raw Ghidra decompilation of TDKPIN.EXE.");
c.println(" * Function boundaries and names are analysis artifacts, not original source symbols.");
c.println(" */");
c.println();
ledger.println("address\tname\tkind\tstatus\tmessage");
FunctionIterator functions = currentProgram.getFunctionManager().getFunctions(true);
while (functions.hasNext() && !monitor.isCancelled()) {
Function function = functions.next();
total++;
String address = function.getEntryPoint().toString();
String name = function.getName();
MemoryBlock block = currentProgram.getMemory().getBlock(function.getEntryPoint());
boolean imported = function.isExternal() || block == null ||
!block.isInitialized() || "EXTERNAL".equals(block.getName());
if (imported) {
external++;
ledger.printf("%s\t%s\texternal\tn/a\timported function%n", address, name);
continue;
}
internal++;
DecompileResults result = decompiler.decompileFunction(function, 120, monitor);
c.printf("/* ===== %s %s ===== */%n", address, name);
if (result.decompileCompleted() && result.getDecompiledFunction() != null) {
c.println(result.getDecompiledFunction().getC());
succeeded++;
ledger.printf("%s\t%s\tinternal\tok\t%n", address, name);
} else {
String message = result.getErrorMessage();
c.printf("/* DECOMPILATION FAILED: %s */%n%n", message);
failed++;
ledger.printf("%s\t%s\tinternal\tfailed\t%s%n", address, name,
message == null ? "" : message.replace('\t', ' ').replace('\n', ' '));
}
}
c.printf("/* SUMMARY: total=%d internal=%d external=%d succeeded=%d failed=%d */%n",
total, internal, external, succeeded, failed);
println(String.format("Exported total=%d internal=%d external=%d succeeded=%d failed=%d",
total, internal, external, succeeded, failed));
} finally {
decompiler.dispose();
}
}
}