diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceDefinedDataRegisterView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceDefinedDataRegisterView.java index cbfdfdcf7a..06ad1084d5 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceDefinedDataRegisterView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceDefinedDataRegisterView.java @@ -26,7 +26,8 @@ public interface TraceDefinedDataRegisterView extends TraceDefinedDataView, TraceBaseDefinedRegisterView { default TraceData create(Range lifespan, Register register, DataType dataType) throws CodeUnitInsertionException { + TraceRegisterUtils.requireByteBound(register); return create(lifespan, register.getAddress(), dataType, - TraceRegisterUtils.byteLengthOf(register)); + register.getNumBytes()); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryRegisterSpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryRegisterSpace.java index b7e55d3473..a3926477a7 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryRegisterSpace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryRegisterSpace.java @@ -54,13 +54,50 @@ public interface TraceMemoryRegisterSpace extends TraceMemorySpace { return getStates(snap, TraceRegisterUtils.rangeForRegister(register)); } + /** + * Set the value of a register at the given snap + * + *

+ * IMPORTANT: The trace database cannot track the state ({@link TraceMemoryState#KNOWN}, + * etc.) with per-bit accuracy. It only has byte precision. If the given value specifies, e.g., + * only a single bit, then the entire byte will become marked {@link TraceMemoryState#KNOWN}, + * even though the remaining 7 bits could technically be unknown. + * + * @param snap the snap + * @param value the register value + * @return the number of bytes written + */ default int setValue(long snap, RegisterValue value) { - ByteBuffer buf = TraceRegisterUtils.bufferForValue(value); - return putBytes(snap, value.getRegister().getAddress(), buf); + if (!value.hasAnyValue()) { + return 0; + } + Register reg = value.getRegister(); + if (!value.hasValue() || !TraceRegisterUtils.isByteBound(reg)) { + RegisterValue old = getValue(snap, reg.getBaseRegister()); + // Do not use .getRegisterValue, as that will zero unmasked bits + // Instead, we'll pass the original register to bufferForValue + value = old.combineValues(value); + } + ByteBuffer buf = TraceRegisterUtils.bufferForValue(reg, value); + return putBytes(snap, reg.getAddress(), buf); } + /** + * Write bytes at the given snap and register address + * + *

+ * Note that bit-masked registers are not properly heeded. If the caller wishes to preserve + * non-masked bits, it must first retrieve the current value and combine it with the desired + * value. The caller must also account for any bit shift in the passed buffer. Alternatively, + * consider {@link #setValue(long, RegisterValue)}. + * + * @param snap the snap + * @param register the register to modify + * @param buf the buffer of bytes to write + * @return the number of bytes written + */ default int putBytes(long snap, Register register, ByteBuffer buf) { - int byteLength = TraceRegisterUtils.byteLengthOf(register); + int byteLength = register.getNumBytes(); int limit = buf.limit(); buf.limit(Math.min(limit, buf.position() + byteLength)); int result = putBytes(snap, register.getAddress(), buf); @@ -79,7 +116,7 @@ public interface TraceMemoryRegisterSpace extends TraceMemorySpace { } default int getBytes(long snap, Register register, ByteBuffer buf) { - int byteLength = TraceRegisterUtils.byteLengthOf(register); + int byteLength = register.getNumBytes(); int limit = buf.limit(); buf.limit(Math.min(limit, buf.position() + byteLength)); int result = getBytes(snap, register.getAddress(), buf); @@ -87,8 +124,21 @@ public interface TraceMemoryRegisterSpace extends TraceMemorySpace { return result; } + /** + * Remove a value from the given time and register + * + *

+ * IMPORANT: The trace database cannot track the state ({@link TraceMemoryState#KNOWN}, + * etc.) with per-bit accuracy. It only has byte precision. If the given register specifies, + * e.g., only a single bit, then the entire byte will become marked + * {@link TraceMemoryState#UNKNOWN}, even though the remaining 7 bits could technically be + * known. + * + * @param snap the snap + * @param register the register + */ default void removeValue(long snap, Register register) { - int byteLength = TraceRegisterUtils.byteLengthOf(register); + int byteLength = register.getNumBytes(); removeBytes(snap, register.getAddress(), byteLength); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceRegisterUtils.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceRegisterUtils.java index 43f4f6f30b..7724c45cf7 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceRegisterUtils.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceRegisterUtils.java @@ -34,16 +34,7 @@ public enum TraceRegisterUtils { public static AddressRange rangeForRegister(Register register) { Address address = register.getAddress(); - return new AddressRangeImpl(address, address.add(register.getMinimumByteSize() - 1)); - } - - public static int byteLengthOf(Register register) { - int bitLength = register.getBitLength(); - if ((bitLength & 7) != 0) { - throw new IllegalArgumentException( - "Cannot work with sub-byte boundaries. Consider using the base register."); - } - return bitLength >> 3; + return new AddressRangeImpl(address, address.add(register.getNumBytes() - 1)); } public static byte[] padOrTruncate(byte[] arr, int length) { @@ -58,33 +49,22 @@ public enum TraceRegisterUtils { return Arrays.copyOfRange(arr, arr.length - length, arr.length); } - public static ByteBuffer bufferForValue(RegisterValue value) { - byte[] arr = value.getSignedValue().toByteArray(); - int byteLength = byteLengthOf(value.getRegister()); - arr = padOrTruncate(arr, byteLength); - if (!value.getRegister().isBigEndian()) { - ArrayUtils.reverse(arr); + public static ByteBuffer bufferForValue(Register reg, RegisterValue value) { + byte[] bytes = value.toBytes().clone(); + int start = bytes.length / 2; + // NB: I guess contextreg is always big? + if (!reg.isBigEndian() && !reg.isProcessorContext()) { + ArrayUtils.reverse(bytes, start, bytes.length); } - return ByteBuffer.wrap(arr); - } - - public static int computeMaskOffset(byte[] arr) { - for (int i = 0; i < arr.length; i++) { - switch (arr[i]) { - case -1: - return i; - case 0: - continue; - default: - throw new IllegalArgumentException( - "Can only handle sub-registers on byte boundaries"); - } - } - throw new IllegalArgumentException("No value"); + int offset = TraceRegisterUtils.computeMaskOffset(reg); + return ByteBuffer.wrap(bytes, start + offset, reg.getNumBytes()); } public static int computeMaskOffset(Register reg) { - return computeMaskOffset(reg.getBaseMask()); + if (reg.isBaseRegister()) { + return 0; + } + return reg.getOffset() - reg.getBaseRegister().getOffset(); } public static int computeMaskOffset(RegisterValue value) { @@ -162,21 +142,38 @@ public enum TraceRegisterUtils { return regs.getValue(snap, reg.getBaseRegister()).combineValues(rv); } - public static RegisterValue getRegisterValue(Register register, + public static RegisterValue getRegisterValue(Register reg, BiConsumer readAction) { - int byteLength = TraceRegisterUtils.byteLengthOf(register); - byte[] mask = register.getBaseMask(); + /* + * The byte array for reg values spans the whole base register, but we'd like to avoid + * over-reading, so we'll zero in on the bytes actually included in the mask. We'll then + * have to handle endianness and such. The regval instance should then apply the actual mask + * for the sub-register, if applicable. + */ + int byteLength = reg.getNumBytes(); + byte[] mask = reg.getBaseMask(); ByteBuffer buf = ByteBuffer.allocate(mask.length * 2); buf.put(mask); - int maskOffset = TraceRegisterUtils.computeMaskOffset(mask); + int maskOffset = TraceRegisterUtils.computeMaskOffset(reg); int startVal = buf.position() + maskOffset; buf.position(startVal); buf.limit(buf.position() + byteLength); - readAction.accept(register.getAddress(), buf); + readAction.accept(reg.getAddress(), buf); byte[] arr = buf.array(); - if (!register.isBigEndian()) { - ArrayUtils.reverse(arr, startVal, startVal + byteLength); + if (!reg.isBigEndian() && !reg.isProcessorContext()) { + ArrayUtils.reverse(arr, mask.length, buf.capacity()); + } + return new RegisterValue(reg, arr); + } + + public static boolean isByteBound(Register register) { + return register.getLeastSignificantBit() % 8 == 0 && register.getBitLength() % 8 == 0; + } + + public static void requireByteBound(Register register) { + if (!isByteBound(register)) { + throw new IllegalArgumentException( + "Cannot work with sub-byte registers. Consider a parent, instead."); } - return new RegisterValue(register, arr); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/ToyDBTraceBuilder.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/ToyDBTraceBuilder.java index 273c1c81e0..09686703b0 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/ToyDBTraceBuilder.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/ToyDBTraceBuilder.java @@ -49,6 +49,8 @@ import ghidra.trace.database.memory.DBTraceMemoryManager; import ghidra.trace.database.symbol.DBTraceReference; import ghidra.trace.database.thread.DBTraceThread; import ghidra.trace.database.thread.DBTraceThreadManager; +import ghidra.trace.model.ImmutableTraceAddressSnapRange; +import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.language.TraceGuestLanguage; import ghidra.util.Msg; import ghidra.util.database.DBOpenMode; @@ -94,6 +96,10 @@ public class ToyDBTraceBuilder implements AutoCloseable { return new AddressRangeImpl(addr(start), addr(end)); } + public TraceAddressSnapRange srange(long snap, long start, long end) { + return new ImmutableTraceAddressSnapRange(addr(start), addr(end), snap, snap); + } + public AddressRange drng(long start, long end) { return new AddressRangeImpl(data(start), data(end)); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerTest.java index 98f3fb292d..7f30a6dfdc 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerTest.java @@ -27,83 +27,65 @@ import java.util.Map.Entry; import org.junit.*; -import com.google.common.collect.Range; - import db.DBHandle; import ghidra.program.model.address.*; import ghidra.program.model.lang.*; -import ghidra.program.util.DefaultLanguageService; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.trace.database.DBTrace; +import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.database.stack.DBTraceStack; import ghidra.trace.database.thread.DBTraceThread; -import ghidra.trace.model.ImmutableTraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.memory.TraceMemoryState; +import ghidra.trace.util.LanguageTestWatcher; import ghidra.util.database.*; import ghidra.util.task.ConsoleTaskMonitor; import ghidra.util.task.TaskMonitor; public abstract class AbstractDBTraceMemoryManagerTest extends AbstractGhidraHeadlessIntegrationTest { - protected Language toyLanguage; - protected DBTrace trace; + protected ToyDBTraceBuilder b; protected DBTraceMemoryManager memory; + @Rule + public LanguageTestWatcher testLanguage = + new LanguageTestWatcher(getLanguageID().getIdAsString()); + protected abstract LanguageID getLanguageID(); @Before public void setUp() throws IOException { - toyLanguage = DefaultLanguageService.getLanguageService() - .getLanguage(getLanguageID()); - trace = new DBTrace("Testing", toyLanguage.getDefaultCompilerSpec(), this); - memory = trace.getMemoryManager(); + b = new ToyDBTraceBuilder("Testing", testLanguage.getLanguage()); + try (UndoableTransaction tid = b.startTransaction()) { + b.trace.getTimeManager().createSnapshot("Initialize"); + } + memory = b.trace.getMemoryManager(); } @After public void tearDown() { - trace.release(this); - } - - protected Address addr(long offset) { - return toyLanguage.getDefaultDataSpace().getAddress(offset); - } - - protected AddressRange range(long start, long end) { - return new AddressRangeImpl(addr(start), addr(end)); - } - - protected TraceAddressSnapRange srange(long snap, long minOff, long maxOff) { - return new ImmutableTraceAddressSnapRange(addr(minOff), addr(maxOff), snap, snap); - } - - protected AddressSetView set(AddressRange... ranges) { - AddressSet result = new AddressSet(); - for (AddressRange rng : ranges) { - result.add(rng); - } - return result; + b.close(); } @Test public void testSetState() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - memory.setState(0, addr(0x4000), addr(0x5000), TraceMemoryState.KNOWN); + try (UndoableTransaction tid = b.startTransaction()) { + memory.setState(0, b.addr(0x4000), b.addr(0x5000), TraceMemoryState.KNOWN); // +1 Overflow - memory.setState(0, range(0x4000, 0x7fffffffffffffffL), TraceMemoryState.KNOWN); - memory.setState(0, range(0x4000, 0xffffffffffffffffL), TraceMemoryState.KNOWN); + memory.setState(0, b.range(0x4000, 0x7fffffffffffffffL), TraceMemoryState.KNOWN); + memory.setState(0, b.range(0x4000, 0xffffffffffffffffL), TraceMemoryState.KNOWN); // NOP - memory.setState(0, addr(0x4500), addr(0x5000), TraceMemoryState.KNOWN); + memory.setState(0, b.addr(0x4500), b.addr(0x5000), TraceMemoryState.KNOWN); AddressSet set = new AddressSet(); - set.add(addr(0x2000), addr(0x2500)); - set.add(addr(0x4000), addr(0x5000)); // NOP when set + set.add(b.addr(0x2000), b.addr(0x2500)); + set.add(b.addr(0x4000), b.addr(0x5000)); // NOP when set memory.setState(0, set, TraceMemoryState.KNOWN); // ERR - AddressSpace regs = trace.getBaseAddressFactory().getRegisterSpace(); + AddressSpace regs = b.trace.getBaseAddressFactory().getRegisterSpace(); try { memory.setState(0, regs.getAddress(0x4000), TraceMemoryState.KNOWN); fail(); @@ -126,42 +108,42 @@ public abstract class AbstractDBTraceMemoryManagerTest @Test public void testSetGetStateOneByte() { - assertEquals(null, memory.getState(3, addr(0x4000))); + assertEquals(null, memory.getState(3, b.addr(0x4000))); - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - memory.setState(3, addr(0x4000), TraceMemoryState.KNOWN); + try (UndoableTransaction tid = b.startTransaction()) { + memory.setState(3, b.addr(0x4000), TraceMemoryState.KNOWN); } - assertEquals(TraceMemoryState.KNOWN, memory.getState(3, addr(0x4000))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, addr(0x4001))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, addr(0x3fff))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(2, addr(0x4000))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(4, addr(0x4000))); + assertEquals(TraceMemoryState.KNOWN, memory.getState(3, b.addr(0x4000))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, b.addr(0x4001))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, b.addr(0x3fff))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(2, b.addr(0x4000))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(4, b.addr(0x4000))); - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - memory.setState(3, addr(0x4000), TraceMemoryState.ERROR); + try (UndoableTransaction tid = b.startTransaction()) { + memory.setState(3, b.addr(0x4000), TraceMemoryState.ERROR); } - assertEquals(TraceMemoryState.ERROR, memory.getState(3, addr(0x4000))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, addr(0x4001))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, addr(0x3fff))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(2, addr(0x4000))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(4, addr(0x4000))); + assertEquals(TraceMemoryState.ERROR, memory.getState(3, b.addr(0x4000))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, b.addr(0x4001))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, b.addr(0x3fff))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(2, b.addr(0x4000))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(4, b.addr(0x4000))); } @Test public void testSetRangeGetState() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - memory.setState(3, addr(0x4000), addr(0x5000), TraceMemoryState.KNOWN); + try (UndoableTransaction tid = b.startTransaction()) { + memory.setState(3, b.addr(0x4000), b.addr(0x5000), TraceMemoryState.KNOWN); } - assertEquals(TraceMemoryState.KNOWN, memory.getState(3, addr(0x4800))); - assertEquals(TraceMemoryState.KNOWN, memory.getState(3, addr(0x4000))); - assertEquals(TraceMemoryState.KNOWN, memory.getState(3, addr(0x5000))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, addr(0x3fff))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, addr(0x5001))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(2, addr(0x4800))); - assertEquals(TraceMemoryState.UNKNOWN, memory.getState(4, addr(0x4800))); + assertEquals(TraceMemoryState.KNOWN, memory.getState(3, b.addr(0x4800))); + assertEquals(TraceMemoryState.KNOWN, memory.getState(3, b.addr(0x4000))); + assertEquals(TraceMemoryState.KNOWN, memory.getState(3, b.addr(0x5000))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, b.addr(0x3fff))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(3, b.addr(0x5001))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(2, b.addr(0x4800))); + assertEquals(TraceMemoryState.UNKNOWN, memory.getState(4, b.addr(0x4800))); } protected static void assertSnapState(long snap, TraceMemoryState state, @@ -172,216 +154,258 @@ public abstract class AbstractDBTraceMemoryManagerTest @Test public void testGetMostRecentStateSingleRange() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - memory.setState(3, addr(0x4000), addr(0x5000), TraceMemoryState.KNOWN); + try (UndoableTransaction tid = b.startTransaction()) { + memory.setState(3, b.addr(0x4000), b.addr(0x5000), TraceMemoryState.KNOWN); } - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x3fff))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x4000))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x3fff))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x4000))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x5001))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x3fff))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x4000))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x3fff))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x4000))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x5001))); - assertEquals(null, memory.getMostRecentStateEntry(4, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(4, addr(0x3fff))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(4, addr(0x4000))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(4, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(4, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(4, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(4, b.addr(0x3fff))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(4, b.addr(0x4000))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(4, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(4, b.addr(0x5001))); } @Test public void testGetMostRecentStateSameSnap() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - memory.setState(3, addr(0x4000), addr(0x5000), TraceMemoryState.KNOWN); - memory.setState(3, addr(0x4020), addr(0x4080), TraceMemoryState.ERROR); + try (UndoableTransaction tid = b.startTransaction()) { + memory.setState(3, b.addr(0x4000), b.addr(0x5000), TraceMemoryState.KNOWN); + memory.setState(3, b.addr(0x4020), b.addr(0x4080), TraceMemoryState.ERROR); } - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x3fff))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x4000))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x401f))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x4020))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x4080))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x4081))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x3fff))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x4000))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x401f))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x4020))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x4080))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x4081))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x5001))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x3fff))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x4000))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x401f))); - assertSnapState(3, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(3, addr(0x4020))); - assertSnapState(3, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(3, addr(0x4080))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x4081))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x3fff))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x4000))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x401f))); + assertSnapState(3, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(3, b.addr(0x4020))); + assertSnapState(3, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(3, b.addr(0x4080))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x4081))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x5001))); - assertEquals(null, memory.getMostRecentStateEntry(5, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(5, addr(0x3fff))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(5, addr(0x4000))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(5, addr(0x401f))); - assertSnapState(3, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(5, addr(0x4020))); - assertSnapState(3, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(5, addr(0x4080))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(5, addr(0x4081))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(5, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(5, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(5, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(5, b.addr(0x3fff))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(5, b.addr(0x4000))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(5, b.addr(0x401f))); + assertSnapState(3, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(5, b.addr(0x4020))); + assertSnapState(3, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(5, b.addr(0x4080))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(5, b.addr(0x4081))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(5, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(5, b.addr(0x5001))); } @Test public void testGetMostRecentStateLaterBefore() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - memory.setState(3, addr(0x4000), addr(0x5000), TraceMemoryState.KNOWN); - memory.setState(4, addr(0x3000), addr(0x3500), TraceMemoryState.ERROR); + try (UndoableTransaction tid = b.startTransaction()) { + memory.setState(3, b.addr(0x4000), b.addr(0x5000), TraceMemoryState.KNOWN); + memory.setState(4, b.addr(0x3000), b.addr(0x3500), TraceMemoryState.ERROR); } - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x2fff))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x3000))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x3500))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x3501))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x3fff))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x4000))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x2fff))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x3000))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x3500))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x3501))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x3fff))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x4000))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x5001))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x2fff))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x3000))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x3500))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x3501))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x3fff))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x4000))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x2fff))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x3000))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x3500))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x3501))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x3fff))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x4000))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x5001))); - assertEquals(null, memory.getMostRecentStateEntry(4, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(4, addr(0x2fff))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(4, addr(0x3000))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(4, addr(0x3500))); - assertEquals(null, memory.getMostRecentStateEntry(4, addr(0x3501))); - assertEquals(null, memory.getMostRecentStateEntry(4, addr(0x3fff))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(4, addr(0x4000))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(4, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(4, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(4, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(4, b.addr(0x2fff))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(4, b.addr(0x3000))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(4, b.addr(0x3500))); + assertEquals(null, memory.getMostRecentStateEntry(4, b.addr(0x3501))); + assertEquals(null, memory.getMostRecentStateEntry(4, b.addr(0x3fff))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(4, b.addr(0x4000))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(4, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(4, b.addr(0x5001))); - assertEquals(null, memory.getMostRecentStateEntry(5, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(5, addr(0x2fff))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(5, addr(0x3000))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(5, addr(0x3500))); - assertEquals(null, memory.getMostRecentStateEntry(5, addr(0x3501))); - assertEquals(null, memory.getMostRecentStateEntry(5, addr(0x3fff))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(5, addr(0x4000))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(5, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(5, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(5, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(5, b.addr(0x2fff))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(5, b.addr(0x3000))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(5, b.addr(0x3500))); + assertEquals(null, memory.getMostRecentStateEntry(5, b.addr(0x3501))); + assertEquals(null, memory.getMostRecentStateEntry(5, b.addr(0x3fff))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(5, b.addr(0x4000))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(5, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(5, b.addr(0x5001))); } @Test public void testGetMostRecentStateLaterOverStart() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - memory.setState(3, addr(0x4000), addr(0x5000), TraceMemoryState.KNOWN); - memory.setState(4, addr(0x3000), addr(0x4500), TraceMemoryState.ERROR); + try (UndoableTransaction tid = b.startTransaction()) { + memory.setState(3, b.addr(0x4000), b.addr(0x5000), TraceMemoryState.KNOWN); + memory.setState(4, b.addr(0x3000), b.addr(0x4500), TraceMemoryState.ERROR); } - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x2fff))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x3000))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x3fff))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x4000))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x4500))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x4501))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(2, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x2fff))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x3000))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x3fff))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x4000))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x4500))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x4501))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(2, b.addr(0x5001))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x2fff))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x3000))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x3fff))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x4000))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x4500))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x4501))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(3, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(3, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x2fff))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x3000))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x3fff))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x4000))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x4500))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x4501))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(3, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(3, b.addr(0x5001))); - assertEquals(null, memory.getMostRecentStateEntry(4, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(4, addr(0x2fff))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(4, addr(0x3000))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(4, addr(0x3fff))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(4, addr(0x4000))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(4, addr(0x4500))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(4, addr(0x4501))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(4, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(4, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(4, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(4, b.addr(0x2fff))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(4, b.addr(0x3000))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(4, b.addr(0x3fff))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(4, b.addr(0x4000))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(4, b.addr(0x4500))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(4, b.addr(0x4501))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(4, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(4, b.addr(0x5001))); - assertEquals(null, memory.getMostRecentStateEntry(5, addr(0))); - assertEquals(null, memory.getMostRecentStateEntry(5, addr(0x2fff))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(5, addr(0x3000))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(5, addr(0x3fff))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(5, addr(0x4000))); - assertSnapState(4, TraceMemoryState.ERROR, memory.getMostRecentStateEntry(5, addr(0x4500))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(5, addr(0x4501))); - assertSnapState(3, TraceMemoryState.KNOWN, memory.getMostRecentStateEntry(5, addr(0x5000))); - assertEquals(null, memory.getMostRecentStateEntry(5, addr(0x5001))); + assertEquals(null, memory.getMostRecentStateEntry(5, b.addr(0))); + assertEquals(null, memory.getMostRecentStateEntry(5, b.addr(0x2fff))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(5, b.addr(0x3000))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(5, b.addr(0x3fff))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(5, b.addr(0x4000))); + assertSnapState(4, TraceMemoryState.ERROR, + memory.getMostRecentStateEntry(5, b.addr(0x4500))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(5, b.addr(0x4501))); + assertSnapState(3, TraceMemoryState.KNOWN, + memory.getMostRecentStateEntry(5, b.addr(0x5000))); + assertEquals(null, memory.getMostRecentStateEntry(5, b.addr(0x5001))); } @Test public void testGetAddressesWithState() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - memory.setState(3, addr(0x4000), addr(0x7000), TraceMemoryState.KNOWN); - memory.setState(3, addr(0x5000), addr(0x6000), TraceMemoryState.ERROR); - memory.setState(4, addr(0x3000), addr(0x4800), TraceMemoryState.KNOWN); + try (UndoableTransaction tid = b.startTransaction()) { + memory.setState(3, b.addr(0x4000), b.addr(0x7000), TraceMemoryState.KNOWN); + memory.setState(3, b.addr(0x5000), b.addr(0x6000), TraceMemoryState.ERROR); + memory.setState(4, b.addr(0x3000), b.addr(0x4800), TraceMemoryState.KNOWN); } AddressSet set = new AddressSet(); - set.add(range(0x2800, 0x3800)); - set.add(range(0x3c00, 0x4800)); - set.add(range(0x4c00, 0x6100)); - set.add(range(0x8000, 0x9000)); + set.add(b.range(0x2800, 0x3800)); + set.add(b.range(0x3c00, 0x4800)); + set.add(b.range(0x4c00, 0x6100)); + set.add(b.range(0x8000, 0x9000)); AddressSet expected; AddressSetView result; expected = new AddressSet(); - expected.add(range(0x3000, 0x3800)); - expected.add(range(0x3c00, 0x4800)); + expected.add(b.range(0x3000, 0x3800)); + expected.add(b.range(0x3c00, 0x4800)); result = memory.getAddressesWithState(4, set, state -> state == TraceMemoryState.KNOWN); assertEquals(expected, set.intersect(result)); expected = new AddressSet(); - expected.add(range(0x4000, 0x4800)); - expected.add(range(0x4c00, 0x4fff)); - expected.add(range(0x6001, 0x6100)); + expected.add(b.range(0x4000, 0x4800)); + expected.add(b.range(0x4c00, 0x4fff)); + expected.add(b.range(0x6001, 0x6100)); result = memory.getAddressesWithState(3, set, state -> state == TraceMemoryState.KNOWN); assertEquals(expected, set.intersect(result)); // Test gaps expected = new AddressSet(); - expected.add(range(0x2800, 0x3800)); - expected.add(range(0x3c00, 0x3fff)); - expected.add(range(0x8000, 0x9000)); + expected.add(b.range(0x2800, 0x3800)); + expected.add(b.range(0x3c00, 0x3fff)); + expected.add(b.range(0x8000, 0x9000)); result = memory.getAddressesWithState(3, set, state -> true); assertEquals(expected, set.subtract(result)); } @Test public void testGetStates() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - memory.setState(3, addr(0x4000), addr(0x7000), TraceMemoryState.KNOWN); - memory.setState(3, addr(0x5000), addr(0x6000), TraceMemoryState.ERROR); + try (UndoableTransaction tid = b.startTransaction()) { + memory.setState(3, b.addr(0x4000), b.addr(0x7000), TraceMemoryState.KNOWN); + memory.setState(3, b.addr(0x5000), b.addr(0x6000), TraceMemoryState.ERROR); } Map expected; expected = new HashMap<>(); - expected.put(srange(3, 0x4000, 0x4fff), TraceMemoryState.KNOWN); - expected.put(srange(3, 0x5000, 0x6000), TraceMemoryState.ERROR); - expected.put(srange(3, 0x6001, 0x7000), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x8000)))); + expected.put(b.srange(3, 0x4000, 0x4fff), TraceMemoryState.KNOWN); + expected.put(b.srange(3, 0x5000, 0x6000), TraceMemoryState.ERROR); + expected.put(b.srange(3, 0x6001, 0x7000), TraceMemoryState.KNOWN); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x8000)))); } protected static Map collectAsMap( @@ -397,30 +421,34 @@ public abstract class AbstractDBTraceMemoryManagerTest @Test public void testGetMostRecentStates() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - memory.setState(3, addr(0x4000), addr(0x7000), TraceMemoryState.KNOWN); - memory.setState(3, addr(0x5000), addr(0x6000), TraceMemoryState.ERROR); - memory.setState(4, addr(0x3000), addr(0x4800), TraceMemoryState.KNOWN); + try (UndoableTransaction tid = b.startTransaction()) { + memory.setState(3, b.addr(0x4000), b.addr(0x7000), TraceMemoryState.KNOWN); + memory.setState(3, b.addr(0x5000), b.addr(0x6000), TraceMemoryState.ERROR); + memory.setState(4, b.addr(0x3000), b.addr(0x4800), TraceMemoryState.KNOWN); } Map expected; expected = new HashMap<>(); - assertEquals(expected, collectAsMap(memory.getMostRecentStates(2, range(0x2800, 0x9000)))); + assertEquals(expected, + collectAsMap(memory.getMostRecentStates(2, b.range(0x2800, 0x9000)))); expected = new HashMap<>(); - expected.put(srange(3, 0x4000, 0x4fff), TraceMemoryState.KNOWN); - expected.put(srange(3, 0x5000, 0x6000), TraceMemoryState.ERROR); - expected.put(srange(3, 0x6001, 0x7000), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getMostRecentStates(3, range(0x2800, 0x9000)))); + expected.put(b.srange(3, 0x4000, 0x4fff), TraceMemoryState.KNOWN); + expected.put(b.srange(3, 0x5000, 0x6000), TraceMemoryState.ERROR); + expected.put(b.srange(3, 0x6001, 0x7000), TraceMemoryState.KNOWN); + assertEquals(expected, + collectAsMap(memory.getMostRecentStates(3, b.range(0x2800, 0x9000)))); expected = new HashMap<>(); - expected.put(srange(4, 0x3000, 0x4800), TraceMemoryState.KNOWN); - expected.put(srange(3, 0x4801, 0x4fff), TraceMemoryState.KNOWN); - expected.put(srange(3, 0x5000, 0x6000), TraceMemoryState.ERROR); - expected.put(srange(3, 0x6001, 0x7000), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getMostRecentStates(4, range(0x2800, 0x9000)))); - assertEquals(expected, collectAsMap(memory.getMostRecentStates(5, range(0x2800, 0x9000)))); + expected.put(b.srange(4, 0x3000, 0x4800), TraceMemoryState.KNOWN); + expected.put(b.srange(3, 0x4801, 0x4fff), TraceMemoryState.KNOWN); + expected.put(b.srange(3, 0x5000, 0x6000), TraceMemoryState.ERROR); + expected.put(b.srange(3, 0x6001, 0x7000), TraceMemoryState.KNOWN); + assertEquals(expected, + collectAsMap(memory.getMostRecentStates(4, b.range(0x2800, 0x9000)))); + assertEquals(expected, + collectAsMap(memory.getMostRecentStates(5, b.range(0x2800, 0x9000)))); } protected byte[] arr(int... e) { @@ -436,7 +464,7 @@ public abstract class AbstractDBTraceMemoryManagerTest } protected int getBlockRecordCount() { - DBTraceMemorySpace space = memory.getForSpace(toyLanguage.getDefaultSpace(), false); + DBTraceMemorySpace space = memory.getForSpace(b.language.getDefaultSpace(), false); if (space == null) { return 0; } @@ -444,7 +472,7 @@ public abstract class AbstractDBTraceMemoryManagerTest } protected DBCachedObjectStore getBufferStore() { - DBTraceMemorySpace space = memory.getForSpace(toyLanguage.getDefaultSpace(), false); + DBTraceMemorySpace space = memory.getForSpace(b.language.getDefaultSpace(), false); if (space == null) { return null; } @@ -461,16 +489,16 @@ public abstract class AbstractDBTraceMemoryManagerTest @Test public void testBytes0Length() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(0, memory.putBytes(3, addr(0x4000), buf())); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(0, memory.putBytes(3, b.addr(0x4000), buf())); assertEquals(0, getBlockRecordCount()); assertEquals(0, getBufferRecordCount()); } - assertEquals(0, memory.getBytes(3, addr(0x4000), buf())); + assertEquals(0, memory.getBytes(3, b.addr(0x4000), buf())); ByteBuffer read = buf(-1, -2, -3, -4); - assertEquals(4, memory.getBytes(3, addr(0x3ffe), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x3ffe), read)); assertEquals(0, read.remaining()); // NOTE: I think this is OK, because the state ought to be UNKNOWN anyway. assertArrayEquals(arr(-1, -2, -3, -4), read.array()); @@ -478,9 +506,9 @@ public abstract class AbstractDBTraceMemoryManagerTest @Test public void testBytesSimple4Zeros() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(0, 0, 0, 0))); - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(0, 0, 0, 0))); // Should have no effect + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(0, 0, 0, 0))); + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(0, 0, 0, 0))); // Should have no effect assertEquals(1, getBlockRecordCount()); // Zeros do not require buffer backing assertEquals(0, getBufferRecordCount()); @@ -489,18 +517,18 @@ public abstract class AbstractDBTraceMemoryManagerTest // verify the corresponding change in state; Map expected; expected = new HashMap<>(); - expected.put(srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x5000)))); + expected.put(b.srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x5000)))); ByteBuffer read = buf(-1, -2, -3, -4); // Verify zeros actually written - assertEquals(4, memory.getBytes(3, addr(0x4000), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x4000), read)); assertArrayEquals(arr(0, 0, 0, 0), read.array()); } @Test public void testBytesSimple4Bytes() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(1, 2, 3, 4))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(1, 2, 3, 4))); assertEquals(1, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); } @@ -510,68 +538,68 @@ public abstract class AbstractDBTraceMemoryManagerTest // verify the corresponding change in state; Map expected; expected = new HashMap<>(); - expected.put(srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x5000)))); + expected.put(b.srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x5000)))); ByteBuffer read = ByteBuffer.allocate(4); - assertEquals(4, memory.getBytes(3, addr(0x4000), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x4000), read)); assertArrayEquals(arr(1, 2, 3, 4), read.array()); } @Test public void testBytesSpan4Bytes() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x3ffe), buf(1, 2, 3, 4))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x3ffe), buf(1, 2, 3, 4))); assertEquals(2, getBlockRecordCount()); assertEquals(2, getBufferRecordCount()); } ByteBuffer read = ByteBuffer.allocate(4); - assertEquals(4, memory.getBytes(3, addr(0x3ffe), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x3ffe), read)); assertArrayEquals(arr(1, 2, 3, 4), read.array()); } @Test public void testBytesSpan12BytesInChunks() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x3ffa), buf(1, 2, 3, 4))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x3ffa), buf(1, 2, 3, 4))); assertEquals(1, getBlockRecordCount()); - assertEquals(4, memory.putBytes(3, addr(0x3ffe), buf(5, 6, 7, 8))); + assertEquals(4, memory.putBytes(3, b.addr(0x3ffe), buf(5, 6, 7, 8))); assertEquals(2, getBlockRecordCount()); - assertEquals(4, memory.putBytes(3, addr(0x4002), buf(9, 10, 11, 12))); + assertEquals(4, memory.putBytes(3, b.addr(0x4002), buf(9, 10, 11, 12))); assertEquals(2, getBlockRecordCount()); assertEquals(2, getBufferRecordCount()); } ByteBuffer read = ByteBuffer.allocate(12); - assertEquals(12, memory.getBytes(3, addr(0x3ffa), read)); + assertEquals(12, memory.getBytes(3, b.addr(0x3ffa), read)); assertArrayEquals(arr(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), read.array()); } @Test public void testBytesOverflow() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { + try (UndoableTransaction tid = b.startTransaction()) { ByteBuffer write = buf(1, 2, 3, 4); - assertEquals(2, memory.putBytes(3, addr(0xfffffffffffffffeL), write)); + assertEquals(2, memory.putBytes(3, b.addr(0xfffffffffffffffeL), write)); assertEquals(2, write.remaining()); assertEquals(1, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); } ByteBuffer read = buf(-1, -1, -1, -1); - assertEquals(2, memory.getBytes(3, addr(0xfffffffffffffffeL), read)); + assertEquals(2, memory.getBytes(3, b.addr(0xfffffffffffffffeL), read)); assertEquals(2, read.remaining()); assertArrayEquals(arr(1, 2, -1, -1), read.array()); } @Test public void testBytesWriteSameLater() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(1, 2, 3, 4))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(1, 2, 3, 4))); assertEquals(1, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); - assertEquals(4, memory.putBytes(5, addr(0x4000), buf(1, 2, 3, 4))); + assertEquals(4, memory.putBytes(5, b.addr(0x4000), buf(1, 2, 3, 4))); assertEquals(1, getBlockRecordCount()); // Should not require a new block assertEquals(1, getBufferRecordCount()); // Definitely not another buffer } @@ -580,25 +608,25 @@ public abstract class AbstractDBTraceMemoryManagerTest Map expected; expected = new HashMap<>(); - assertEquals(expected, collectAsMap(memory.getStates(2, range(0x3000, 0x5000)))); - assertEquals(expected, collectAsMap(memory.getStates(4, range(0x3000, 0x5000)))); - assertEquals(expected, collectAsMap(memory.getStates(6, range(0x3000, 0x5000)))); + assertEquals(expected, collectAsMap(memory.getStates(2, b.range(0x3000, 0x5000)))); + assertEquals(expected, collectAsMap(memory.getStates(4, b.range(0x3000, 0x5000)))); + assertEquals(expected, collectAsMap(memory.getStates(6, b.range(0x3000, 0x5000)))); expected = new HashMap<>(); - expected.put(srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x5000)))); + expected.put(b.srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x5000)))); expected = new HashMap<>(); - expected.put(srange(5, 0x4000, 0x4003), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getStates(5, range(0x3000, 0x5000)))); + expected.put(b.srange(5, 0x4000, 0x4003), TraceMemoryState.KNOWN); + assertEquals(expected, collectAsMap(memory.getStates(5, b.range(0x3000, 0x5000)))); ByteBuffer read = buf(0, 0, 0, 0); - assertEquals(4, memory.getBytes(5, addr(0x4000), read)); + assertEquals(4, memory.getBytes(5, b.addr(0x4000), read)); assertArrayEquals(arr(1, 2, 3, 4), read.array()); } @Test public void testBytesArrayOffset() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { + try (UndoableTransaction tid = b.startTransaction()) { byte[] array = new byte[20]; array[9] = -1; array[10] = 1; @@ -606,84 +634,84 @@ public abstract class AbstractDBTraceMemoryManagerTest array[12] = 3; array[13] = 4; array[14] = -1; - assertEquals(4, memory.putBytes(3, addr(0x4000), ByteBuffer.wrap(array, 10, 4))); + assertEquals(4, memory.putBytes(3, b.addr(0x4000), ByteBuffer.wrap(array, 10, 4))); } byte[] array = new byte[20]; array[9] = -2; array[16] = -2; ByteBuffer read = ByteBuffer.wrap(array, 10, 6); - assertEquals(6, memory.getBytes(3, addr(0x3fff), read)); + assertEquals(6, memory.getBytes(3, b.addr(0x3fff), read)); assertArrayEquals(arr(-2, 0, 1, 2, 3, 4, 0, -2), Arrays.copyOfRange(array, 9, 17)); } @Test public void testGetBytesMostRecent() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(1, 2, 3, 4))); - assertEquals(4, memory.putBytes(4, addr(0x4002), buf(5, 6, 7, 8))); - assertEquals(1, memory.putBytes(5, addr(0x4003), buf(0))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(1, 2, 3, 4))); + assertEquals(4, memory.putBytes(4, b.addr(0x4002), buf(5, 6, 7, 8))); + assertEquals(1, memory.putBytes(5, b.addr(0x4003), buf(0))); assertEquals(3, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); } ByteBuffer read = buf(-1, -1, -1, -1); - assertEquals(4, memory.getBytes(2, addr(0x4000), read)); + assertEquals(4, memory.getBytes(2, b.addr(0x4000), read)); assertArrayEquals(arr(-1, -1, -1, -1), read.array()); read.position(0); - assertEquals(4, memory.getBytes(3, addr(0x4000), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x4000), read)); assertArrayEquals(arr(1, 2, 3, 4), read.array()); read.position(0); - assertEquals(4, memory.getBytes(4, addr(0x4002), read)); + assertEquals(4, memory.getBytes(4, b.addr(0x4002), read)); assertArrayEquals(arr(5, 6, 7, 8), read.array()); read.position(0); - assertEquals(4, memory.getBytes(4, addr(0x4000), read)); + assertEquals(4, memory.getBytes(4, b.addr(0x4000), read)); assertArrayEquals(arr(1, 2, 5, 6), read.array()); read = ByteBuffer.allocate(10); - assertEquals(10, memory.getBytes(5, addr(0x3ffe), read)); + assertEquals(10, memory.getBytes(5, b.addr(0x3ffe), read)); assertArrayEquals(arr(0, 0, 1, 2, 5, 0, 7, 8, 0, 0), read.array()); } @Test public void testPutBytesIntoPastGetBytesMostRecent() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(4, addr(0x4800), buf(5, 6, 7, 8))); - assertEquals(4, memory.putBytes(3, addr(0x4802), buf(1, 2, 3, 4))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(4, b.addr(0x4800), buf(5, 6, 7, 8))); + assertEquals(4, memory.putBytes(3, b.addr(0x4802), buf(1, 2, 3, 4))); assertEquals(10, - memory.putBytes(2, addr(0x47fe), buf(9, 10, 11, 12, 13, 14, 15, 16, 17, 18))); + memory.putBytes(2, b.addr(0x47fe), buf(9, 10, 11, 12, 13, 14, 15, 16, 17, 18))); assertEquals(3, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); } ByteBuffer read = buf(-1, -1, -1, -1); - assertEquals(4, memory.getBytes(1, addr(0x4802), read)); + assertEquals(4, memory.getBytes(1, b.addr(0x4802), read)); assertArrayEquals(arr(-1, -1, -1, -1), read.array()); read.position(0); - assertEquals(4, memory.getBytes(3, addr(0x4802), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x4802), read)); assertArrayEquals(arr(1, 2, 3, 4), read.array()); read.position(0); - assertEquals(4, memory.getBytes(4, addr(0x4800), read)); + assertEquals(4, memory.getBytes(4, b.addr(0x4800), read)); assertArrayEquals(arr(5, 6, 7, 8), read.array()); read.position(0); - assertEquals(4, memory.getBytes(4, addr(0x4802), read)); + assertEquals(4, memory.getBytes(4, b.addr(0x4802), read)); assertArrayEquals(arr(7, 8, 3, 4), read.array()); read = ByteBuffer.allocate(14); - assertEquals(14, memory.getBytes(4, addr(0x47fc), read)); + assertEquals(14, memory.getBytes(4, b.addr(0x47fc), read)); assertArrayEquals(arr(0, 0, 9, 10, 5, 6, 7, 8, 3, 4, 17, 18, 0, 0), read.array()); } @Test public void testPutBytesPackGetBytes() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(1, 2, 3, 4))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(1, 2, 3, 4))); memory.pack(); assertEquals(1, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); @@ -692,7 +720,7 @@ public abstract class AbstractDBTraceMemoryManagerTest assertTrue(bufEnt.isCompressed()); ByteBuffer read = ByteBuffer.allocate(4); - assertEquals(4, memory.getBytes(3, addr(0x4000), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x4000), read)); assertArrayEquals(arr(1, 2, 3, 4), read.array()); assertTrue(bufEnt.isCompressed()); @@ -700,30 +728,30 @@ public abstract class AbstractDBTraceMemoryManagerTest @Test public void testPutBytesPackPutBytes() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(1, 2, 3, 4))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(1, 2, 3, 4))); memory.pack(); assertEquals(1, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); DBTraceMemoryBufferEntry bufEnt = getBufferStore().getObjectAt(0); assertTrue(bufEnt.isCompressed()); - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(1, 2, 3, 4))); + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(1, 2, 3, 4))); assertFalse(bufEnt.isCompressed()); // TODO: This is an implementation quirk. Do I care? } ByteBuffer read = ByteBuffer.allocate(4); - assertEquals(4, memory.getBytes(3, addr(0x4000), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x4000), read)); assertArrayEquals(arr(1, 2, 3, 4), read.array()); } @Test public void testFindBytes() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(5, memory.putBytes(3, addr(0x4000), buf(1, 2, 3, 4, 5))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(5, memory.putBytes(3, b.addr(0x4000), buf(1, 2, 3, 4, 5))); } try { - memory.findBytes(3, range(0x4000, 0x4003), buf(1, 2, 3, 4), buf(-1, -1, -1), + memory.findBytes(3, b.range(0x4000, 0x4003), buf(1, 2, 3, 4), buf(-1, -1, -1), true, TaskMonitor.DUMMY); } catch (IllegalArgumentException e) { @@ -732,62 +760,63 @@ public abstract class AbstractDBTraceMemoryManagerTest // Degenerate assertNull( - memory.findBytes(2, range(0x4000, 0x4003), buf(), buf(), + memory.findBytes(2, b.range(0x4000, 0x4003), buf(), buf(), true, TaskMonitor.DUMMY)); // Too soon assertNull( - memory.findBytes(2, range(0x4000, 0x4003), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), + memory.findBytes(2, b.range(0x4000, 0x4003), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), true, TaskMonitor.DUMMY)); // Too small assertNull( - memory.findBytes(3, range(0x4000, 0x4002), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), + memory.findBytes(3, b.range(0x4000, 0x4002), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), true, TaskMonitor.DUMMY)); // Too high assertNull( - memory.findBytes(3, range(0x4001, 0x4004), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), + memory.findBytes(3, b.range(0x4001, 0x4004), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), true, TaskMonitor.DUMMY)); // Too high, into unknown assertNull( - memory.findBytes(3, range(0x4001, 0x4005), buf(1, 2, 3, 4, 5), buf(-1, -1, -1, -1, -1), + memory.findBytes(3, b.range(0x4001, 0x4005), buf(1, 2, 3, 4, 5), + buf(-1, -1, -1, -1, -1), true, TaskMonitor.DUMMY)); // Too low assertNull( - memory.findBytes(3, range(0x3fff, 0x4002), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), + memory.findBytes(3, b.range(0x3fff, 0x4002), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), true, TaskMonitor.DUMMY)); // Perfect match - assertEquals(addr(0x4000), - memory.findBytes(3, range(0x4000, 0x4003), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), + assertEquals(b.addr(0x4000), + memory.findBytes(3, b.range(0x4000, 0x4003), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), true, TaskMonitor.DUMMY)); // Make it work for the match - assertEquals(addr(0x4000), - memory.findBytes(3, range(0x0, -1), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), + assertEquals(b.addr(0x4000), + memory.findBytes(3, b.range(0x0, -1), buf(1, 2, 3, 4), buf(-1, -1, -1, -1), true, TaskMonitor.DUMMY)); // Make it work for the match - assertEquals(addr(0x4000), - memory.findBytes(3, range(0x0, -1), buf(1), buf(-1), + assertEquals(b.addr(0x4000), + memory.findBytes(3, b.range(0x0, -1), buf(1), buf(-1), true, TaskMonitor.DUMMY)); // Sub match - assertEquals(addr(0x4001), - memory.findBytes(3, range(0x4000, 0x4003), buf(2, 3, 4), buf(-1, -1, -1), + assertEquals(b.addr(0x4001), + memory.findBytes(3, b.range(0x4000, 0x4003), buf(2, 3, 4), buf(-1, -1, -1), true, TaskMonitor.DUMMY)); } @Test public void testRemoveBytes() { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { + try (UndoableTransaction tid = b.startTransaction()) { assertEquals(10, - memory.putBytes(2, addr(0x47fe), buf(9, 10, 11, 12, 13, 14, 15, 16, 17, 18))); - assertEquals(4, memory.putBytes(4, addr(0x4800), buf(5, 6, 7, 8))); - assertEquals(4, memory.putBytes(3, addr(0x4802), buf(1, 2, 3, 4))); + memory.putBytes(2, b.addr(0x47fe), buf(9, 10, 11, 12, 13, 14, 15, 16, 17, 18))); + assertEquals(4, memory.putBytes(4, b.addr(0x4800), buf(5, 6, 7, 8))); + assertEquals(4, memory.putBytes(3, b.addr(0x4802), buf(1, 2, 3, 4))); assertEquals(3, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); /* 0x fe ff 00 01 02 03 04 05 06 07 @@ -797,7 +826,7 @@ public abstract class AbstractDBTraceMemoryManagerTest * 2: 9 10 11 12 13 14 15 16 17 18 */ - memory.removeBytes(2, addr(0x47ff), 14); + memory.removeBytes(2, b.addr(0x47ff), 14); /* 0x fe ff 00 01 02 03 04 05 06 07 * * 4: 5 6 7 8 @@ -807,45 +836,46 @@ public abstract class AbstractDBTraceMemoryManagerTest } ByteBuffer read = ByteBuffer.allocate(4); - assertEquals(4, memory.getBytes(1, addr(0x4802), read)); + assertEquals(4, memory.getBytes(1, b.addr(0x4802), read)); assertArrayEquals(arr(0, 0, 0, 0), read.array()); read.position(0); - assertEquals(4, memory.getBytes(3, addr(0x4802), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x4802), read)); assertArrayEquals(arr(1, 2, 3, 4), read.array()); read.position(0); - assertEquals(4, memory.getBytes(4, addr(0x4800), read)); + assertEquals(4, memory.getBytes(4, b.addr(0x4800), read)); assertArrayEquals(arr(5, 6, 7, 8), read.array()); read.position(0); - assertEquals(4, memory.getBytes(4, addr(0x4802), read)); + assertEquals(4, memory.getBytes(4, b.addr(0x4802), read)); assertArrayEquals(arr(7, 8, 3, 4), read.array()); read = ByteBuffer.allocate(14); - assertEquals(14, memory.getBytes(4, addr(0x47fc), read)); + assertEquals(14, memory.getBytes(4, b.addr(0x47fc), read)); assertArrayEquals(arr(0, 0, 9, 0, 5, 6, 7, 8, 3, 4, 0, 0, 0, 0), read.array()); // Check overall effect on state Map expected; expected = new HashMap<>(); - expected.put(srange(2, 0x47fe, 0x47fe), TraceMemoryState.KNOWN); - expected.put(srange(4, 0x4800, 0x4803), TraceMemoryState.KNOWN); - expected.put(srange(3, 0x4804, 0x4805), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getMostRecentStates(6, range(0x4700, 0x4900)))); + expected.put(b.srange(2, 0x47fe, 0x47fe), TraceMemoryState.KNOWN); + expected.put(b.srange(4, 0x4800, 0x4803), TraceMemoryState.KNOWN); + expected.put(b.srange(3, 0x4804, 0x4805), TraceMemoryState.KNOWN); + assertEquals(expected, + collectAsMap(memory.getMostRecentStates(6, b.range(0x4700, 0x4900)))); } @Test public void testSaveAndLoad() throws Exception { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(1, 2, 3, 4))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(1, 2, 3, 4))); assertEquals(1, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); } Path tmp = Files.createTempFile("test", ".db"); Files.delete(tmp); // saveAs must create the file - trace.getDBHandle().saveAs(tmp.toFile(), false, new ConsoleTaskMonitor()); + b.trace.getDBHandle().saveAs(tmp.toFile(), false, new ConsoleTaskMonitor()); DBHandle opened = new DBHandle(tmp.toFile()); DBTrace restored = null; @@ -853,17 +883,17 @@ public abstract class AbstractDBTraceMemoryManagerTest restored = new DBTrace(opened, DBOpenMode.UPDATE, new ConsoleTaskMonitor(), this); DBTraceMemorySpace rSpace = - restored.getMemoryManager().getMemorySpace(toyLanguage.getDefaultDataSpace(), true); + restored.getMemoryManager().getMemorySpace(b.language.getDefaultDataSpace(), true); assertEquals(1, rSpace.bufferStore.getRecordCount()); // verify the corresponding change in state; Map expected; expected = new HashMap<>(); - expected.put(srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x5000)))); + expected.put(b.srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x5000)))); ByteBuffer read = ByteBuffer.allocate(4); - assertEquals(4, rSpace.getBytes(3, addr(0x4000), read)); + assertEquals(4, rSpace.getBytes(3, b.addr(0x4000), read)); assertArrayEquals(arr(1, 2, 3, 4), read.array()); } finally { @@ -875,16 +905,16 @@ public abstract class AbstractDBTraceMemoryManagerTest @Test public void testAddButAbortedStillEmpty() throws Exception { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(1, 2, 3, 4))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(1, 2, 3, 4))); assertEquals(1, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); // verify the corresponding change in state; Map expected; expected = new HashMap<>(); - expected.put(srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x5000)))); + expected.put(b.srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x5000)))); tid.abort(); } @@ -894,27 +924,27 @@ public abstract class AbstractDBTraceMemoryManagerTest // verify the corresponding change in state; Map expected; expected = new HashMap<>(); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x5000)))); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x5000)))); ByteBuffer read = ByteBuffer.allocate(4); - assertEquals(4, memory.getBytes(3, addr(0x4000), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x4000), read)); assertArrayEquals(arr(0, 0, 0, 0), read.array()); } @Test public void testAddThenUndo() throws Exception { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(1, 2, 3, 4))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(1, 2, 3, 4))); assertEquals(1, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); // verify the corresponding change in state; Map expected; expected = new HashMap<>(); - expected.put(srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x5000)))); + expected.put(b.srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x5000)))); } - trace.undo(); + b.trace.undo(); assertEquals(0, getBlockRecordCount()); assertEquals(0, getBufferRecordCount()); @@ -922,27 +952,27 @@ public abstract class AbstractDBTraceMemoryManagerTest // verify the corresponding change in state; Map expected; expected = new HashMap<>(); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x5000)))); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x5000)))); ByteBuffer read = ByteBuffer.allocate(4); - assertEquals(4, memory.getBytes(3, addr(0x4000), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x4000), read)); assertArrayEquals(arr(0, 0, 0, 0), read.array()); } @Test public void testAddThenUndoThenRedo() throws Exception { - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - assertEquals(4, memory.putBytes(3, addr(0x4000), buf(1, 2, 3, 4))); + try (UndoableTransaction tid = b.startTransaction()) { + assertEquals(4, memory.putBytes(3, b.addr(0x4000), buf(1, 2, 3, 4))); assertEquals(1, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); // verify the corresponding change in state; Map expected; expected = new HashMap<>(); - expected.put(srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x5000)))); + expected.put(b.srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x5000)))); } - trace.undo(); + b.trace.undo(); assertEquals(0, getBlockRecordCount()); assertEquals(0, getBufferRecordCount()); @@ -950,23 +980,23 @@ public abstract class AbstractDBTraceMemoryManagerTest // verify the corresponding change in state; Map expected; expected = new HashMap<>(); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x5000)))); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x5000)))); ByteBuffer read = ByteBuffer.allocate(4); - assertEquals(4, memory.getBytes(3, addr(0x4000), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x4000), read)); assertArrayEquals(arr(0, 0, 0, 0), read.array()); - trace.redo(); + b.trace.redo(); assertEquals(1, getBlockRecordCount()); assertEquals(1, getBufferRecordCount()); expected = new HashMap<>(); - expected.put(srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); - assertEquals(expected, collectAsMap(memory.getStates(3, range(0x3000, 0x5000)))); + expected.put(b.srange(3, 0x4000, 0x4003), TraceMemoryState.KNOWN); + assertEquals(expected, collectAsMap(memory.getStates(3, b.range(0x3000, 0x5000)))); read.position(0); - assertEquals(4, memory.getBytes(3, addr(0x4000), read)); + assertEquals(4, memory.getBytes(3, b.addr(0x4000), read)); assertArrayEquals(arr(1, 2, 3, 4), read.array()); } @@ -975,31 +1005,31 @@ public abstract class AbstractDBTraceMemoryManagerTest /** * This test gets down into the block buffer implementation. If the block number exceeds * 127, if might (accidentally) get treated as negative. Thanks Java! We can create this - * situation by writing to the same address at more than 127 different snaps. + * situation by writing to the same b.address at more than 127 different snaps. */ - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { + try (UndoableTransaction tid = b.startTransaction()) { for (int i = 0; i < 300; i++) { - memory.putBytes(i, addr(0x4000), buf(1, 2, 3, i % 256)); + memory.putBytes(i, b.addr(0x4000), buf(1, 2, 3, i % 256)); } } for (int i = 0; i < 300; i++) { ByteBuffer buf = ByteBuffer.allocate(4); - memory.getBytes(i, addr(0x4000), buf); + memory.getBytes(i, b.addr(0x4000), buf); assertArrayEquals(arr(1, 2, 3, i % 256), buf.array()); } } @Test public void testRegisters() throws Exception { - Register r0 = toyLanguage.getRegister("r0"); - Register r0h = toyLanguage.getRegister("r0h"); - Register r0l = toyLanguage.getRegister("r0l"); + Register r0 = b.language.getRegister("r0"); + Register r0h = b.language.getRegister("r0h"); + Register r0l = b.language.getRegister("r0l"); DBTraceThread thread; - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - thread = trace.getThreadManager().addThread("Thread1", Range.atLeast(0L)); + try (UndoableTransaction tid = b.startTransaction()) { + thread = b.getOrAddThread("Thread1", 0); DBTraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(r0, new BigInteger("0123456789ABCDEF", 16))); @@ -1018,7 +1048,7 @@ public abstract class AbstractDBTraceMemoryManagerTest assertEquals(new BigInteger("76543210", 16), regs.getValue(0, r0h).getUnsignedValue()); assertEquals(new BigInteger("FEDCBA98", 16), regs.getValue(0, r0l).getUnsignedValue()); - DBTraceStack stack = trace.getStackManager().getStack(thread, 0, true); + DBTraceStack stack = b.trace.getStackManager().getStack(thread, 0, true); stack.setDepth(2, true); assertEquals(regs, memory.getMemoryRegisterSpace(stack.getFrame(0, false), false)); DBTraceMemoryRegisterSpace frame = @@ -1031,15 +1061,54 @@ public abstract class AbstractDBTraceMemoryManagerTest } } + /** + * This has to be called by the sub-class, having created a trace with the Toy:??:32:builder + * language. + */ + protected void runTestRegisterBits() throws Exception { + Register contextreg = b.language.getRegister("contextreg"); + Register fctx = b.language.getRegister("fctx"); + Register nfctx = b.language.getRegister("nfctx"); + Register phase = b.language.getRegister("phase"); + Register counter = b.language.getRegister("counter"); + + DBTraceThread thread; + try (UndoableTransaction tid = b.startTransaction()) { + thread = b.getOrAddThread("Thread1", 0); + DBTraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true); + + regs.setValue(0, new RegisterValue(fctx, BigInteger.valueOf(0xa))); + assertEquals(BigInteger.valueOf(0xa), regs.getValue(0, fctx).getUnsignedValue()); + + regs.setValue(0, new RegisterValue(nfctx, BigInteger.valueOf(0xb))); + assertEquals(BigInteger.valueOf(0xb), regs.getValue(0, nfctx).getUnsignedValue()); + assertEquals(BigInteger.valueOf(0xa), regs.getValue(0, fctx).getUnsignedValue()); + + regs.setValue(0, new RegisterValue(phase, BigInteger.valueOf(0x3))); + assertEquals(BigInteger.valueOf(0x3), regs.getValue(0, phase).getUnsignedValue()); + assertEquals(BigInteger.valueOf(0), regs.getValue(0, counter).getUnsignedValue()); + + regs.setValue(0, new RegisterValue(counter, BigInteger.valueOf(0xf))); + assertEquals(BigInteger.valueOf(0xf), regs.getValue(0, counter).getUnsignedValue()); + + assertEquals(BigInteger.valueOf(0xabfc).shiftLeft(48), + regs.getValue(0, contextreg).getUnsignedValue()); + + regs.setValue(0, new RegisterValue(fctx, BigInteger.valueOf(0x5))); + assertEquals(BigInteger.valueOf(0x5bfc).shiftLeft(48), + regs.getValue(0, contextreg).getUnsignedValue()); + } + } + /** * This test is based on the MWE submitted in GitHub issue #2760. */ @Test public void testManyStateEntries() throws Exception { - Register pc = toyLanguage.getRegister("pc"); + Register pc = b.language.getRegister("pc"); DBTraceThread thread; - try (UndoableTransaction tid = UndoableTransaction.start(trace, "Testing", true)) { - thread = trace.getThreadManager().addThread("Thread1", Range.atLeast(0L)); + try (UndoableTransaction tid = b.startTransaction()) { + thread = b.getOrAddThread("Thread1", 0); DBTraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true); for (int i = 1; i < 2000; i++) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerBETest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerBETest.java index 587ab7fc1d..1da55d140d 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerBETest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerBETest.java @@ -15,11 +15,20 @@ */ package ghidra.trace.database.memory; +import org.junit.Test; + import ghidra.program.model.lang.LanguageID; +import ghidra.trace.util.LanguageTestWatcher.TestLanguage; public class DBTraceMemoryManagerBETest extends AbstractDBTraceMemoryManagerTest { @Override protected LanguageID getLanguageID() { return new LanguageID("Toy:BE:64:default"); } + + @TestLanguage("Toy:BE:32:builder") + @Test + public void testRegisterBits() throws Exception { + runTestRegisterBits(); + } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerLETest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerLETest.java index 87deff851e..c508a22125 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerLETest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerLETest.java @@ -15,11 +15,20 @@ */ package ghidra.trace.database.memory; +import org.junit.Test; + import ghidra.program.model.lang.LanguageID; +import ghidra.trace.util.LanguageTestWatcher.TestLanguage; public class DBTraceMemoryManagerLETest extends AbstractDBTraceMemoryManagerTest { @Override protected LanguageID getLanguageID() { return new LanguageID("Toy:LE:64:default"); } + + @TestLanguage("Toy:LE:32:builder") + @Test + public void testRegisterBits() throws Exception { + runTestRegisterBits(); + } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceDisassemblerIntegrationTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceDisassemblerIntegrationTest.java index 4e51e715bb..f7e5382e7e 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceDisassemblerIntegrationTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceDisassemblerIntegrationTest.java @@ -19,12 +19,9 @@ import static org.junit.Assert.assertEquals; import java.io.File; import java.io.IOException; -import java.lang.annotation.*; import java.util.Set; import org.junit.*; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; import com.google.common.collect.Range; @@ -45,6 +42,8 @@ import ghidra.trace.database.memory.DBTraceMemoryManager; import ghidra.trace.database.memory.DBTraceMemorySpace; import ghidra.trace.model.memory.TraceMemoryFlag; import ghidra.trace.model.memory.TraceOverlappedRegionException; +import ghidra.trace.util.LanguageTestWatcher; +import ghidra.trace.util.LanguageTestWatcher.TestLanguage; import ghidra.util.database.UndoableTransaction; import ghidra.util.exception.*; import ghidra.util.task.ConsoleTaskMonitor; @@ -54,35 +53,8 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn protected ToyDBTraceBuilder b; protected DBTraceVariableSnapProgramView view; - @Target(ElementType.METHOD) - @Retention(RetentionPolicy.RUNTIME) - public @interface TestLanguage { - String value(); - } - - public static class LanguageWatcher extends TestWatcher { - String language = ProgramBuilder._TOY64_BE; - - @Override - protected void starting(Description description) { - language = computeLanguage(description); - } - - private String computeLanguage(Description description) { - TestLanguage annot = description.getAnnotation(TestLanguage.class); - if (annot == null) { - return ProgramBuilder._TOY64_BE; - } - return annot.value(); - } - - public String getLanguage() { - return language; - } - } - @Rule - public LanguageWatcher testLanguage = new LanguageWatcher(); + public LanguageTestWatcher testLanguage = new LanguageTestWatcher(); @Before public void setUp() throws IOException { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/util/LanguageTestWatcher.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/util/LanguageTestWatcher.java new file mode 100644 index 0000000000..70f9dad541 --- /dev/null +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/util/LanguageTestWatcher.java @@ -0,0 +1,55 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.trace.util; + +import java.lang.annotation.*; + +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +import ghidra.program.database.ProgramBuilder; + +public class LanguageTestWatcher extends TestWatcher { + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface TestLanguage { + String value(); + } + + protected String language; + + public LanguageTestWatcher() { + this(ProgramBuilder._TOY64_BE); + } + + public LanguageTestWatcher(String defaultLanguage) { + this.language = defaultLanguage; + } + + @Override + protected void starting(Description description) { + TestLanguage annot = description.getAnnotation(TestLanguage.class); + if (annot == null) { + return; + } + language = annot.value(); + } + + public String getLanguage() { + return language; + } +} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/Register.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/Register.java index 141acc83a1..a35c5ee185 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/Register.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/Register.java @@ -21,11 +21,10 @@ import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; /** - * Class to represent a processor register. To sort of handle bit registers, a - * special addressing convention is used. First the upper bit is set. Second, the - * next 3 bits are used to specify what bit position within a byte that this register - * bit exists at. Finally, the rest of the address is the address of the byte where - * the register bit lives. + * Class to represent a processor register. To sort of handle bit registers, a special addressing + * convention is used. First the upper bit is set. Second, the next 3 bits are used to specify what + * bit position within a byte that this register bit exists at. Finally, the rest of the address is + * the address of the byte where the register bit lives. */ public class Register implements java.io.Serializable, Comparable { @@ -61,7 +60,7 @@ public class Register implements java.io.Serializable, Comparable { private Register baseRegister; private String group; - /**Set of valid lane sizes**/ + /** Set of valid lane sizes **/ private TreeSet laneSizes; /** @@ -72,10 +71,10 @@ public class Register implements java.io.Serializable, Comparable { * @param address the address in register space of this register * @param numBytes the size (in bytes) of this register * @param bigEndian true if the most significant bytes are associated with the lowest register - * addresses, and false if the least significant bytes are associated with the lowest register - * addresses. - * @param typeFlags the type(s) of this Register (TYPE_NONE, TYPE_FP, TYPE_SP, - * TYPE_PC, TYPE_CONTEXT, TYPE_ZERO);) + * addresses, and false if the least significant bytes are associated with the lowest + * register addresses. + * @param typeFlags the type(s) of this Register (TYPE_NONE, TYPE_FP, TYPE_SP, TYPE_PC, + * TYPE_CONTEXT, TYPE_ZERO);) */ public Register(String name, String description, Address address, int numBytes, boolean bigEndian, int typeFlags) { @@ -128,6 +127,7 @@ public class Register implements java.io.Serializable, Comparable { /** * Add register alias + * * @param aliasReg */ void addAlias(String alias) { @@ -142,6 +142,7 @@ public class Register implements java.io.Serializable, Comparable { /** * Remove register alias + * * @param alias */ void removeAlias(String alias) { @@ -151,9 +152,8 @@ public class Register implements java.io.Serializable, Comparable { } /** - * Return register aliases. - * NOTE: This is generally only supported for - * context register fields. + * Return register aliases. NOTE: This is generally only supported for context register fields. + * * @return register aliases or null */ public Iterable getAliases() { @@ -201,6 +201,19 @@ public class Register implements java.io.Serializable, Comparable { return (bitLength + 7) / 8; } + /** + * Returns the number of bytes spanned by this Register. + * + *

+ * Compare to {{@link #getMinimumByteSize()}: Suppose a 5-bit register spans 2 bytes: 1 bit in + * the first byte, and the remaining 4 in the following byte. Its value can still be stored in 1 + * byte, which is what {@link #getMinimumByteSize()} returns; however, its storage still spans 2 + * bytes of the base register, which is what this method returns. + */ + public int getNumBytes() { + return numBytes; + } + /** * Returns the offset into the register space for this register */ @@ -210,6 +223,7 @@ public class Register implements java.io.Serializable, Comparable { /** * Returns the bit offset from the register address for this register. + * * @return the bit offset from the register address for this register. */ public int getLeastSignificantBit() { @@ -224,8 +238,7 @@ public class Register implements java.io.Serializable, Comparable { } /** - * Returns true for a register whose context value should - * follow the disassembly flow. + * Returns true for a register whose context value should follow the disassembly flow. */ public boolean followsFlow() { return (typeFlags & TYPE_DOES_NOT_FOLLOW_FLOW) == 0; @@ -335,8 +348,8 @@ public class Register implements java.io.Serializable, Comparable { } /** - * Returns list of children registers sorted by - * lest-significant bit-offset within this register. + * Returns list of children registers sorted by lest-significant bit-offset within this + * register. */ public List getChildRegisters() { return new ArrayList<>(childRegisters); @@ -400,6 +413,7 @@ public class Register implements java.io.Serializable, Comparable { /** * Returns the mask that indicates which bits in the base register apply to this register. + * * @return the mask that indicates which bits in the base register apply to this register */ public byte[] getBaseMask() { @@ -445,11 +459,11 @@ public class Register implements java.io.Serializable, Comparable { } /** - * Determines if reg is contained within this register. - * Method does not work for bit registers (e.g., context-bits) + * Determines if reg is contained within this register. Method does not work for bit registers + * (e.g., context-bits) + * * @param reg another register - * @return true if reg equals this register or is contained - * within it. + * @return true if reg equals this register or is contained within it. */ public boolean contains(Register reg) { if (equals(reg)) { @@ -472,8 +486,9 @@ public class Register implements java.io.Serializable, Comparable { /** * Returns true if this is a vector register - * @return true precisely when {@code this} is a full vector register (i.e., a register that can be - * used as input or output for a SIMD operation). + * + * @return true precisely when {@code this} is a full vector register (i.e., a register that can + * be used as input or output for a SIMD operation). */ public boolean isVectorRegister() { return (typeFlags & TYPE_VECTOR) != 0; @@ -481,8 +496,10 @@ public class Register implements java.io.Serializable, Comparable { /** * Determines whether {@code laneSizeInBytes} is a valid lane size for this register. + * * @param laneSizeInBytes lane size to check, measured in bytes - * @return true precisely when {@code this} is a vector register and {@code laneSizeInBytes} is a valid lane size. + * @return true precisely when {@code this} is a vector register and {@code laneSizeInBytes} is + * a valid lane size. */ public boolean isValidLaneSize(int laneSizeInBytes) { if (!isVectorRegister()) { @@ -496,7 +513,9 @@ public class Register implements java.io.Serializable, Comparable { /** * Returns the sorted array of lane sizes for this register, measured in bytes. - * @return array of lane sizes, or {@code null} if {@code this} is not a vector register or no lane sizes have been set. + * + * @return array of lane sizes, or {@code null} if {@code this} is not a vector register or no + * lane sizes have been set. */ public int[] getLaneSizes() { if (laneSizes == null) { @@ -512,9 +531,10 @@ public class Register implements java.io.Serializable, Comparable { /** * Adds a lane size. + * * @param laneSizeInBytes lane size to add - * @throws UnsupportedOperationException if register is unable to support the definition of - * lanes. + * @throws UnsupportedOperationException if register is unable to support the definition of + * lanes. * @throws IllegalArgumentException if {@code laneSizeInBytes} is invalid */ void addLaneSize(int laneSizeInBytes) {