// Map virtual methods to classes via RTTI-labelled vftables. // Usage (postScript): VTableMap.java // Writes: class, vftable_address, slot, function_address, function_name import ghidra.app.script.GhidraScript; import ghidra.program.model.address.*; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.*; import java.io.*; import java.nio.file.*; public class VTableMap extends GhidraScript { @Override public void run() throws Exception { Path out = Paths.get(getScriptArgs()[0]); int ptr = currentProgram.getDefaultPointerSize(); Listing listing = currentProgram.getListing(); SymbolTable st = currentProgram.getSymbolTable(); try (PrintWriter w = new PrintWriter(Files.newBufferedWriter(out))) { w.println("class\tvftable\tslot\tfunction\tname"); for (Symbol s : st.getSymbols("vftable")) { String cls = s.getParentNamespace().getName(true); Address a = s.getAddress(); for (int slot = 0; slot < 512; slot++) { Address p = a.add((long) slot * ptr); if (slot > 0 && st.getPrimarySymbol(p) != null && st.getPrimarySymbol(p).getSource() != SourceType.DEFAULT) break; // next labelled object long v = currentProgram.getMemory().getLong(p); Address t; try { t = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(v); } catch (Exception e) { break; } Function f = getFunctionAt(t); if (f == null) break; w.println(cls + "\t0x" + a + "\t" + slot + "\t0x" + t + "\t" + f.getName(true)); } } } println("vtable map written"); } }