forked from UsernameFodder/pmdsky-debug
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathImportSymbolsJson.java
More file actions
135 lines (114 loc) · 4.7 KB
/
Copy pathImportSymbolsJson.java
File metadata and controls
135 lines (114 loc) · 4.7 KB
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Imports symbols from a JSON file
// @author UsernameFodder
// @category Import
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Collections;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionManager;
import ghidra.program.model.symbol.SourceType;
import ghidra.util.exception.DuplicateNameException;
public class ImportSymbolsJson extends GhidraScript {
private static final String COMMENT_TAG = "=== imported description ===\n";
private static class SymbolEntry {
String type;
String name;
Object address;
String description;
List<String> aliases;
public List<String> getAliases() {
return aliases != null ? aliases : Collections.emptyList();
}
}
@Override
public void run() throws Exception {
File jsonFile = askFile("Select symbol JSON file", "Import");
List<SymbolEntry> symbols = loadSymbols(jsonFile);
for (SymbolEntry symbol : symbols) {
processSymbol(symbol);
}
}
private List<SymbolEntry> loadSymbols(File file) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(file.toPath())) {
Gson gson = new Gson();
TypeToken<List<SymbolEntry>> symbolListType = new TypeToken<List<SymbolEntry>>() {};
return gson.fromJson(reader, symbolListType.getType());
}
}
private void processSymbol(SymbolEntry symbol) throws Exception {
Address address = parseAddress(symbol.address);
if (address == null) {
printerr("Skipping symbol with invalid address: " + symbol.name);
return;
}
if ("function".equals(symbol.type)) {
handleFunction(address, symbol.name);
} else {
println("Created primary label " + symbol.name + " at address " + address);
createLabel(address, symbol.name, true);
}
for (String alias : symbol.getAliases()) {
println("Created label " + alias + " at address " + address);
createLabel(address, alias, false);
}
if (symbol.description != null && !symbol.description.isEmpty()) {
updatePlateComment(address, symbol.description);
}
}
private void handleFunction(Address address, String name) throws Exception {
FunctionManager functionManager = currentProgram.getFunctionManager();
Function func = functionManager.getFunctionAt(address);
if (func == null) {
createFunction(address, name);
println("Created function " + name + " at address " + address);
} else {
String oldName = func.getName();
try {
func.setName(name, SourceType.USER_DEFINED);
} catch (DuplicateNameException e) {
// This can happen if name already exists, but is not the
// primary label, which can happen if it was overridden by a
// different label. In this case, just set it as the primary.
createLabel(address, name, true);
}
println("Renamed function " + oldName + " to " + name + " at address " + address);
}
}
private Address parseAddress(Object addrObj) {
if (addrObj == null) {
return null;
}
if (addrObj instanceof Number) {
return toAddr(((Number) addrObj).longValue());
}
String addrStr = addrObj.toString().trim();
if (addrStr.startsWith("0x") || addrStr.startsWith("0X")) {
return toAddr(Long.parseLong(addrStr.substring(2), 16));
}
return toAddr(Long.parseLong(addrStr));
}
private void updatePlateComment(Address address, String description) {
String existingComment = getPlateComment(address);
String updatedComment;
if (existingComment == null || existingComment.isEmpty()) {
updatedComment = COMMENT_TAG + description;
} else {
String[] parts = existingComment.split(COMMENT_TAG);
if (parts.length == 1) {
// Append description if the comment tag was not found
updatedComment = parts[0] + "\n\n" + COMMENT_TAG + description;
} else {
// Replace old description while preserving the comment prefix
updatedComment = parts[0] + COMMENT_TAG + description;
}
}
setPlateComment(address, updatedComment);
}
}