import ghidra.app.script.GhidraScript; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Function; import ghidra.program.model.symbol.Reference; import ghidra.program.model.symbol.ReferenceIterator; import java.io.File; import java.io.PrintWriter; public class XrefReport extends GhidraScript { @Override protected void run() throws Exception { String[] args = getScriptArgs(); if (args.length < 2) { println("usage: XrefReport [...]"); return; } File output = new File(args[0]); output.getParentFile().mkdirs(); long imageBase = currentProgram.getImageBase().getOffset(); try (PrintWriter writer = new PrintWriter(output, "UTF-8")) { writer.printf("# %s xrefs%n%n", currentProgram.getName()); for (int i = 1; i < args.length; i++) { long raw = Long.decode(args[i]); long absolute = raw < imageBase ? imageBase + raw : raw; Address target = toAddr(absolute); Function targetFunction = getFunctionContaining(target); writer.printf("## %s at %s%n%n", args[i], target); writer.printf("Target function: `%s`%n%n", targetFunction == null ? "(none)" : targetFunction.getName()); writer.println("| From | Ref type | Caller function |"); writer.println("| --- | --- | --- |"); int count = 0; ReferenceIterator references = currentProgram.getReferenceManager().getReferencesTo(target); while (references.hasNext()) { Reference reference = references.next(); Address from = reference.getFromAddress(); Function caller = getFunctionContaining(from); writer.printf( "| `%s` | `%s` | `%s` |%n", from, reference.getReferenceType(), caller == null ? "" : caller.getName()); count++; } if (count == 0) { writer.println("| (none) | | |"); } writer.println(); } } } }