// Apply function names from tools/names.txt to the persistent Ghidra project // (run on every program; each line names its module). // // Headless usage (see tools/rename.ps1): // analyzeHeadless sacred2 -process -noanalysis // -scriptPath tools/ghidra -postScript Rename.java // // names.txt: one "module 0xADDRESS Name" per line (module as the program // name, e.g. s2logic.dll; the address at its preferred base), "Class::Method" puts the function // into a class namespace; "#" starts a comment. Functions are created where // none starts at the address yet. Names starting with "g_" label data // (globals, tables) instead of functions. // @category sacred2K import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import ghidra.app.cmd.disassemble.DisassembleCommand; import ghidra.app.script.GhidraScript; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Function; import ghidra.program.model.symbol.Namespace; import ghidra.program.model.symbol.SourceType; import ghidra.program.model.symbol.SymbolTable; public class Rename extends GhidraScript { @Override protected void run() throws Exception { String[] args = getScriptArgs(); if (args.length != 1) { printerr("usage: Rename.java "); return; } SymbolTable symbols = currentProgram.getSymbolTable(); int renamed = 0; int labelled = 0; for (String raw : Files.readAllLines(Paths.get(args[0]), StandardCharsets.UTF_8)) { String line = raw.replaceAll("#.*", "").trim(); if (line.isEmpty()) { continue; } String[] parts = line.split("\\s+"); if (parts.length != 3) { printerr("bad line: " + raw); continue; } if (!parts[0].equalsIgnoreCase(currentProgram.getName())) { continue; } parts = new String[] {parts[1], parts[2]}; Address address = toAddr(parts[0]); if (parts[1].startsWith("g_")) { createLabel(address, parts[1], true, SourceType.USER_DEFINED); labelled++; continue; } Function function = getFunctionAt(address); if (function == null) { new DisassembleCommand(address, null, true).applyTo(currentProgram, monitor); function = createFunction(address, null); } if (function == null) { printerr("no function at " + parts[0]); continue; } String name = parts[1]; Namespace namespace = currentProgram.getGlobalNamespace(); int separator = name.lastIndexOf("::"); if (separator >= 0) { String className = name.substring(0, separator); name = name.substring(separator + 2); namespace = symbols.getNamespace(className, currentProgram.getGlobalNamespace()); if (namespace == null) { namespace = symbols.createClass(currentProgram.getGlobalNamespace(), className, SourceType.USER_DEFINED); } } function.setParentNamespace(namespace); function.setName(name, SourceType.USER_DEFINED); renamed++; } println(currentProgram.getName() + ": renamed " + renamed + " functions, labelled " + labelled + " data addresses"); } }