summaryrefslogtreecommitdiffstats
path: root/userspace/cuda/tools/ghidra/ApplyNameMap.java
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-23 12:11:04 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-23 12:11:04 -0400
commit21b8ebc9db1d0ae649d6406087ea22b54e3b5775 (patch)
tree192aa5d3c76e0cf3a785936d9902c6848609d37e /userspace/cuda/tools/ghidra/ApplyNameMap.java
parent631bd20c63a4058775a4fa549b9473915c918020 (diff)
downloadopen-iov-21b8ebc9db1d0ae649d6406087ea22b54e3b5775.tar.gz
open-iov-21b8ebc9db1d0ae649d6406087ea22b54e3b5775.zip
userspace/cuda: add CUDA userspace driver analysis, tooling and name maps
Add the analysis of the NVIDIA CUDA userspace driver used by Open-IOV VMs: * docs/01-08: architecture (layers, object model, threads, sync, memory, channels, launch), build and execution model, the driver/kernel/GPU interface contract, virtualization approaches, the 570.144 decompilation map with the corrected libcuda crash path and the current engine-topology blocker, tooling, and a version-upgrade playbook. * tools/: version-agnostic toolchain - stdlib ELF/interface toolkit (exports, unwind-table function map, wrapper resolution, version delta, crash address decode), callgraph walker, corpus annotator, and Ghidra analysis/decompilation/name-map scripts with resumable parallel drivers. * 570.144/annotations/: our name map (exports + resolved wrappers + verified internals) and subsystem index, tracked so naming work accumulates. * READ-ME-FIRST.md: reading guide with the fast lookup recipes. The full decompiled corpus and annotated corpus stay untracked (vendor- derived, gitignored under the version run/ tree).
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)" : ""));
+ }
+}