Package ghidra.pcode.emu

# Class DefaultPcodeThread<T>

java.lang.Object
ghidra.pcode.emu.DefaultPcodeThread<T>

All Implemented Interfaces:
  `PcodeThread<T>`

Direct Known Subclasses:
  `ModifiedPcodeThread`

public class DefaultPcodeThread<T> extends Object implements PcodeThread<T>
The default implementation of `PcodeThread` suitable for most applications

When emulating on concrete state, consider using `ModifiedPcodeThread`, so that state modifiers from the older `Emulator` are incorporated. In either case, it may be worthwhile to examine existing state modifiers to ensure they are appropriately represented in any abstract state. It may be necessary to port them.

This class implements the control-flow logic of the target machine, cooperating with the p-code program flow implemented by the `PcodeExecutor`. This implementation exists primarily in `beginInstructionOrInject()` and `advanceAfterFinished()`.

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `static class`
  `DefaultPcodeThread.PcodeEmulationLibrary<T>`
  A userop library exporting some methods for emulated thread control
  `static class`
  `DefaultPcodeThread.PcodeThreadExecutor<T>`
  An executor for the p-code thread

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected final PcodeArithmetic<T>`
  `arithmetic`
  `protected final Register`
  `contextreg`
  `protected final InstructionDecoder`
  `decoder`
  `protected final ProgramContextImpl`
  `defaultContext`
  `protected final DefaultPcodeThread.PcodeThreadExecutor<T>`
  `executor`
  `protected PcodeFrame`
  `frame`
  `protected final Map<Address,PcodeProgram>`
  `injects`
  `protected Instruction`
  `instruction`
  `protected final SleighLanguage`
  `language`
  `protected final PcodeUseropLibrary<T>`
  `library`
  `protected final Register`
  `pc`
  `protected final ThreadPcodeExecutorState<T>`
  `state`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `DefaultPcodeThread(String name, AbstractPcodeMachine<T> machine)`
  Construct a new thread

- ## Method Summary

  Modifier and Type
  Method
  Description
  `protected void`
  `advanceAfterFinished()`
  Resolve a finished instruction, advancing the program counter if necessary
  `protected void`
  `assertCompletedInstruction()`
  A sanity-checking measure: Cannot start a new instruction while one is still being executed
  `protected void`
  `assertMidInstruction()`
  A sanity-checking measure: Cannot finish an instruction unless one is currently being executed
  `void`
  `assignContext(RegisterValue context)`
  Adjust the thread's decoding context without writing to its executor state
  `protected void`
  `beginInstructionOrInject()`
  Start execution of the instruction or inject at the program counter
  `protected void`
  `branchToAddress(Address target)`
  `protected void`
  `checkLoad(AddressSpace space, T offset, int size)`
  Perform checks on a requested LOAD
  `protected void`
  `checkStore(AddressSpace space, T offset, int size)`
  Perform checks on a requested STORE
  `void`
  `clearAllInjects()`
  Remove all per-thread injects from this thread
  `void`
  `clearInject(Address address)`
  Remove the per-thread inject, if present, at the given address
  `protected DefaultPcodeThread.PcodeThreadExecutor<T>`
  `createExecutor()`
  A factory method to create the executor for this thread
  `protected SleighInstructionDecoder`
  `createInstructionDecoder(PcodeExecutorState<T> sharedState)`
  A factory method for the instruction decoder
  `protected PcodeUseropLibrary<T>`
  `createUseropLibrary()`
  A factory method to create the complete userop library for this thread
  `protected void`
  `doPluggableInitialization()`
  Execute the initializer upon this thread, if applicable
  `void`
  `dropInstruction()`
  If there is a current instruction, drop its frame of execution
  `void`
  `executeInstruction()`
  Execute the next instruction, ignoring injects
  `void`
  `finishInstruction()`
  Finish execution of the current instruction or inject
  `PcodeArithmetic<T>`
  `getArithmetic()`
  Get the thread's p-code arithmetic
  `RegisterValue`
  `getContext()`
  Get the thread's decoding context
  `protected RegisterValue`
  `getContextAfterCommits()`
  `Address`
  `getCounter()`
  Get the value of the program counter of this thread
  `PcodeExecutor<T>`
  `getExecutor()`
  Get the thread's p-code executor
  `PcodeFrame`
  `getFrame()`
  Get the current frame, if present
  `protected PcodeProgram`
  `getInject(Address address)`
  Check for a p-code injection (override) at the given address
  `Instruction`
  `getInstruction()`
  Get the current decoded instruction, if applicable
  `SleighLanguage`
  `getLanguage()`
  Get the thread's Sleigh language (processor model)
  `AbstractPcodeMachine<T>`
  `getMachine()`
  Get the machine within which this thread executes
  `String`
  `getName()`
  Get the name of this thread
  `ThreadPcodeExecutorState<T>`
  `getState()`
  Get the thread's memory and register state
  `PcodeUseropLibrary<T>`
  `getUseropLibrary()`
  Get the complete userop library for this thread
  `void`
  `inject(Address address, String source)`
  Override the p-code at the given address with the given Sleigh source for only this thread
  `boolean`
  `isSuspended()`
  Check the suspension state of the thread's executor
  `protected boolean`
  `onMissingUseropDef(PcodeOp op, String opName)`
  Extension point: Behavior when a p-code userop definition is not found
  `void`
  `overrideContext(RegisterValue context)`
  Adjust the thread's decoding context and write the contextreg of its executor state
  `void`
  `overrideContextWithDefault()`
  Set the context at the current counter to the default given by the language
  `void`
  `overrideCounter(Address counter)`
  Set the thread's program counter and write the pc register of its executor state
  `protected void`
  `postExecuteInstruction()`
  Extension point: Extra behavior after executing an instruction
  `protected void`
  `preExecuteInstruction()`
  Extension point: Extra behavior before executing an instruction
  `void`
  `reInitialize()`
  Re-sync the decode context and counter address from the machine state
  `void`
  `run()`
  Emulate indefinitely
  `void`
  `setCounter(Address counter)`
  Set the thread's program counter without writing to its executor state
  `void`
  `setSuspended(boolean suspended)`
  Set the suspension state of the thread's executor
  `void`
  `skipInstruction()`
  Decode, but skip the next instruction
  `void`
  `skipPcodeOp()`
  Skip emulation of a single p-code operation
  `void`
  `stepInstruction()`
  Step emulation a single instruction
  `void`
  `stepPatch(String sleigh)`
  Apply a patch to the emulator
  `void`
  `stepPcodeOp()`
  Step emulation a single p-code operation
  `protected void`
  `stepped()`
  Notify the machine a thread has been stepped a p-code op, so that it may re-enable software interrupts, if applicable
  `protected void`
  `swi()`
  Throw a software interrupt exception if those interrupts are active
  `protected void`
  `writeCounter(Address counter)`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

  ### Methods inherited from interface ghidra.pcode.emu.PcodeThread

  `stepInstruction, stepPcodeOp`

- ## Field Details

  - ### language

    protected final SleighLanguage language

  - ### arithmetic

    protected final PcodeArithmetic<T> arithmetic

  - ### state

    protected final ThreadPcodeExecutorState<T> state

  - ### decoder

    protected final InstructionDecoder decoder

  - ### library

    protected final PcodeUseropLibrary<T> library

  - ### executor

    protected final DefaultPcodeThread.PcodeThreadExecutor<T> executor

  - ### pc

    protected final Register pc

  - ### contextreg

    protected final Register contextreg

  - ### instruction

    protected Instruction instruction

  - ### frame

    protected PcodeFrame frame

  - ### defaultContext

    protected final ProgramContextImpl defaultContext

  - ### injects

    protected final Map<Address,PcodeProgram> injects

- ## Constructor Details

  - ### DefaultPcodeThread

    public DefaultPcodeThread(String name, AbstractPcodeMachine<T> machine)
    Construct a new thread
    Parameters:
      `name` - the name of the thread
      `machine` - the machine containing the thread
    See Also:
      - `AbstractPcodeMachine.createThread(String)`

- ## Method Details

  - ### createInstructionDecoder

    protected SleighInstructionDecoder createInstructionDecoder(PcodeExecutorState<T> sharedState)
    A factory method for the instruction decoder
    Parameters:
      `sharedState` - the machine's shared (memory state)
    Returns:

  - ### createUseropLibrary

    protected PcodeUseropLibrary<T> createUseropLibrary()
    A factory method to create the complete userop library for this thread

    The returned library must compose the containing machine's shared userop library. See `PcodeUseropLibrary.compose(PcodeUseropLibrary)`.

    Returns:
      the thread's complete userop library

  - ### createExecutor

    protected DefaultPcodeThread.PcodeThreadExecutor<T> createExecutor()
    A factory method to create the executor for this thread
    Returns:
      the executor

  - ### getName

    public String getName()
    Description copied from interface: `PcodeThread`
    Get the name of this thread
    Specified by:
      `getName` in interface `PcodeThread<T>`
    Returns:
      the name

  - ### getMachine

    public AbstractPcodeMachine<T> getMachine()
    Description copied from interface: `PcodeThread`
    Get the machine within which this thread executes
    Specified by:
      `getMachine` in interface `PcodeThread<T>`
    Returns:
      the containing machine

  - ### setCounter

    public void setCounter(Address counter)
    Description copied from interface: `PcodeThread`
    Set the thread's program counter without writing to its executor state
    Specified by:
      `setCounter` in interface `PcodeThread<T>`
    Parameters:
      `counter` - the new target address
    See Also:
      - `PcodeThread.overrideCounter(Address)`

  - ### getCounter

    public Address getCounter()
    Description copied from interface: `PcodeThread`
    Get the value of the program counter of this thread
    Specified by:
      `getCounter` in interface `PcodeThread<T>`
    Returns:
      the value

  - ### branchToAddress

    protected void branchToAddress(Address target)

  - ### writeCounter

    protected void writeCounter(Address counter)

  - ### overrideCounter

    public void overrideCounter(Address counter)
    Description copied from interface: `PcodeThread`
    Set the thread's program counter and write the pc register of its executor state

    Warning: Setting the counter into the middle of group constructs, e.g., parallel instructions or delay-slotted instructions, may cause undefined behavior.

    Specified by:
      `overrideCounter` in interface `PcodeThread<T>`
    Parameters:
      `counter` - the new target address
    See Also:
      - `PcodeThread.setCounter(Address)`

  - ### assignContext

    public void assignContext(RegisterValue context)
    Description copied from interface: `PcodeThread`
    Adjust the thread's decoding context without writing to its executor state

    As in `RegisterValue.assign(Register, RegisterValue)`, only those bits having a value in the given context are applied to the current context.

    Specified by:
      `assignContext` in interface `PcodeThread<T>`
    Parameters:
      `context` - the new context
    See Also:
      - `PcodeThread.overrideContext(RegisterValue)`

  - ### getContext

    public RegisterValue getContext()
    Description copied from interface: `PcodeThread`
    Get the thread's decoding context
    Specified by:
      `getContext` in interface `PcodeThread<T>`
    Returns:
      the context

  - ### overrideContext

    public void overrideContext(RegisterValue context)
    Description copied from interface: `PcodeThread`
    Adjust the thread's decoding context and write the contextreg of its executor state
    Specified by:
      `overrideContext` in interface `PcodeThread<T>`
    Parameters:
      `context` - the new context
    See Also:
      - `PcodeThread.assignContext(RegisterValue)`

  - ### overrideContextWithDefault

    public void overrideContextWithDefault()
    Description copied from interface: `PcodeThread`
    Set the context at the current counter to the default given by the language

    This also writes the context to the thread's state. For languages without context, this call does nothing.

    Specified by:
      `overrideContextWithDefault` in interface `PcodeThread<T>`

  - ### doPluggableInitialization

    protected void doPluggableInitialization()
    Execute the initializer upon this thread, if applicable
    See Also:
      - `AbstractPcodeMachine.getPluggableInitializer(Language)`

  - ### reInitialize

    public void reInitialize()
    Description copied from interface: `PcodeThread`
    Re-sync the decode context and counter address from the machine state
    Specified by:
      `reInitialize` in interface `PcodeThread<T>`

  - ### stepInstruction

    public void stepInstruction()
    Description copied from interface: `PcodeThread`
    Step emulation a single instruction

    Note because of the way Ghidra and Sleigh handle delay slots, the execution of an instruction with delay slots cannot be separated from the instructions filling those slots. It and its slotted instructions are executed in a single "step." However, stepping the individual p-code ops is still possible using `PcodeThread.stepPcodeOp()`.

    Specified by:
      `stepInstruction` in interface `PcodeThread<T>`

  - ### stepPcodeOp

    public void stepPcodeOp()
    Description copied from interface: `PcodeThread`
    Step emulation a single p-code operation

    Execution of the current instruction begins if there is no current frame: A new frame is constructed and its counter is initialized. If a frame is present, and it has not been completed, its next operation is executed and its counter is stepped. If the current frame is completed, the machine's program counter is advanced and the current frame is removed.

    Consider the case of a fall-through instruction: The first p-code step decodes the instruction and sets up the p-code frame. The second p-code step executes the first p-code op of the frame. Each subsequent p-code step executes the next p-code op until no ops remain. The final p-code step detects the fall-through result, advances the counter, and disposes the frame. The next p-code step is actually the first p-code step of the next instruction.

    Consider the case of a branching instruction: The first p-code step decodes the instruction and sets up the p-code frame. The second p-code step executes the first p-code op of the frame. Each subsequent p-code step executes the next p-code op until an (external) branch is executed. That branch itself sets the program counter appropriately. The final p-code step detects the branch result and simply disposes the frame. The next p-code step is actually the first p-code step of the next instruction.

    The decode step in both examples is subject to p-code injections. In order to provide the most flexibility, there is no enforcement of various emulation state on this method. Expect strange behavior for strange call sequences.

    While this method heeds injects, such injects will obscure the p-code of the instruction itself. If the inject executes the instruction, the entire instruction will be executed when stepping the `DefaultPcodeThread.PcodeEmulationLibrary.emu_exec_decoded()` userop, since there is not (currently) any way to "step into" a userop.

    Specified by:
      `stepPcodeOp` in interface `PcodeThread<T>`

  - ### skipPcodeOp

    public void skipPcodeOp()
    Description copied from interface: `PcodeThread`
    Skip emulation of a single p-code operation

    If there is no current frame, this behaves as in `PcodeThread.stepPcodeOp()`. Otherwise, this skips the current pcode op, advancing as if a fall-through op. If no ops remain in the frame, this behaves as in `PcodeThread.stepPcodeOp()`. Please note to skip an extranal branch, the op itself must be skipped. "Skipping" the following op, which disposes the frame, cannot prevent the branch.

    Specified by:
      `skipPcodeOp` in interface `PcodeThread<T>`

  - ### stepPatch

    public void stepPatch(String sleigh)
    Description copied from interface: `PcodeThread`
    Apply a patch to the emulator
    Specified by:
      `stepPatch` in interface `PcodeThread<T>`
    Parameters:
      `sleigh` - a line of sleigh semantic source to execute (excluding the final semicolon)

  - ### beginInstructionOrInject

    protected void beginInstructionOrInject()
    Start execution of the instruction or inject at the program counter

  - ### getContextAfterCommits

    protected RegisterValue getContextAfterCommits()

  - ### advanceAfterFinished

    protected void advanceAfterFinished()
    Resolve a finished instruction, advancing the program counter if necessary

  - ### getFrame

    public PcodeFrame getFrame()
    Description copied from interface: `PcodeThread`
    Get the current frame, if present

    If the client only calls `PcodeThread.stepInstruction()` and execution completes normally, this method will always return `null`. If interrupted, the frame marks where execution of an instruction or inject should resume. Depending on the case, the frame may need to be stepped back in order to retry the failed p-code operation. If this frame is present, it means that the instruction has not been executed completed. Even if the frame `PcodeFrame.isFinished()`,

    Specified by:
      `getFrame` in interface `PcodeThread<T>`
    Returns:
      the current frame

  - ### getInstruction

    public Instruction getInstruction()
    Description copied from interface: `PcodeThread`
    Get the current decoded instruction, if applicable
    Specified by:
      `getInstruction` in interface `PcodeThread<T>`
    Returns:
      the instruction

  - ### assertCompletedInstruction

    protected void assertCompletedInstruction()
    A sanity-checking measure: Cannot start a new instruction while one is still being executed

  - ### assertMidInstruction

    protected void assertMidInstruction()
    A sanity-checking measure: Cannot finish an instruction unless one is currently being executed

  - ### preExecuteInstruction

    protected void preExecuteInstruction()
    Extension point: Extra behavior before executing an instruction

    This is currently used for incorporating state modifiers from the older `Emulator` framework. There is likely utility here when porting those to this framework.

  - ### postExecuteInstruction

    protected void postExecuteInstruction()
    Extension point: Extra behavior after executing an instruction

    This is currently used for incorporating state modifiers from the older `Emulator` framework. There is likely utility here when porting those to this framework.

  - ### onMissingUseropDef

    protected boolean onMissingUseropDef(PcodeOp op, String opName)
    Extension point: Behavior when a p-code userop definition is not found
    Parameters:
      `op` - the op
      `opName` - the name of the p-code userop
    Returns:
      true if handle, false if still undefined

  - ### executeInstruction

    public void executeInstruction()
    Description copied from interface: `PcodeThread`
    Execute the next instruction, ignoring injects

    WARNING: This method should likely only be used internally. It steps the current instruction, but without any consideration for user injects, e.g., breakpoints. Most clients should call `PcodeThread.stepInstruction()` instead.

    Specified by:
      `executeInstruction` in interface `PcodeThread<T>`

  - ### finishInstruction

    public void finishInstruction()
    Description copied from interface: `PcodeThread`
    Finish execution of the current instruction or inject

    In general, this method is only used after an interrupt or fault in order to complete the p-code of the faulting instruction. Depending on the nature of the interrupt, this behavior may not be desired.

    Specified by:
      `finishInstruction` in interface `PcodeThread<T>`

  - ### skipInstruction

    public void skipInstruction()
    Description copied from interface: `PcodeThread`
    Decode, but skip the next instruction
    Specified by:
      `skipInstruction` in interface `PcodeThread<T>`

  - ### dropInstruction

    public void dropInstruction()
    Description copied from interface: `PcodeThread`
    If there is a current instruction, drop its frame of execution

    WARNING: This does not revert any state changes caused by a partially-executed instruction. It is up to the client to revert the underlying machine state if desired. Note the thread's program counter will not be advanced. Likely, the next call to `PcodeThread.stepInstruction()` will re-start the same instruction. If there is no current instruction, this method has no effect.

    Specified by:
      `dropInstruction` in interface `PcodeThread<T>`

  - ### run

    public void run()
    Description copied from interface: `PcodeThread`
    Emulate indefinitely

    This begins or resumes execution of the emulator. If there is a current instruction, that instruction is finished. By calling this method, you are "donating" the current Java thread to the emulator. This method will not likely return, but instead only terminates via exception, e.g., hitting a user breakpoint or becoming suspended. Depending on the use case, this method might be invoked from a Java thread dedicated to this emulated thread.

    Specified by:
      `run` in interface `PcodeThread<T>`

  - ### setSuspended

    public void setSuspended(boolean suspended)
    Description copied from interface: `PcodeThread`
    Set the suspension state of the thread's executor

    When `PcodeThread.run()` is invoked by a dedicated thread, suspending the pcode thread is the most reliable way to halt execution. Note the emulator may halt mid instruction. If this is not desired, then upon catching the exception, un-suspend the p-code thread and call `PcodeThread.finishInstruction()` or `PcodeThread.dropInstruction()`.

    Specified by:
      `setSuspended` in interface `PcodeThread<T>`

  - ### isSuspended

    public boolean isSuspended()
    Description copied from interface: `PcodeThread`
    Check the suspension state of the thread's executor
    Specified by:
      `isSuspended` in interface `PcodeThread<T>`
    Returns:
      true if suspended

  - ### getLanguage

    public SleighLanguage getLanguage()
    Description copied from interface: `PcodeThread`
    Get the thread's Sleigh language (processor model)
    Specified by:
      `getLanguage` in interface `PcodeThread<T>`
    Returns:
      the language

  - ### getArithmetic

    public PcodeArithmetic<T> getArithmetic()
    Description copied from interface: `PcodeThread`
    Get the thread's p-code arithmetic
    Specified by:
      `getArithmetic` in interface `PcodeThread<T>`
    Returns:
      the arithmetic

  - ### getExecutor

    public PcodeExecutor<T> getExecutor()
    Description copied from interface: `PcodeThread`
    Get the thread's p-code executor

    This can be used to execute injected p-code, e.g., as part of implementing a userop, or as part of testing, outside the thread's usual control flow. Any new frame generated by the executor is ignored by the thread. It retains the instruction frame, if any. Note that suspension is implemented by the executor, so if this p-code thread is suspended, the executor cannot execute any code.

    Specified by:
      `getExecutor` in interface `PcodeThread<T>`
    Returns:
      the executor

  - ### getUseropLibrary

    public PcodeUseropLibrary<T> getUseropLibrary()
    Description copied from interface: `PcodeThread`
    Get the complete userop library for this thread
    Specified by:
      `getUseropLibrary` in interface `PcodeThread<T>`
    Returns:
      the library

  - ### getState

    public ThreadPcodeExecutorState<T> getState()
    Description copied from interface: `PcodeThread`
    Get the thread's memory and register state

    The memory part of this state is shared among all threads in the same machine. See `PcodeMachine.getSharedState()`.

    Specified by:
      `getState` in interface `PcodeThread<T>`

  - ### getInject

    protected PcodeProgram getInject(Address address)
    Check for a p-code injection (override) at the given address

    This checks this thread's particular injects and then defers to the machine's injects.

    Parameters:
      `address` - the address, usually the program counter
    Returns:
      the injected program, most likely `null`

  - ### inject

    public void inject(Address address, String source)
    Description copied from interface: `PcodeThread`
    Override the p-code at the given address with the given Sleigh source for only this thread

    This works the same `PcodeMachine.inject(Address, String)` but on a per-thread basis. Where there is both a machine-level and thread-level inject the thread inject takes precedence. Furthermore, the machine-level inject cannot be accessed by the thread-level inject.

    Specified by:
      `inject` in interface `PcodeThread<T>`
    Parameters:
      `address` - the address to inject at
      `source` - the Sleigh source to compile and inject

  - ### clearInject

    public void clearInject(Address address)
    Description copied from interface: `PcodeThread`
    Remove the per-thread inject, if present, at the given address

    This has no effect on machine-level injects. If there is one present, it will still override this thread's p-code if execution reaches the address.

    Specified by:
      `clearInject` in interface `PcodeThread<T>`
    Parameters:
      `address` - the address to clear

  - ### clearAllInjects

    public void clearAllInjects()
    Description copied from interface: `PcodeThread`
    Remove all per-thread injects from this thread

    All machine-level injects are still effective after this call.

    Specified by:
      `clearAllInjects` in interface `PcodeThread<T>`

  - ### checkLoad

    protected void checkLoad(AddressSpace space, T offset, int size)
    Perform checks on a requested LOAD

    Throw an exception if the LOAD should cause an interrupt.

    Parameters:
      `space` - the address space being accessed
      `offset` - the offset being accessed
      `size` - the size of the variable being accessed

  - ### checkStore

    protected void checkStore(AddressSpace space, T offset, int size)
    Perform checks on a requested STORE

    Throw an exception if the STORE should cause an interrupt.

    Parameters:
      `space` - the address space being accessed
      `offset` - the offset being accessed
      `size` - the size of the variable being accessed

  - ### swi

    protected void swi()
    Throw a software interrupt exception if those interrupts are active

  - ### stepped

    protected void stepped()
    Notify the machine a thread has been stepped a p-code op, so that it may re-enable software interrupts, if applicable