1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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)" : ""));
}
}
|