Package ghidra.trace.model.memory

# Interface TraceMemoryOperations

All Known Subinterfaces:
  `InternalTraceMemoryOperations`, `TraceMemoryManager`, `TraceMemorySpace`

All Known Implementing Classes:
  `DBTraceMemoryManager`, `DBTraceMemorySpace`

public interface TraceMemoryOperations
Operations for mutating memory regions, values, and state within a trace

This models memory over the course of an arbitrary number of snaps. The duration between snaps is unspecified. However, the mapping of snaps to real time ought to be strictly monotonic. Observations of memory are recorded using the `putBytes(long, Address, ByteBuffer)` and related methods. Those observations, and some related deductions can be retrieved using the `getBytes(long, Address, ByteBuffer)` and related methods. Many of the `get` methods permit the retrieval of the most recent observations. This is useful as an observed value in memory is presumed unchanged until another observation is made. Observations of bytes in memory cause the state at the same location and snap to become `TraceMemoryState.KNOWN`. These states can be manipulated directly; however, this is recommended only to record read failures, using the state `TraceMemoryState.ERROR`. A state of `null` is equivalent to `TraceMemoryState.UNKNOWN` and indicates no observation has been made.

Negative snaps may have different semantics than positive, since negative snaps are used as "scratch space". These snaps are not presumed to have any temporal relation to their neighbors, or any other snap for that matter. Clients may use the description field of the `TraceSnapshot` to indicate a relationship to another snap. Operations which seek the "most-recent" data might not retrieve anything from scratch snaps, and writing to a scratch snap might not cause any changes to others. Note the "integrity" of data where the memory state is not `TraceMemoryState.KNOWN` may be neglected to some extent. For example, writing bytes to snap -10 may cause bytes in snap -9 to change, where the effected range at snap -9 has state `TraceMemoryState.UNKNOWN`. The time semantics are not necessarily prohibited in scratch space, but implementations may choose cheaper semantics if desired. Clients should be wary not to accidentally rely on implied temporal relationships in scratch space.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `Address`
  `findBytes(long snap, AddressRange range, ByteBuffer data, ByteBuffer mask, boolean forward, TaskMonitor monitor)`
  Search the given address range at the given snap for a given byte pattern
  `default AddressSetView`
  `getAddressesWithState(long snap, AddressSetView set, Predicate<TraceMemoryState> predicate)`
  Get at least the subset of addresses having state satisfying the given predicate
  `AddressSetView`
  `getAddressesWithState(long snap, Predicate<TraceMemoryState> predicate)`
  Get the addresses having state satisfying the given predicate
  `AddressSetView`
  `getAddressesWithState(Lifespan span, AddressSetView set, Predicate<TraceMemoryState> predicate)`
  Get at least the subset of addresses having state satisfying the given predicate
  `AddressSetView`
  `getAddressesWithState(Lifespan lifespan, Predicate<TraceMemoryState> predicate)`
  Get the addresses having state satisfying the given predicate at any time in the specified lifespan
  `int`
  `getBlockSize()`
  Get the block size used by internal storage.
  `default MemBuffer`
  `getBufferAt(long snap, Address start)`
  Get a view of a particular snap as a memory buffer using the base language's byte order
  `MemBuffer`
  `getBufferAt(long snap, Address start, ByteOrder byteOrder)`
  Get a view of a particular snap as a memory buffer
  `int`
  `getBytes(long snap, Address start, ByteBuffer buf)`
  Read the most recent bytes from the given snap and address
  `default int`
  `getBytes(long snap, Register register, ByteBuffer buf)`
  Get the most-recent bytes of a given register at the given time
  `int`
  `getBytes(TracePlatform platform, long snap, Register register, ByteBuffer buf)`
  Get the most-recent bytes of a given register at the given time
  `Map.Entry<TraceAddressSnapRange,TraceMemoryState>`
  `getMostRecentStateEntry(long snap, Address address)`
  Get the entry recording the most recent state at the given snap and address
  `default Iterable<Map.Entry<TraceAddressSnapRange,TraceMemoryState>>`
  `getMostRecentStates(long snap, AddressRange range)`
  `Iterable<Map.Entry<TraceAddressSnapRange,TraceMemoryState>>`
  `getMostRecentStates(TraceAddressSnapRange within)`
  Break a range of addresses into smaller ranges each mapped to its most recent state at the given time
  `Long`
  `getSnapOfMostRecentChangeToBlock(long snap, Address address)`
  Find the internal storage block that most-recently defines the value at the given snap and address, and return the block's snap.
  `TraceMemoryState`
  `getState(long snap, Address address)`
  Get the state of memory at a given snap and address
  `default TraceMemoryState`
  `getState(long snap, Register register)`
  Assert that a register's range has a single state at the given snap and get that state
  `TraceMemoryState`
  `getState(TracePlatform platform, long snap, Register register)`
  Assert that a register's range has a single state at the given snap and get that state
  `Collection<Map.Entry<TraceAddressSnapRange,TraceMemoryState>>`
  `getStates(long snap, AddressRange range)`
  Break a range of addresses into smaller ranges each mapped to its state at the given snap
  `default Collection<Map.Entry<TraceAddressSnapRange,TraceMemoryState>>`
  `getStates(long snap, Register register)`
  Break the register's range into smaller ranges each mapped to its state at the given snap
  `Collection<Map.Entry<TraceAddressSnapRange,TraceMemoryState>>`
  `getStates(TracePlatform platform, long snap, Register register)`
  Break the register's range into smaller ranges each mapped to its state at the given snap
  `Trace`
  `getTrace()`
  Get the trace to which the memory manager belongs
  `default RegisterValue`
  `getValue(long snap, Register register)`
  Get the most-recent value of a given register at the given time
  `RegisterValue`
  `getValue(TracePlatform platform, long snap, Register register)`
  Get the most-recent value of a given register at the given time
  `int`
  `getViewBytes(long snap, Address start, ByteBuffer buf)`
  Read the most recent bytes from the given snap and address, following schedule forks
  `Map.Entry<TraceAddressSnapRange,TraceMemoryState>`
  `getViewMostRecentStateEntry(long snap, Address address)`
  Get the entry recording the most recent state at the given snap and address, following schedule forks
  `Map.Entry<TraceAddressSnapRange,TraceMemoryState>`
  `getViewMostRecentStateEntry(long snap, AddressRange range, Predicate<TraceMemoryState> predicate)`
  Get the entry recording the most recent state since the given snap within the given range that satisfies a given predicate, following schedule forks
  `Map.Entry<Long,TraceMemoryState>`
  `getViewState(long snap, Address address)`
  Get the state of memory at a given snap and address, following schedule forks
  `default RegisterValue`
  `getViewValue(long snap, Register register)`
  Get the most-recent value of a given register at the given time, following schedule forks
  `RegisterValue`
  `getViewValue(TracePlatform platform, long snap, Register register)`
  Get the most-recent value of a given register at the given time
  `default boolean`
  `isKnown(long snap, AddressRange range)`
  Check if a range addresses are all known
  `static boolean`
  `isStateEntirely(AddressRange range, Collection<Map.Entry<TraceAddressSnapRange,TraceMemoryState>> stateEntries, TraceMemoryState state)`
  Check if the return value of `getStates(long, AddressRange)` or similar represents a single entry of the given state.
  `void`
  `pack()`
  Optimize storage space
  `int`
  `putBytes(long snap, Address start, ByteBuffer buf)`
  Write bytes at the given snap and address
  `default int`
  `putBytes(long snap, Register register, ByteBuffer buf)`
  Write bytes at the given snap and register address
  `int`
  `putBytes(TracePlatform platform, long snap, Register register, ByteBuffer buf)`
  `void`
  `removeBytes(long snap, Address start, int len)`
  Remove bytes from the given time and location
  `default void`
  `removeValue(long snap, Register register)`
  Remove a value from the given time and register
  `void`
  `removeValue(TracePlatform platform, long snap, Register register)`
  `void`
  `setState(long snap, AddressRange range, TraceMemoryState state)`
  Set the state of memory over a given time and address range
  `void`
  `setState(long snap, Address start, Address end, TraceMemoryState state)`
  `void`
  `setState(long snap, Address address, TraceMemoryState state)`
  `void`
  `setState(long snap, AddressSetView set, TraceMemoryState state)`
  Set the state of memory over a given time and address set
  `default void`
  `setState(long snap, Register register, TraceMemoryState state)`
  Set the state of a given register at a given time
  `void`
  `setState(TracePlatform platform, long snap, Register register, TraceMemoryState state)`
  Set the state of a given register at a given time
  `default int`
  `setValue(long snap, RegisterValue value)`
  Set the value of a register at the given snap
  `int`
  `setValue(TracePlatform platform, long snap, RegisterValue value)`

- ## Method Details

  - ### isStateEntirely

    static boolean isStateEntirely(AddressRange range, Collection<Map.Entry<TraceAddressSnapRange,TraceMemoryState>> stateEntries, TraceMemoryState state)
    Check if the return value of `getStates(long, AddressRange)` or similar represents a single entry of the given state.

    This method returns false if there is not exactly one entry of the given state whose range covers the given range. As a special case, an empty collection will cause this method to return true iff state is `TraceMemoryState.UNKNOWN`.

    Parameters:
      `range` - the range to check, usually that passed to `getStates(long, AddressRange)`.
      `stateEntries` - the collection returned by `getStates(long, AddressRange)`.
      `state` - the expected state
    Returns:
      true if the state matches

  - ### getTrace

    Trace getTrace()
    Get the trace to which the memory manager belongs
    Returns:
      the trace

  - ### setState

    void setState(long snap, AddressRange range, TraceMemoryState state)
    Set the state of memory over a given time and address range

    Setting state to `TraceMemoryState.KNOWN` via this method is not recommended. Setting bytes will automatically update the state accordingly.

    Parameters:
      `snap` - the time
      `range` - the range
      `state` - the state

  - ### setState

    void setState(long snap, Address address, TraceMemoryState state)
    See Also:
      - `setState(long, AddressRange, TraceMemoryState)`

  - ### setState

    void setState(long snap, Address start, Address end, TraceMemoryState state)
    See Also:
      - `setState(long, AddressRange, TraceMemoryState)`

  - ### setState

    void setState(long snap, AddressSetView set, TraceMemoryState state)
    Set the state of memory over a given time and address set
    See Also:
      - `setState(long, AddressRange, TraceMemoryState)`

  - ### getState

    TraceMemoryState getState(long snap, Address address)
    Get the state of memory at a given snap and address

    If the location's state has not been set, the result is `null`, which implies `TraceMemoryState.UNKNOWN`.

    Parameters:
      `snap` - the time
      `address` - the location
    Returns:
      the state

  - ### getViewState

    Map.Entry<Long,TraceMemoryState> getViewState(long snap, Address address)
    Get the state of memory at a given snap and address, following schedule forks
    Parameters:
      `snap` - the time
      `address` - the location
    Returns:
      the state, and the snap where it was found

  - ### getMostRecentStateEntry

    Map.Entry<TraceAddressSnapRange,TraceMemoryState> getMostRecentStateEntry(long snap, Address address)
    Get the entry recording the most recent state at the given snap and address

    The entry includes the entire entry at that snap. Parts occluded by more recent snaps are not subtracted from the entry's address range.

    Parameters:
      `snap` - the time
      `address` - the location
    Returns:
      the entry including the entire recorded range

  - ### getViewMostRecentStateEntry

    Map.Entry<TraceAddressSnapRange,TraceMemoryState> getViewMostRecentStateEntry(long snap, Address address)
    Get the entry recording the most recent state at the given snap and address, following schedule forks
    Parameters:
      `snap` - the latest time to consider
      `address` - the address
    Returns:
      the most-recent entry

  - ### getViewMostRecentStateEntry

    Map.Entry<TraceAddressSnapRange,TraceMemoryState> getViewMostRecentStateEntry(long snap, AddressRange range, Predicate<TraceMemoryState> predicate)
    Get the entry recording the most recent state since the given snap within the given range that satisfies a given predicate, following schedule forks
    Parameters:
      `snap` - the latest time to consider
      `range` - the range of addresses
      `predicate` - a predicate on the state
    Returns:
      the most-recent entry

  - ### getAddressesWithState

    default AddressSetView getAddressesWithState(long snap, AddressSetView set, Predicate<TraceMemoryState> predicate)
    Get at least the subset of addresses having state satisfying the given predicate
    Parameters:
      `snap` - the time
      `set` - the set to examine
      `predicate` - a predicate on state to search for
    Returns:
      the address set
    See Also:
      - `getAddressesWithState(Lifespan, AddressSetView, Predicate)`

  - ### getAddressesWithState

    AddressSetView getAddressesWithState(Lifespan span, AddressSetView set, Predicate<TraceMemoryState> predicate)
    Get at least the subset of addresses having state satisfying the given predicate

    The implementation may provide a larger view than requested, but within the requested set, only ranges satisfying the predicate may be present. Use `AddressSetView.intersect(AddressSetView)` with `set` if a strict subset is required.

    Because `TraceMemoryState.UNKNOWN` is not explicitly stored in the map, to compute the set of `TraceMemoryState.UNKNOWN` addresses, use the predicate `state -> state != null && state != TraceMemoryState.UNKNOWN` and subtract the result from `set`.

    Parameters:
      `span` - the range of time
      `set` - the set to examine
      `predicate` - a predicate on state to search for
    Returns:
      the address set

  - ### getAddressesWithState

    AddressSetView getAddressesWithState(long snap, Predicate<TraceMemoryState> predicate)
    Get the addresses having state satisfying the given predicate

    The implementation may provide a view that updates with changes. Behavior is not well defined for predicates testing for `TraceMemoryState.UNKNOWN`.

    Parameters:
      `snap` - the time
      `predicate` - a predicate on state to search for
    Returns:
      the address set

  - ### getAddressesWithState

    AddressSetView getAddressesWithState(Lifespan lifespan, Predicate<TraceMemoryState> predicate)
    Get the addresses having state satisfying the given predicate at any time in the specified lifespan

    The implementation may provide a view that updates with changes. Behavior is not well defined for predicates testing for `TraceMemoryState.UNKNOWN` .

    Parameters:
      `lifespan` - the span of time
      `predicate` - a predicate on state to search for
    Returns:
      the address set

  - ### getStates

    Collection<Map.Entry<TraceAddressSnapRange,TraceMemoryState>> getStates(long snap, AddressRange range)
    Break a range of addresses into smaller ranges each mapped to its state at the given snap

    Note that `TraceMemoryState.UNKNOWN` entries will not appear in the result. Gaps in the returned entries are implied to be `TraceMemoryState.UNKNOWN`.

    Parameters:
      `snap` - the time
      `range` - the range to examine
    Returns:
      the map of ranges to states

  - ### isKnown

    default boolean isKnown(long snap, AddressRange range)
    Check if a range addresses are all known
    Parameters:
      `snap` - the time
      `range` - the range to examine
    Returns:
      true if the entire range is `TraceMemoryState.KNOWN`

  - ### getMostRecentStates

    Iterable<Map.Entry<TraceAddressSnapRange,TraceMemoryState>> getMostRecentStates(TraceAddressSnapRange within)
    Break a range of addresses into smaller ranges each mapped to its most recent state at the given time

    Typically `within` is the box whose width is the address range to break down and whose height is from "negative infinity" to the "current" snap.

    In this context, "most recent" means the latest state other than `TraceMemoryState.UNKNOWN`.

    Parameters:
      `within` - a box intersecting entries to consider
    Returns:
      an iterable over the snap ranges and states

  - ### getMostRecentStates

    default Iterable<Map.Entry<TraceAddressSnapRange,TraceMemoryState>> getMostRecentStates(long snap, AddressRange range)
    See Also:
      - `getMostRecentStates(TraceAddressSnapRange)`

  - ### putBytes

    int putBytes(long snap, Address start, ByteBuffer buf)
    Write bytes at the given snap and address

    This will attempt to read `Buffer.remaining()` bytes starting at `Buffer.position()` from the source buffer `buf` and write them into memory at the specified time and location. The affected region is also updated to `TraceMemoryState.KNOWN`. The written bytes are assumed effective for all future snaps up to the next write.

    Parameters:
      `snap` - the time
      `start` - the location
      `buf` - the source buffer of bytes
    Returns:
      the number of bytes written

  - ### getBytes

    int getBytes(long snap, Address start, ByteBuffer buf)
    Read the most recent bytes from the given snap and address

    This will attempt to read `Buffer.remaining()` of the most recent bytes from memory at the specified time and location and write them into the destination buffer `buf` starting at `Buffer.position()`. Where bytes in memory have no defined value, values in the destination buffer are unspecified. The implementation may leave those bytes in the destination buffer unmodified, or it may write zeroes.

    Parameters:
      `snap` - the time
      `start` - the location
      `buf` - the destination buffer of bytes
    Returns:
      the number of bytes read

  - ### getViewBytes

    int getViewBytes(long snap, Address start, ByteBuffer buf)
    Read the most recent bytes from the given snap and address, following schedule forks

    This behaves similarly to `getBytes(long, Address, ByteBuffer)`, except it checks for the `TraceMemoryState.KNOWN` state among each involved snap range and reads the applicable address ranges, preferring the most recent. Where memory is never known the buffer is left unmodified.

    Parameters:
      `snap` - the time
      `start` - the location
      `buf` - the destination buffer of bytes
    Returns:
      the number of bytes read

  - ### findBytes

    Address findBytes(long snap, AddressRange range, ByteBuffer data, ByteBuffer mask, boolean forward, TaskMonitor monitor)
    Search the given address range at the given snap for a given byte pattern
    Parameters:
      `snap` - the time to search
      `range` - the address range to search
      `data` - the values to search for
      `mask` - a mask on the bits of `data`; or null to match all bytes exactly
      `forward` - true to return the match with the lowest address in `range`, false for the highest address.
      `monitor` - a monitor for progress reporting and canceling
    Returns:
      the minimum address of the matched bytes, or `null` if not found

  - ### removeBytes

    void removeBytes(long snap, Address start, int len)
    Remove bytes from the given time and location

    This deletes all observed bytes from the given address through length at the given snap. If there were no observations in the range at exactly the given snap, this has no effect. If there were, then those observations are removed. The next time those bytes are read, they will have a value from a previous snap, or no value at all. The affected region's state is also deleted, i.e., set to `null`, implying `TraceMemoryState.UNKNOWN`.

    Note, use of this method is discouraged. The more observations within the same range that follow the deleted observation, the more expensive this operation typically is, since all of those observations may need to be updated.

    Parameters:
      `snap` - the time
      `start` - the location
      `len` - the number of bytes to remove

  - ### getBufferAt

    MemBuffer getBufferAt(long snap, Address start, ByteOrder byteOrder)
    Get a view of a particular snap as a memory buffer

    The bytes read by this buffer are the most recent bytes written before the given snap

    Parameters:
      `snap` - the snap
      `start` - the starting address
      `byteOrder` - the byte ordering for this buffer
    Returns:
      the memory buffer

  - ### getBufferAt

    default MemBuffer getBufferAt(long snap, Address start)
    Get a view of a particular snap as a memory buffer using the base language's byte order
    See Also:
      - `getBufferAt(long, Address, ByteOrder)`

  - ### getSnapOfMostRecentChangeToBlock

    Long getSnapOfMostRecentChangeToBlock(long snap, Address address)
    Find the internal storage block that most-recently defines the value at the given snap and address, and return the block's snap.

    This method reveals portions of the internal storage so that clients can optimize difference computations by eliminating corresponding ranges defined by the same block. If the underlying implementation cannot answer this question, this returns the given snap.

    Parameters:
      `snap` - the time
      `address` - the location
    Returns:
      the most snap for the most recent containing block

  - ### getBlockSize

    int getBlockSize()
    Get the block size used by internal storage.

    This method reveals portions of the internal storage so that clients can optimize searches. If the underlying implementation cannot answer this question, this returns 0.

    Returns:
      the block size

  - ### pack

    void pack()
    Optimize storage space

    This gives the implementation an opportunity to clean up garbage, apply compression, etc., in order to best use the storage space. Because memory observations can be sparse, a trace's memory is often compressible, and observations are not often modified or deleted, packing is recommended whenever the trace is saved to disk.

  - ### setState

    void setState(TracePlatform platform, long snap, Register register, TraceMemoryState state)
    Set the state of a given register at a given time

    Setting state to `TraceMemoryState.KNOWN` via this method is not recommended. Setting bytes will automatically update the state accordingly.

    Parameters:
      `platform` - the platform whose language defines the register
      `snap` - the time
      `register` - the register
      `state` - the state

  - ### setState

    default void setState(long snap, Register register, TraceMemoryState state)
    Set the state of a given register at a given time

    Setting state to `TraceMemoryState.KNOWN` via this method is not recommended. Setting bytes will automatically update the state accordingly.

    Parameters:
      `snap` - the time
      `register` - the register
      `state` - the state

  - ### getState

    TraceMemoryState getState(TracePlatform platform, long snap, Register register)
    Assert that a register's range has a single state at the given snap and get that state
    Parameters:
      `platform` - the platform whose language defines the register
      `snap` - the time
      `register` - the register to examine
    Returns:
      the state
    Throws:
      `IllegalStateException` - if the register is mapped to more than one state. See `getStates(long, Register)`

  - ### getState

    default TraceMemoryState getState(long snap, Register register)
    Assert that a register's range has a single state at the given snap and get that state
    Parameters:
      `snap` - the time
      `register` - the register to examine
    Returns:
      the state
    Throws:
      `IllegalStateException` - if the register is mapped to more than one state. See `getStates(long, Register)`

  - ### getStates

    Collection<Map.Entry<TraceAddressSnapRange,TraceMemoryState>> getStates(TracePlatform platform, long snap, Register register)
    Break the register's range into smaller ranges each mapped to its state at the given snap

    If the register is memory mapped, this will delegate to the appropriate space.

    Parameters:
      `platform` - the platform whose language defines the register
      `snap` - the time
      `register` - the register to examine
    Returns:
      the map of ranges to states

  - ### getStates

    default Collection<Map.Entry<TraceAddressSnapRange,TraceMemoryState>> getStates(long snap, Register register)
    Break the register's range into smaller ranges each mapped to its state at the given snap

    If the register is memory mapped, this will delegate to the appropriate space.

    Parameters:
      `snap` - the time
      `register` - the register to examine
    Returns:
      the map of ranges to states

  - ### setValue

    int setValue(TracePlatform platform, long snap, RegisterValue value)
    Parameters:
      `platform` - the platform whose language defines the register
      `snap` - the snap
      `value` - the register value
    Returns:
      the number of bytes written
    See Also:
      - `setValue(long, RegisterValue)`

  - ### setValue

    default int setValue(long snap, RegisterValue value)
    Set the value of a register at the given snap

    If the register is memory mapped, this will delegate to the appropriate space. In those cases, the assignment affects all threads.

    IMPORTANT: The trace database cannot track the state (`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 `TraceMemoryState.KNOWN`, even though the remaining 7 bits could technically be unknown.

    Parameters:
      `snap` - the snap
      `value` - the register value
    Returns:
      the number of bytes written

  - ### putBytes

    int putBytes(TracePlatform platform, long snap, Register register, ByteBuffer buf)
    Parameters:
      `platform` - the platform whose language defines the register
      `snap` - the snap
      `register` - the register to modify
      `buf` - the buffer of bytes to write
    Returns:
      the number of bytes written
    See Also:
      - `putBytes(long, Register, ByteBuffer)`

  - ### putBytes

    default int putBytes(long snap, Register register, ByteBuffer buf)
    Write bytes at the given snap and register address

    If the register is memory mapped, this will delegate to the appropriate space. In those cases, the assignment affects all threads.

    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 `setValue(long, RegisterValue)`.

    Parameters:
      `snap` - the snap
      `register` - the register to modify
      `buf` - the buffer of bytes to write
    Returns:
      the number of bytes written

  - ### getValue

    RegisterValue getValue(TracePlatform platform, long snap, Register register)
    Get the most-recent value of a given register at the given time

    If the register is memory mapped, this will delegate to the appropriate space.

    Parameters:
      `platform` - the platform whose language defines the register
      `snap` - the time
      `register` - the register
    Returns:
      the value

  - ### getValue

    default RegisterValue getValue(long snap, Register register)
    Get the most-recent value of a given register at the given time

    If the register is memory mapped, this will delegate to the appropriate space.

    Parameters:
      `snap` - the time
      `register` - the register
    Returns:
      the value

  - ### getViewValue

    RegisterValue getViewValue(TracePlatform platform, long snap, Register register)
    Get the most-recent value of a given register at the given time

    If the register is memory mapped, this will delegate to the appropriate space.

    Parameters:
      `platform` - the platform whose language defines the register
      `snap` - the time
      `register` - the register
    Returns:
      the value

  - ### getViewValue

    default RegisterValue getViewValue(long snap, Register register)
    Get the most-recent value of a given register at the given time, following schedule forks

    If the register is memory mapped, this will delegate to the appropriate space.

    Parameters:
      `snap` - the time
      `register` - the register
    Returns:
      the value

  - ### getBytes

    int getBytes(TracePlatform platform, long snap, Register register, ByteBuffer buf)
    Get the most-recent bytes of a given register at the given time

    If the register is memory mapped, this will delegate to the appropriate space.

    Parameters:
      `platform` - the platform whose language defines the register
      `snap` - the time
      `register` - the register
      `buf` - the destination buffer
    Returns:
      the number of bytes read

  - ### getBytes

    default int getBytes(long snap, Register register, ByteBuffer buf)
    Get the most-recent bytes of a given register at the given time

    If the register is memory mapped, this will delegate to the appropriate space.

    Parameters:
      `snap` - the time
      `register` - the register
      `buf` - the destination buffer
    Returns:
      the number of bytes read

  - ### removeValue

    void removeValue(TracePlatform platform, long snap, Register register)
    Parameters:
      `platform` - the platform whose language defines the register
      `snap` - the snap
      `register` - the register
    See Also:
      - `removeValue(long, Register)`

  - ### removeValue

    default void removeValue(long snap, Register register)
    Remove a value from the given time and register

    If the register is memory mapped, this will delegate to the appropriate space.

    IMPORANT: The trace database cannot track the state (`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 `TraceMemoryState.UNKNOWN`, even though the remaining 7 bits could technically be known.

    Parameters:
      `snap` - the snap
      `register` - the register