Interface Target


public interface Target
The interface between the front-end UI and the back-end connector.

Anything the UI might command a target to do must be defined as a method here. Each implementation can then sort out, using context from the UI as appropriate, how best to effect the command using the protocol and resources available on the back-end.

  • Field Details

  • Method Details

    • describe

      String describe()
      Describe the target for display in the UI
      Returns:
      the description
    • isValid

      boolean isValid()
      Check if the target is still valid
      Returns:
      true if valid
    • getTrace

      Trace getTrace()
      Get the trace into which this target is recorded
      Returns:
      the trace
    • getSnap

      long getSnap()
      Get the current snapshot key for the target

      For most targets, this is the most recently created snapshot. For time-traveling targets, if may not be. If this returns a negative number, then it refers to a scratch snapshot and almost certainly indicates time travel with instruction steps. Use getTime() in that case to get a more precise schedule.

      Returns:
      the snapshot
    • getTime

      default TraceSchedule getTime()
      Get the current time
      Returns:
      the current time
    • getSupportedTimeForm

      TraceSchedule.ScheduleForm getSupportedTimeForm(TraceObject obj, long snap)
      Get the form of schedules supported by "activate" on the back end

      A non-null return value indicates the back end supports time travel. If it does, the return value indicates the form of schedules that can be activated, (i.e., via some "go to time" command). NOTE: Switching threads is considered an event by every time-traveling back end that we know of. Events are usually mapped to a Ghidra trace's snapshots, and so most back ends are constrained to schedules of the form TraceSchedule.ScheduleForm.SNAP_EVT_STEPS. A back-end based on emulation may support thread switching. To support p-code op stepping, the back-end will certainly have to be based on p-code emulation, and it must be using the same Sleigh language as Ghidra.

      Parameters:
      obj - the object (or an ancestor) that may support time travel
      snap - the destination snapshot
      Returns:
      the form
    • collectActions

      Collect all actions that implement the given common debugger command

      Note that if the context provides a program location (i.e., address), the object policy is ignored. It will use current and related objects.

      Parameters:
      name - the action name
      context - applicable context from the UI
      policy - determines how objects may be found
      Returns:
      the collected actions
    • executeAsync

      CompletableFuture<String> executeAsync(String command, boolean toString)
      See Also:
    • execute

      String execute(String command, boolean toString)
      Execute a command as if in the CLI
      Parameters:
      command - the command
      toString - true to capture the output and return it, false to print to the terminal
      Returns:
      the captured output, or null if toString is false
    • getThreadForSuccessor

      TraceThread getThreadForSuccessor(KeyPath path)
      Get the trace thread that contains the given object
      Parameters:
      path - the path of the object
      Returns:
      the thread, or null
    • getThreadExecutionState

      TraceExecutionState getThreadExecutionState(TraceThread thread)
      Get the execution state of the given thread
      Parameters:
      thread - the thread
      Returns:
      the state
    • getStackFrameForSuccessor

      TraceStackFrame getStackFrameForSuccessor(KeyPath path)
      Get the trace stack frame that contains the given object
      Parameters:
      path - the path of the object
      Returns:
      the stack frame, or null
    • isSupportsFocus

      boolean isSupportsFocus()
      Check if the target supports synchronizing focus
      Returns:
      true if supported
    • getFocus

      KeyPath getFocus()
      Get the object that currently has focus on the back end's UI
      Returns:
      the focused object's path, or null
    • activateAsync

      See Also:
    • activate

      void activate(DebuggerCoordinates prev, DebuggerCoordinates coords)
      Request that the back end's focus be set to the same as the front end's (Ghidra's) GUI.
      Parameters:
      prev - the GUI's immediately previous coordinates
      coords - the GUI's current coordinates
    • invalidateMemoryCachesAsync

      CompletableFuture<Void> invalidateMemoryCachesAsync()
      See Also:
    • invalidateMemoryCaches

      void invalidateMemoryCaches()
      Invalidate any caches on the target's back end or on the client side of the connection.

      In general, back ends should avoid doing any caching. Instead, the front-end will assume anything marked TraceMemoryState.KNOWN is up to date. I.e., the trace database acts as the client-side cache for a live target.

      NOTE: This method exists for invalidating model-based target caches. It may be deprecated and removed, unless it turns out we need this for Trace RMI, too.

    • readMemoryAsync

      CompletableFuture<Void> readMemoryAsync(AddressSetView set, TaskMonitor monitor)
      See Also:
    • readMemory

      void readMemory(AddressSetView set, TaskMonitor monitor) throws CancelledException
      Read and capture several ranges of target memory

      The target may read more than the requested memory, usually because it will read all pages containing any portion of the requested set. The target should attempt to read at least the given memory. To the extent it is successful, it must cause the values to be recorded into the trace before this method returns. Only if the request is entirely unsuccessful should this method throw an exception. Otherwise, the failed portions, if any, should be logged without throwing an exception.

      Parameters:
      set - the addresses to capture
      monitor - a monitor for displaying task steps
      Throws:
      CancelledException - if the operation is cancelled
    • writeMemoryAsync

      CompletableFuture<Void> writeMemoryAsync(Address address, byte[] data)
      See Also:
    • writeMemory

      void writeMemory(Address address, byte[] data)
      Write data to the target's memory

      The target should attempt to write the memory. To the extent it is successful, it must cause the effects to be recorded into the trace before this method returns. Only if the request is entirely unsuccessful should this method throw an exception. Otherwise, the failed portions, if any, should be logged without throwing an exception.

      Parameters:
      address - the starting address
      data - the bytes to write
    • readRegistersAsync

      CompletableFuture<Void> readRegistersAsync(TracePlatform platform, TraceThread thread, int frame, Set<Register> registers)
      See Also:
    • readRegisters

      void readRegisters(TracePlatform platform, TraceThread thread, int frame, Set<Register> registers)
      Read and capture the named target registers for the given platform, thread, and frame.

      Target target should read the registers and, to the extent it is successful, cause the values to be recorded into the trace before this method returns. Only if the request is entirely unsuccessful should this method throw an exception. Otherwise, the failed registers, if any, should be logged without throwing an exception.

      Parameters:
      platform - the platform defining the registers
      thread - the thread whose context contains the register values
      frame - the frame, if applicable, for saved register values. 0 for current values.
      registers - the registers to read
    • readRegistersAsync

      CompletableFuture<Void> readRegistersAsync(TracePlatform platform, TraceThread thread, int frame, AddressSetView guestSet)
      See Also:
    • readRegisters

      void readRegisters(TracePlatform platform, TraceThread thread, int frame, AddressSetView guestSet)
      Read and capture the target registers in the given address set.

      Aside from how registers are named, this works equivalently to readRegisters(TracePlatform, TraceThread, int, Set).

    • writeRegisterAsync

      CompletableFuture<Void> writeRegisterAsync(TracePlatform platform, TraceThread thread, int frame, RegisterValue value)
      See Also:
    • writeRegister

      void writeRegister(TracePlatform platform, TraceThread thread, int frame, RegisterValue value)
      Write a value to a target register for the given platform, thread, and frame

      The target should attempt to write the register. If successful, it must cause the effects to be recorded into the trace before this method returns. If the request is unsuccessful, this method throw an exception.

      Parameters:
      platform - the platform whose language defines the registers
      thread - the thread whose register to write
      frame - the frame level, usually 0.
      value - the register and value to write
    • writeRegisterAsync

      CompletableFuture<Void> writeRegisterAsync(TracePlatform platform, TraceThread thread, int frame, Address address, byte[] data)
      See Also:
    • writeRegister

      void writeRegister(TracePlatform platform, TraceThread thread, int frame, Address address, byte[] data)
      Write a value to a target register by its address

      Aside from how the register is named, this works equivalently to writeRegister(TracePlatform, TraceThread, int, RegisterValue). The address is the one defined by Ghidra.

    • isVariableExists

      boolean isVariableExists(TracePlatform platform, TraceThread thread, int frame, Address address, int length)
      Check if a given variable (register or memory) exists on target
      Parameters:
      platform - the platform whose language defines the registers
      thread - if a register, the thread whose registers to examine
      frame - the frame level, usually 0.
      address - the address of the variable
      length - the size of the variable. Ignored for memory
      Returns:
      true if the variable can be mapped to the target
    • writeVariableAsync

      CompletableFuture<Void> writeVariableAsync(TracePlatform platform, TraceThread thread, int frame, Address address, byte[] data)
      See Also:
    • writeVariable

      void writeVariable(TracePlatform platform, TraceThread thread, int frame, Address address, byte[] data)
      Write a variable (memory or register) of the given thread or the process

      This is a convenience for writing target memory or registers, based on address. If the given address represents a register, this will attempt to map it to a register and write it in the given thread and frame. If the address is in memory, it will simply delegate to writeMemory(Address, byte[]).

      Parameters:
      thread - the thread. Ignored (may be null) if address is in memory
      frame - the frame, usually 0. Ignored if address is in memory
      address - the starting address
      data - the value to write
    • getSupportedBreakpointKinds

      Set<TraceBreakpointKind> getSupportedBreakpointKinds()
      Get the kinds of breakpoints supported by the target.
      Returns:
      the set of kinds
    • placeBreakpointAsync

      CompletableFuture<Void> placeBreakpointAsync(AddressRange range, Set<TraceBreakpointKind> kinds, String condition, String commands)
      See Also:
    • placeBreakpoint

      void placeBreakpoint(AddressRange range, Set<TraceBreakpointKind> kinds, String condition, String commands)
      Place a new breakpoint of the given kind(s) over the given range

      If successful, this method must cause the breakpoint to be recorded into the trace. Otherwise, it should throw an exception.

      Parameters:
      range - the range. NOTE: The target is only required to support length-1 execution breakpoints.
      kinds - the kind(s) of the breakpoint.
      condition - optionally, a condition for the breakpoint, expressed in the back-end's language. NOTE: May be silently ignored by the implementation, if not supported.
      commands - optionally, a command to execute upon hitting the breakpoint, expressed in the back-end's language. NOTE: May be silently ignored by the implementation, if not supported.
    • isBreakpointValid

      boolean isBreakpointValid(TraceBreakpointLocation breakpoint)
      Check if the given breakpoint (location) is still valid on target
      Parameters:
      breakpoint - the breakpoint
      Returns:
      true if valid
    • deleteBreakpointAsync

      CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpointCommon breakpoint)
      See Also:
    • deleteBreakpoint

      void deleteBreakpoint(TraceBreakpointCommon breakpoint)
      Delete the given breakpoint from the target

      If successful, this method must cause the breakpoint removal to be recorded in the trace. Otherwise, it should throw an exception.

      Parameters:
      breakpoint - the breakpoint to delete
    • toggleBreakpointAsync

      CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpointCommon breakpoint, boolean enabled)
      See Also:
    • toggleBreakpoint

      void toggleBreakpoint(TraceBreakpointCommon breakpoint, boolean enabled)
      Toggle the given breakpoint on the target

      If successful, this method must cause the breakpoint toggle to be recorded in the trace. If the state is already as desired, this method may have no effect. If unsuccessful, this method should throw an exception.

      Parameters:
      breakpoint - the breakpoint to toggle
      enabled - true to enable, false to disable
    • forceTerminateAsync

      CompletableFuture<Void> forceTerminateAsync()
      See Also:
    • forceTerminate

      void forceTerminate()
      Forcefully terminate the target

      This will first attempt to kill the target gracefully. In addition, and whether or not the target is successfully terminated, the target will be dissociated from its trace, and the target will be invalidated. To attempt only a graceful termination, check collectActions(ActionName, ActionContext, ObjectArgumentPolicy) with ActionName.KILL.

    • disconnectAsync

      CompletableFuture<Void> disconnectAsync()
      See Also:
    • disconnect

      void disconnect()
      Terminate the target and its connection

      WARNING: This terminates the connection, even if there are other live targets still using it. One example where this might happen is if the target process launches a child, and the debugger is configured to remain attached to both. Whether this is expected or acceptable behavior has not been decided.

      NOTE: This method cannot be invoked on the Swing thread, because it may block on I/O.

      See Also:
    • isBusy

      boolean isBusy()
      Check if the target is busy updating the trace

      This generally means the connection has an open transaction. If does not indicate the execution state of the target/debuggee.

      Returns:
      true if busy
    • forciblyCloseTransactions

      void forciblyCloseTransactions()
      Forcibly commit all of the back-ends transactions on this target's trace.

      This is generally not a recommended course of action, except that sometimes the back-end crashes and fails to close a transaction. It should only be invoked by a relatively hidden menu option, and mediated by a warning of some sort. Closing a transaction prematurely, when the back-end actually does still need it may cause a host of other problems.