Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/build_on_tag_push.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: Ghidra Extension Publish

env:
ghidra-url: https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_11.3.1_build/ghidra_11.3.1_PUBLIC_20250219.zip
ghidra-zip-filename: ghidra_11.3.1_PUBLIC_20250219.zip
ghidra-directory: ghidra_11.3.1_PUBLIC
ghidra-url: https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_12.0.4_build/ghidra_12.0.4_PUBLIC_20260303.zip
ghidra-zip-filename: ghidra_12.0.4_PUBLIC_20260303.zip
ghidra-directory: ghidra_12.0.4_PUBLIC

on:
push:
Expand Down
2 changes: 1 addition & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{
"label": "Build",
"type": "shell",
"command": "gradle -PGHIDRA_INSTALL_DIR=/opt/ghidra_11.3.1_PUBLIC",
"command": "gradle -PGHIDRA_INSTALL_DIR=/opt/ghidra_12.0.4_PUBLIC",
"group": "build",
"options": {
"cwd": "${workspaceFolder}/lightkeeper"
Expand Down
8 changes: 4 additions & 4 deletions lightkeeper/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@
//----------------------START "DO NOT MODIFY" SECTION------------------------------
def ghidraInstallDir

if (System.env.GHIDRA_INSTALL_DIR) {
ghidraInstallDir = System.env.GHIDRA_INSTALL_DIR
}
else if (project.hasProperty("GHIDRA_INSTALL_DIR")) {
if (project.hasProperty("GHIDRA_INSTALL_DIR")) {
ghidraInstallDir = project.getProperty("GHIDRA_INSTALL_DIR")
}
else if (System.env.GHIDRA_INSTALL_DIR) {
ghidraInstallDir = System.env.GHIDRA_INSTALL_DIR
}

if (ghidraInstallDir) {
apply from: new File(ghidraInstallDir).getCanonicalPath() + "/support/buildExtension.gradle"
Expand Down
10 changes: 7 additions & 3 deletions lightkeeper/src/main/java/lightkeeper/io/file/DynamoRioFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import lightkeeper.io.module.ModuleReader;

public class DynamoRioFile implements IEventListener {
protected final String HEADER = "DRCOV VERSION: 2";
protected final Pattern HEADER_REGEX = Pattern.compile("^DRCOV VERSION: (?<version>[23])$");
protected final Pattern FLAVOUR_REGEX = Pattern.compile("^DRCOV FLAVOR: (?<flavour>.*)$");
protected final Pattern TABLE_REGEX = Pattern
.compile("^Module Table: (version (?<version>\\d+), count )?(?<count>\\d+)$");
Expand All @@ -31,6 +31,7 @@ public class DynamoRioFile implements IEventListener {
protected File file;

protected String flavour;
protected int fileVersion;
protected int tableVersion;
protected int tableCount;
protected ArrayList<ModuleEntry> modules = new ArrayList<>();
Expand Down Expand Up @@ -78,9 +79,12 @@ private void readHeader(TaskMonitor monitor) throws CancelledException, IOExcept
monitor.setMessage("Reading header");
var headerLine = reader.readLine();
addMessage(headerLine);
if (!headerLine.equals(HEADER)) {
throw new IOException(String.format("Invalid header: '%s' expected '%s'", headerLine, HEADER));
var headerMatcher = HEADER_REGEX.matcher(headerLine);
if (!headerMatcher.matches()) {
throw new IOException(String.format("Invalid header: '%s'", headerLine));
}
fileVersion = Integer.parseInt(headerMatcher.group("version"));
addMessage(String.format("Detected file version: %d", fileVersion));
monitor.checkCancelled();
}

Expand Down
19 changes: 16 additions & 3 deletions lightkeeper/src/main/java/lightkeeper/io/module/ModuleReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,29 @@ public class ModuleReader {
"^\\s*(?<id>\\d+), (0x)?(?<start>[0-9a-fA-F]+), (0x)?(?<end>[0-9a-fA-F]+), (0x)?(?<entry>[0-9a-fA-F]+), (?<path>.+)$");

protected final String COLUMN_3_HDR_WIN = "Columns: id, containing_id, start, end, entry, checksum, timestamp, path";
protected final Pattern COLUMN_3_HDR_WIN_FMT = null;
protected final Pattern COLUMN_3_HDR_WIN_FMT = Pattern.compile(
"^\\s*(?<id>\\d+), \\s*(?<containingid>\\d+), (0x)?(?<start>[0-9a-fA-F]+), (0x)?(?<end>[0-9a-fA-F]+), (0x)?(?<entry>[0-9a-fA-F]+), (0x)?(?<checksum>[0-9a-fA-F]+), (0x)?(?<timestamp>[0-9a-fA-F]+), (?<path>.+)$");

protected final String COLUMN_3_HDR_LINUX = "Columns: id, containing_id, start, end, entry, path";
protected final Pattern COLUMN_3_HDR_LINUX_FMT = null;
protected final Pattern COLUMN_3_HDR_LINUX_FMT = Pattern.compile(
"^\\s*(?<id>\\d+), \\s*(?<containingid>\\d+), (0x)?(?<start>[0-9a-fA-F]+), (0x)?(?<end>[0-9a-fA-F]+), (0x)?(?<entry>[0-9a-fA-F]+), (?<path>.+)$");

protected final String COLUMN_4_HDR_WIN = "Columns: id, containing_id, start, end, entry, offset, checksum, timestamp, path";
protected final Pattern COLUMN_4_HDR_WIN_FMT = null;
protected final Pattern COLUMN_4_HDR_WIN_FMT = Pattern.compile(
"^\\s*(?<id>\\d+), \\s*(?<containingid>\\d+), (0x)?(?<start>[0-9a-fA-F]+), (0x)?(?<end>[0-9a-fA-F]+), (0x)?(?<entry>[0-9a-fA-F]+), (0x)?(?<offset>[0-9a-fA-F]+), (0x)?(?<checksum>[0-9a-fA-F]+), (0x)?(?<timestamp>[0-9a-fA-F]+), (?<path>.+)$");

protected final String COLUMN_4_HDR_LINUX = "Columns: id, containing_id, start, end, entry, offset, path";
protected final Pattern COLUMN_4_HDR_LINUX_FMT = Pattern.compile(
"^\\s*(?<id>\\d+), \\s*(?<containingid>\\d+), (0x)?(?<start>[0-9a-fA-F]+), (0x)?(?<end>[0-9a-fA-F]+), (0x)?(?<entry>[0-9a-fA-F]+), (0x)?(?<offset>[0-9a-fA-F]+), (?<path>.+)$");

protected final String COLUMN_5_HDR_WIN = "Columns: id, containing_id, start, end, entry, offset, preferred_base, checksum, timestamp, path";
protected final Pattern COLUMN_5_HDR_WIN_FMT = Pattern.compile(
"^\\s*(?<id>\\d+), \\s*(?<containingid>\\d+), (0x)?(?<start>[0-9a-fA-F]+), (0x)?(?<end>[0-9a-fA-F]+), (0x)?(?<entry>[0-9a-fA-F]+), (0x)?(?<offset>[0-9a-fA-F]+), (0x)?(?<preferredbase>[0-9a-fA-F]+), (0x)?(?<checksum>[0-9a-fA-F]+), (0x)?(?<timestamp>[0-9a-fA-F]+), (?<path>.+)$");

protected final String COLUMN_5_HDR_LINUX = "Columns: id, containing_id, start, end, entry, offset, preferred_base, path";
protected final Pattern COLUMN_5_HDR_LINUX_FMT = Pattern.compile(
"^\\s*(?<id>\\d+), \\s*(?<containingid>\\d+), (0x)?(?<start>[0-9a-fA-F]+), (0x)?(?<end>[0-9a-fA-F]+), (0x)?(?<entry>[0-9a-fA-F]+), (0x)?(?<offset>[0-9a-fA-F]+), (0x)?(?<preferredbase>[0-9a-fA-F]+), (?<path>.+)$");

protected final Pattern NULL_CHECKSUM = Pattern.compile("0+");

private List<IEventListener> listeners = new ArrayList<>();
Expand Down Expand Up @@ -71,6 +82,8 @@ public ModuleReader(TaskMonitor monitor, BinaryLineReader reader, int tableVersi
formats.add(new ModuleTriplet(3, COLUMN_3_HDR_LINUX, COLUMN_3_HDR_LINUX_FMT, true, false));
formats.add(new ModuleTriplet(4, COLUMN_4_HDR_WIN, COLUMN_4_HDR_WIN_FMT, true, true));
formats.add(new ModuleTriplet(4, COLUMN_4_HDR_LINUX, COLUMN_4_HDR_LINUX_FMT, true, false));
formats.add(new ModuleTriplet(5, COLUMN_5_HDR_WIN, COLUMN_5_HDR_WIN_FMT, true, true));
formats.add(new ModuleTriplet(5, COLUMN_5_HDR_LINUX, COLUMN_5_HDR_LINUX_FMT, true, false));

readColumnHeader();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ protected List<ModuleEntry> getSelectedModules(DynamoRioFile file) throws IOExce
var api = plugin.getApi();
var programFileName = api.getCurrentProgram().getName();
var selectedModules = file.getModules().stream()
.filter(m -> new File(m.getPath()).getName().trim().equals(programFileName))
.filter(m -> new File(m.getPath()).getName().trim().equalsIgnoreCase(programFileName))
.collect(Collectors.toList());
if (selectedModules.isEmpty()) {
addMessage(String.format("Found %d modules", file.getModules().size()));
Expand Down Expand Up @@ -112,11 +112,12 @@ public void update(TaskMonitor monitor) throws CancelledException, IOException {
var selectedModules = getSelectedModules(file);

var misMatch = selectedModules.stream().filter(m -> m.getChecksum() != null)
.filter(m -> m.getChecksum().length() == md5.length())
.filter(m -> !m.getChecksum().equalsIgnoreCase(md5)).findFirst();
if (misMatch.isPresent()) {
var module = misMatch.get();
throw new IOException(String.format("Module entry '%s' has invalid checksum '%s'", module.getPath(),
module.getChecksum()));
addErrorMessage(String.format("Warning: module '%s' has checksum '%s' but loaded binary has MD5 '%s' - coverage may be inaccurate",
module.getPath(), module.getChecksum(), md5));
}

Set<Integer> ids = this.getSelectedModuleIds(selectedModules);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import docking.widgets.table.AbstractSortedTableModel;
import docking.widgets.table.ColumnSortState.SortDirection;
import docking.widgets.table.TableSortStateEditor;
import ghidra.util.Swing;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import lightkeeper.model.ICoverageModelListener;
Expand Down Expand Up @@ -68,6 +69,6 @@ public Object getColumnValueForRow(CoverageListRow row, int columnIndex) {

@Override
public void modelChanged(TaskMonitor monitor) throws CancelledException {
fireTableDataChanged();
Swing.runLater(() -> fireTableDataChanged());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import docking.widgets.table.AbstractSortedTableModel;
import docking.widgets.table.ColumnSortState.SortDirection;
import docking.widgets.table.TableSortStateEditor;
import ghidra.util.Swing;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import lightkeeper.model.ICoverageModelListener;
Expand Down Expand Up @@ -70,6 +71,6 @@ public Object getColumnValueForRow(CoverageTableRow row, int columnIndex) {

@Override
public void modelChanged(TaskMonitor monitor) throws CancelledException {
fireTableDataChanged();
Swing.runLater(() -> fireTableDataChanged());
}
}