// Decompile functions of one program of the persistent Ghidra project. // // Headless usage (see tools/decompile.ps1): // analyzeHeadless sacred2 -process -noanalysis // -scriptPath tools/ghidra -postScript Decompile.java [...] // // An argument that is not a number is looked up as a symbol name (e.g. a // decorated export). Addresses without a function (e.g. methods only // reachable via a vtable) get one created first; run without -readOnly to // keep those in the project. // @category sacred2K import java.io.File; import java.io.PrintWriter; import ghidra.app.cmd.disassemble.DisassembleCommand; import ghidra.app.decompiler.DecompInterface; import ghidra.app.decompiler.DecompileOptions; import ghidra.app.decompiler.DecompileResults; import ghidra.app.script.GhidraScript; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Function; import ghidra.program.model.symbol.SymbolIterator; public class Decompile extends GhidraScript { // A hex address (0x-prefixed or 8 digits), or the address of a symbol with // that name. private Address resolve(String text) { if (text.matches("0x[0-9a-fA-F]+|[0-9a-fA-F]{8}")) { return toAddr(text); } SymbolIterator symbols = currentProgram.getSymbolTable().getSymbols(text); return symbols.hasNext() ? symbols.next().getAddress() : null; } @Override protected void run() throws Exception { String[] args = getScriptArgs(); if (args.length < 2) { printerr("usage: Decompile.java
[address...]"); return; } DecompInterface decompiler = new DecompInterface(); decompiler.setOptions(new DecompileOptions()); decompiler.openProgram(currentProgram); try (PrintWriter out = new PrintWriter(new File(args[0]), "UTF-8")) { for (int i = 1; i < args.length; i++) { Address address = resolve(args[i]); if (address == null) { out.println("// ==== " + args[i] + " ===="); out.println("// no such address or symbol"); continue; } Function function = getFunctionAt(address); if (function == null) { function = getFunctionContaining(address); } if (function == null) { new DisassembleCommand(address, null, true).applyTo(currentProgram, monitor); function = createFunction(address, null); } out.println("// ==== " + args[i] + " ===="); if (function == null) { out.println("// could not create a function here"); continue; } out.println("// " + function.getName(true) + " @ " + function.getEntryPoint() + " (" + function.getCallingConventionName() + ")"); DecompileResults result = decompiler.decompileFunction(function, 120, monitor); if (result.decompileCompleted()) { out.println(result.getDecompiledFunction().getC()); } else { out.println("// decompile failed: " + result.getErrorMessage()); } } } finally { decompiler.dispose(); } } }