summaryrefslogtreecommitdiffstats
path: root/userspace/cuda/tools/ghidra/ApplyNameMap.java
diff options
context:
space:
mode:
Diffstat (limited to 'userspace/cuda/tools/ghidra/ApplyNameMap.java')
-rw-r--r--userspace/cuda/tools/ghidra/ApplyNameMap.java86
1 files changed, 86 insertions, 0 deletions
diff --git a/userspace/cuda/tools/ghidra/ApplyNameMap.java b/userspace/cuda/tools/ghidra/ApplyNameMap.java
new file mode 100644
index 0000000..b8be68f
--- /dev/null
+++ b/userspace/cuda/tools/ghidra/ApplyNameMap.java
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: BSD-3-Clause
+//
+// ApplyNameMap.java - Ghidra post-script: apply a symbol name map to a
+// program. This is the version-transfer hook of the Open-IOV CUDA tooling:
+// once a name map exists for version N (derived from public documentation,
+// decompiled behaviour or an earlier version), it can be applied to version
+// N+1 in seconds, so analysis effort accumulates instead of restarting.
+//
+// Input format (TSV, no header required):
+// <hex-addr> <name> [<optional namespace>]
+// Lines starting with '#' and empty lines are ignored. Addresses are file
+// virtual addresses ("libcuda+0x..."), not Ghidra image-base offsets.
+//
+// Usage (analyzeHeadless):
+// -process <program> -noanalysis \
+// -postScript ApplyNameMap.java <namemap.tsv> [--dry-run]
+//
+// The script prints how many names were applied, and leaves a
+// "cuda-names-applied" user property on the program with the map path and
+// count so a later session can see it happened.
+
+import ghidra.app.script.GhidraScript;
+import ghidra.program.model.address.Address;
+import ghidra.program.model.listing.Function;
+import ghidra.program.model.listing.Listing;
+import ghidra.program.model.symbol.SourceType;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+
+public class ApplyNameMap extends GhidraScript {
+
+ @Override
+ public void run() throws Exception {
+ String[] args = getScriptArgs();
+ if (args.length < 1) {
+ println("usage: ApplyNameMap.java <namemap.tsv> [--dry-run]");
+ return;
+ }
+ boolean dryRun = args.length > 1 && args[1].equals("--dry-run");
+ Listing listing = currentProgram.getListing();
+ long imageBase = currentProgram.getImageBase().getOffset();
+ int applied = 0, missing = 0, lines = 0;
+
+ try (BufferedReader r = new BufferedReader(new FileReader(args[0]))) {
+ String line;
+ while ((line = r.readLine()) != null && !monitor.isCancelled()) {
+ line = line.trim();
+ if (line.isEmpty() || line.startsWith("#")) continue;
+ lines++;
+ String[] parts = line.split("[ \t]+");
+ if (parts.length < 2) continue;
+ long addr;
+ try {
+ addr = Long.parseUnsignedLong(parts[0].replaceFirst("^0x", ""), 16);
+ } catch (NumberFormatException e) {
+ continue;
+ }
+ String name = parts[1];
+ // Map keys are file virtual addresses (libcuda+0x...).
+ Address a = toAddr(addr + imageBase);
+ Function f = listing.getFunctionAt(a);
+ if (f == null) {
+ missing++;
+ continue;
+ }
+ if (!dryRun) {
+ try {
+ f.setName(name, SourceType.USER_DEFINED);
+ } catch (Exception e) {
+ println(" cannot rename 0x" + Long.toHexString(addr)
+ + " -> " + name + ": " + e.getMessage());
+ continue;
+ }
+ }
+ applied++;
+ }
+ }
+ if (!dryRun) {
+ currentProgram.getOptions("OpenIOV")
+ .setString("cuda-names-applied", args[0] + " (" + applied + " names)");
+ }
+ println(String.format("[ApplyNameMap] lines=%d applied=%s missing=%d%s",
+ lines, String.valueOf(applied), missing, dryRun ? " (dry run)" : ""));
+ }
+}