Finish Ghidra symbol export script

This commit is contained in:
KeybadeBlox 2026-02-16 00:13:06 -05:00
parent d81bd646fa
commit 1e8ae0f72f

View file

@ -1,17 +1,19 @@
// TODO // Writes user-defined data and function symbols to a specified TSV file for
// re-import by the EnhancedImport script.
// //
// @category Export // @category Export
import ghidra.app.script.GhidraScript; import ghidra.app.script.GhidraScript;
import ghidra.program.flatapi.FlatProgramAPI; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Data; import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
import ghidra.program.model.symbol.SourceType; import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.symbol.Symbol; import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolIterator;
import java.io.FileWriter; import java.io.FileWriter;
import java.util.Arrays; import java.util.Arrays;
import java.util.Optional;
public class EnhancedExport extends GhidraScript{ public class EnhancedExport extends GhidraScript{
@ -19,41 +21,18 @@ public class EnhancedExport extends GhidraScript{
public void run() throws Exception { public void run() throws Exception {
final FileWriter out = new FileWriter(askFile("Specify output file", "OK")); final FileWriter out = new FileWriter(askFile("Specify output file", "OK"));
final SymbolIterator iter = currentProgram.getSymbolTable() for (final Symbol s : currentProgram.getSymbolTable()
.getPrimarySymbolIterator(true); .getPrimarySymbolIterator(true)) {
while (iter.hasNext() && !monitor.isCancelled()) {
final Symbol s = iter.next();
if (s.getSource() != SourceType.USER_DEFINED) continue; if (s.getSource() != SourceType.USER_DEFINED) continue;
final Object obj = s.getObject(); final Object obj = s.getObject();
if (obj != null) switch (obj) { if (obj != null) switch (obj) {
case Data d: case Data d:
out.write( outputData(s.getAddress(), d.getDataType(), s.getName(true), out);
"0x" + s.getAddress().toString() + "\t" +
"d" + "\t" +
d.getDataType().getDisplayName() + "\t" +
s.getName(true) + "\n"
);
break; break;
case Function f: case Function f:
out.write( outputFunc(s.getAddress(), f, out);
"0x" + s.getAddress().toString() + "\t" +
"f" + "\t" +
f.getSignature(true).getReturnType()
.getDisplayName() + "\t" +
f.getCallingConventionName() + "\t" +
f.getName(true) +
String.join(
"\t",
Arrays.stream(f.getSignature(true).getArguments())
.map(arg -> "\t" +
arg.getDataType().getDisplayName() + "\t" +
arg.getName()
).toArray(String[]::new)
) +
(f.hasVarArgs() ? "\t..." : "") + "\n"
);
break; break;
default: {} default: {}
@ -62,4 +41,46 @@ public class EnhancedExport extends GhidraScript{
out.close(); out.close();
} }
private static void outputData(
final Address addr,
final DataType type,
final String name,
final FileWriter out
) throws Exception {
out.write(
"0x" + addr.toString() + "\t" +
"data" + "\t" +
type.getDisplayName() + "\t" +
name + "\n"
);
}
private static void outputFunc(
final Address addr,
final Function f,
final FileWriter out
) throws Exception {
out.write(
"0x" + addr.toString() + "\t" +
"func" + "\t" +
f.getSignature(true).getReturnType()
.getDisplayName() + "\t" +
f.getCallingConventionName() + "\t" +
(f.isInline() ? "inline" : "notinline") + "\t" +
Optional.ofNullable(f.getCallFixup())
.orElse("nofixup") + "\t" +
f.getName(true) +
String.join(
"\t",
Arrays.stream(f.getSignature(true)
.getArguments())
.map(arg ->
"\t" + arg.getDataType().getDisplayName() +
"\t" + arg.getName()
).toArray(String[]::new)
) +
(f.hasVarArgs() ? "\t..." : "") + "\n"
);
}
} }