add ghidra script to import markers as bookmarks

This commit is contained in:
2026-03-17 23:52:33 +01:00
parent 8afdee2fd2
commit 5d4d84de39

View File

@ -0,0 +1,121 @@
// CSV format per line:
// 0x401000,<count>
//
// Creates NOTE bookmarks in category: FAIL_MARKER
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.BookmarkManager;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class ImportMarkersAsBookmarks extends GhidraScript {
private static final String BOOKMARK_TYPE = "NOTE";
private static final String BOOKMARK_CATEGORY = "FAIL_MARKER";
@Override
public void run() throws Exception {
File input = askFile("Select CSV file", "Import");
BookmarkManager bm = currentProgram.getBookmarkManager();
int imported = 0;
int skipped = 0;
int lineNo = 0;
try (BufferedReader br = new BufferedReader(new FileReader(input))) {
String line;
while ((line = br.readLine()) != null) {
lineNo++;
if (monitor.isCancelled()) {
println("Cancelled.");
break;
}
line = line.trim();
if (line.isEmpty() || line.startsWith("#")) {
continue;
}
String[] parts = splitCsvLine(line);
if (parts.length < 1) {
skipped++;
printerr("Line " + lineNo + ": missing address");
continue;
}
String addrText = parts[0].trim();
String description = parts.length >= 2 ? parts[1].trim() : "";
if (addrText.isEmpty()) {
skipped++;
printerr("Line " + lineNo + ": empty address");
continue;
}
Address addr = parseAddress(addrText);
if (addr == null) {
skipped++;
printerr("Line " + lineNo + ": invalid address: " + addrText);
continue;
}
println("Adding bookmark at " + addr + " with description " + description);
bm.setBookmark(addr, BOOKMARK_TYPE, BOOKMARK_CATEGORY, description);
imported++;
}
}
println("Imported " + imported + " bookmarks.");
if (skipped > 0) {
println("Skipped " + skipped + " lines.");
}
}
public Address parseAddress(String text) {
text = text.trim();
if (text.startsWith("\"") && text.endsWith("\"") && text.length() >= 2) {
text = text.substring(1, text.length() - 1).trim();
}
if (text.startsWith("0x") || text.startsWith("0X")) {
text = text.substring(2);
}
try {
return toAddr(text);
} catch (Exception e) {
return null;
}
}
private String[] splitCsvLine(String line) {
java.util.ArrayList<String> fields = new java.util.ArrayList<>();
StringBuilder current = new StringBuilder();
boolean inQuotes = false;
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (c == '"') {
if (inQuotes && i + 1 < line.length() && line.charAt(i + 1) == '"') {
current.append('"');
i++;
} else {
inQuotes = !inQuotes;
}
} else if (c == ',' && !inQuotes) {
fields.add(current.toString());
current.setLength(0);
} else {
current.append(c);
}
}
fields.add(current.toString());
return fields.toArray(new String[0]);
}
}