import ghidra.app.script.GhidraScript; import ghidra.app.decompiler.DecompInterface; import ghidra.app.decompiler.DecompileResults; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.FunctionManager; import ghidra.program.model.address.Address; import java.io.PrintWriter; import java.io.FileWriter; public class DumpVtables extends GhidraScript { @Override public void run() throws Exception { long[][] vts = { {0x1824abb90L, 64}, // SpectralProcessor {0x1824ac7a8L, 64}, // Soothe2ModuleBase {0x1824ab7c0L, 64}, // CloudyAudioProcessor }; DecompInterface di = new DecompInterface(); di.openProgram(currentProgram); FunctionManager fm = currentProgram.getFunctionManager(); PrintWriter pw = new PrintWriter(new java.io.BufferedWriter(new FileWriter("/home/m/re-tools/decomp_vtables.txt", false))); for (long[] vt : vts) { long base = vt[0]; int n = (int) vt[1]; pw.println("############ VTABLE 0x" + Long.toHexString(base) + " (" + n + " slots) ############"); for (int i = 0; i < n; i++) { Address va = currentProgram.getAddressFactory().getDefaultAddressSpace(). getAddress(base + i * 8L); long tgt = (long) currentProgram.getMemory().getLong(va); if (tgt < 0x180000000L || tgt > 0x182a00000L) { pw.println(" [" + i + "] 0x" + Long.toHexString(tgt) + " (invalid/enc)"); continue; } Address a = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(tgt); Function f = fm.getFunctionAt(a); long sz = (f == null) ? 0 : f.getBody().getNumAddresses(); pw.println(" [" + i + "] 0x" + Long.toHexString(tgt) + " size=" + sz); if (f != null && sz >= 40) { DecompileResults res = di.decompileFunction(f, 60, monitor); if (res != null && res.getDecompiledFunction() != null) { pw.println(" --- C ---"); pw.println(res.getDecompiledFunction().getC()); } } } } pw.close(); di.dispose(); println("DUMP_VT_DONE"); } }