{"record":{"id":"e89e0b70c2f2a6bf","repo":"NationalSecurityAgency/ghidra","slug":"todo-unoptimized-byte-diff","errorCode":null,"errorMessage":"TODO: Unoptimized byte diff","messagePattern":"TODO: Unoptimized byte diff","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/diff/DebuggerTraceViewDiffPlugin.java","lineNumber":558,"sourceCode":"\n\t\tTraceMemoryManager mm = trace.getMemoryManager();\n\n\t\tAddressSetView known1 = mm.getAddressesWithState(snap1, StatePredicate.IS_KNOWN);\n\t\tAddressSetView known2 = mm.getAddressesWithState(snap2, StatePredicate.IS_KNOWN);\n\n\t\t//AddressSet knownEither = known1.union(known2);\n\t\tAddressSet knownBoth = known1.intersect(known2); // Will need byte-by-byte examination\n\n\t\t// Symmetric difference in state counts as difference?\n\t\t// TODO: Should that be togglable?\n\n\t\tAddressSet diff = new AddressSet(); //knownEither;\n\t\t//knownEither = null; // Don't need knownEither anymore. Avoid accidental use\n\t\t//diff.delete(knownBoth);\n\n\t\tint blockSize = mm.getBlockSize();\n\t\tif (blockSize == 0) {\n\t\t\tthrow new UnsupportedOperationException(\"TODO: Unoptimized byte diff\");\n\t\t}\n\t\tByteBuffer buf1 = ByteBuffer.allocate(blockSize);\n\t\tByteBuffer buf2 = ByteBuffer.allocate(blockSize);\n\n\t\twhile (!knownBoth.isEmpty()) {\n\t\t\tAddress next = knownBoth.getMinAddress();\n\t\t\tLong mrs1 = mm.getSnapOfMostRecentChangeToBlock(snap1, next);\n\t\t\tLong mrs2 = mm.getSnapOfMostRecentChangeToBlock(snap2, next);\n\t\t\tif (Objects.equals(mrs1, mrs2)) {\n\t\t\t\tknownBoth.delete(blockFor(blockSize, next));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tint len = lenRemainsBlock(blockSize, next.getOffset());\n\t\t\tbuf1.clear();\n\t\t\tbuf1.limit(len);\n\t\t\tif (len != mm.getBytes(snap1, next, buf1)) {\n\t\t\t\tthrow new AssertionError(\"Read failed\");","sourceCodeStart":540,"sourceCodeEnd":576,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/diff/DebuggerTraceViewDiffPlugin.java#L540-L576","documentation":"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.","triggerScenarios":"Invoking the trace-view diff on two snapshots whose TraceMemoryManager's block size is 0 (memory backed by an implementation without block-change tracking).","commonSituations":"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.","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."],"exampleFix":"// before\nint blockSize = mm.getBlockSize();\nif (blockSize == 0) {\n    throw new UnsupportedOperationException(\"TODO: Unoptimized byte diff\");\n}\n\n// after (caller-side guard)\nif (mm.getBlockSize() == 0) {\n    Msg.warn(this, \"Byte diff unavailable: memory lacks block optimization\");\n    return;\n}","handlingStrategy":"validation","validationCode":"boolean supported = trace.getMemoryManager().getBlockSize() != 0;","typeGuard":"static boolean diffSupported(TraceMemoryManager mm) {\n    return mm.getBlockSize() != 0;\n}","tryCatchPattern":"try {\n    plugin.diffSnapshots(snap1, snap2);\n} catch (UnsupportedOperationException e) {\n    Msg.showWarn(this, null, \"Diff unavailable\", e.getMessage());\n}","preventionTips":["Do not invoke the byte diff on traces lacking block-optimized memory.","Record emulator targets to populate block metadata."],"tags":["diff","memory","unimplemented","todo","block-storage"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}