diff options
Diffstat (limited to 'userspace/cuda/tools/ghidra/ApplyNameMap.java')
| -rw-r--r-- | userspace/cuda/tools/ghidra/ApplyNameMap.java | 86 |
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)" : "")); + } +} |
