server-re/decomp/scripts/VTableMap.java
2026-10-14 16:45:19 -04:00

39 lines
1.8 KiB
Java

// Map virtual methods to classes via RTTI-labelled vftables.
// Usage (postScript): VTableMap.java <outFile.tsv>
// 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");
}
}