// 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): // [] // Lines starting with '#' and empty lines are ignored. Addresses are file // virtual addresses ("libcuda+0x..."), not Ghidra image-base offsets. // // Usage (analyzeHeadless): // -process -noanalysis \ // -postScript ApplyNameMap.java [--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 [--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)" : "")); } }