NationalSecurityAgency/ghidra · error · UnsupportedOperationException
TODO: Unoptimized byte diff
Error message
TODO: Unoptimized byte diff
What it means
An explicit UnsupportedOperationException marking an unimplemented code path in trace-view byte differencing. When the memory map reports blockSize == 0 (no block-optimized storage), the byte-by-byte comparison algorithm is not implemented, so the diff aborts.
Source
Thrown at Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/diff/DebuggerTraceViewDiffPlugin.java:558
TraceMemoryManager mm = trace.getMemoryManager();
AddressSetView known1 = mm.getAddressesWithState(snap1, StatePredicate.IS_KNOWN);
AddressSetView known2 = mm.getAddressesWithState(snap2, StatePredicate.IS_KNOWN);
//AddressSet knownEither = known1.union(known2);
AddressSet knownBoth = known1.intersect(known2); // Will need byte-by-byte examination
// Symmetric difference in state counts as difference?
// TODO: Should that be togglable?
AddressSet diff = new AddressSet(); //knownEither;
//knownEither = null; // Don't need knownEither anymore. Avoid accidental use
//diff.delete(knownBoth);
int blockSize = mm.getBlockSize();
if (blockSize == 0) {
throw new UnsupportedOperationException("TODO: Unoptimized byte diff");
}
ByteBuffer buf1 = ByteBuffer.allocate(blockSize);
ByteBuffer buf2 = ByteBuffer.allocate(blockSize);
while (!knownBoth.isEmpty()) {
Address next = knownBoth.getMinAddress();
Long mrs1 = mm.getSnapOfMostRecentChangeToBlock(snap1, next);
Long mrs2 = mm.getSnapOfMostRecentChangeToBlock(snap2, next);
if (Objects.equals(mrs1, mrs2)) {
knownBoth.delete(blockFor(blockSize, next));
continue;
}
int len = lenRemainsBlock(blockSize, next.getOffset());
buf1.clear();
buf1.limit(len);
if (len != mm.getBytes(snap1, next, buf1)) {
throw new AssertionError("Read failed");View on GitHub (pinned to d5f144c24d)
Solutions
- Use snapshots/traces whose memory manager supports block-optimized storage (non-zero block size).
- Run the diff against a recorded emulator target rather than a synthetic/empty trace.
- File a feature request / contribute the unoptimized byte-diff path upstream (it is a TODO).
- Fall back to a manual byte comparison via TraceMemoryBuffer over the knownBoth address set.
Example fix
// before
int blockSize = mm.getBlockSize();
if (blockSize == 0) {
throw new UnsupportedOperationException("TODO: Unoptimized byte diff");
}
// after (caller-side guard)
if (mm.getBlockSize() == 0) {
Msg.warn(this, "Byte diff unavailable: memory lacks block optimization");
return;
} Defensive patterns
Strategy: validation
Validate before calling
boolean supported = trace.getMemoryManager().getBlockSize() != 0;
Type guard
static boolean diffSupported(TraceMemoryManager mm) {
return mm.getBlockSize() != 0;
} Try / catch
try {
plugin.diffSnapshots(snap1, snap2);
} catch (UnsupportedOperationException e) {
Msg.showWarn(this, null, "Diff unavailable", e.getMessage());
} Prevention
- Do not invoke the byte diff on traces lacking block-optimized memory.
- Record emulator targets to populate block metadata.
When it happens
Trigger: Invoking the trace-view diff on two snapshots whose TraceMemoryManager's block size is 0 (memory backed by an implementation without block-change tracking).
Common situations: Comparing traces or snapshots that use a memory storage backend without block optimization; diffing newly-created or synthetic traces; traces imported from formats that do not populate block metadata.
Related errors
- %s: %s
- Failed to read memory
- Could not set target memory
- Byte arrays cannot exceed length of variable
- Cannot convert '{address}' to address
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/e89e0b70c2f2a6bf.
Report an issue: GitHub.