// SPDX-License-Identifier: BSD-3-Clause // // DecompileAt.java - Ghidra post-script: decompile the function containing a // given file virtual address. Version-agnostic copy of the per-version // helper used with ghidra_decompile_at.sh. // // Usage: // analyzeHeadless -process -readOnly -noanalysis \ // -postScript DecompileAt.java [outfile] // // If the address does not fall inside a known function, the script tries to // disassemble at the address; if the target is outside any function body it // prints a comment with the nearest preceding function instead of failing. import ghidra.app.script.GhidraScript; import ghidra.app.decompiler.DecompInterface; import ghidra.app.decompiler.DecompileResults; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.FunctionIterator; import ghidra.program.model.listing.Listing; import java.io.FileWriter; public class DecompileAt extends GhidraScript { @Override public void run() throws Exception { String[] args = getScriptArgs(); if (args.length < 1) { println("usage: DecompileAt.java [outfile]"); return; } long fileAddr = Long.parseUnsignedLong(args[0].replaceFirst("^0x", ""), 16); // Arguments are FILE virtual addresses (libcuda+0x...). Ghidra may have // loaded the program at a non-zero image base (0x100000 in this build), // so translate before resolving. If image base is 0 this is a no-op. long imageBase = currentProgram.getImageBase().getOffset(); Address addr = toAddr(fileAddr + imageBase); long target = addr.getOffset(); Function f = getFunctionContaining(addr); if (f == null) { Listing listing = currentProgram.getListing(); FunctionIterator it = listing.getFunctions(addr, false); if (it.hasNext()) f = it.next(); } if (f == null) { disassemble(addr); f = createFunction(addr, null); } StringBuilder sb = new StringBuilder(); if (f == null) { sb.append("// no function at 0x").append(Long.toHexString(target)).append("\n"); } else { DecompInterface dif = new DecompInterface(); dif.toggleCCode(true); dif.toggleSyntaxTree(true); dif.openProgram(currentProgram); DecompileResults res = dif.decompileFunction(f, 300, monitor); sb.append("// function ").append(f.getName()) .append(" at libcuda+0x") .append(Long.toHexString(f.getEntryPoint().getOffset() - imageBase)) .append(" (program 0x").append(Long.toHexString(f.getEntryPoint().getOffset())) .append(", query file 0x").append(Long.toHexString(fileAddr)).append(")\n"); if (res != null && res.decompileCompleted()) { sb.append("#include \n") .append("typedef unsigned char undefined1;\n") .append("typedef unsigned short undefined2;\n") .append("typedef unsigned int undefined4;\n") .append("typedef unsigned long long undefined8;\n") .append("typedef long long longlong;\n") .append("typedef unsigned long long ulonglong;\n\n") .append(res.getDecompiledFunction().getC()); } else { sb.append("// decompilation failed\n"); } } String text = sb.toString(); if (args.length > 1) { try (FileWriter w = new FileWriter(args[1])) { w.write(text); } } println(text); } }