Interface PcodeThread<T>
- Type Parameters:
T
- the type of values in the emulated machine state
- All Known Implementing Classes:
AuxPcodeThread
,BytesPcodeThread
,DefaultPcodeThread
,ModifiedPcodeThread
-
Method Summary
Modifier and TypeMethodDescriptionvoid
assignContext
(RegisterValue context) Adjust the thread's decoding context without writing to its executor statevoid
Remove all per-thread injects from this threadvoid
clearInject
(Address address) Remove the per-thread inject, if present, at the given addressvoid
If there is a current instruction, drop its frame of executionvoid
Execute the next instruction, ignoring injectsvoid
Finish execution of the current instruction or injectGet the thread's p-code arithmeticGet the thread's decoding contextGet the value of the program counter of this threadGet the thread's p-code executorgetFrame()
Get the current frame, if presentGet the current decoded instruction, if applicableGet the thread's Sleigh language (processor model)Get the machine within which this thread executesgetName()
Get the name of this threadgetState()
Get the thread's memory and register stateGet the complete userop library for this threadvoid
Override the p-code at the given address with the given Sleigh source for only this threadboolean
Check the suspension state of the thread's executorvoid
overrideContext
(RegisterValue context) Adjust the thread's decoding context and write the contextreg of its executor statevoid
Set the context at the current counter to the default given by the languagevoid
overrideCounter
(Address counter) Set the thread's program counter and write the pc register of its executor statevoid
Re-sync the decode context and counter address from the machine statevoid
run()
Emulate indefinitelyvoid
setCounter
(Address counter) Set the thread's program counter without writing to its executor statevoid
setSuspended
(boolean suspended) Set the suspension state of the thread's executorvoid
Decode, but skip the next instructionvoid
Skip emulation of a single p-code operationvoid
Step emulation a single instructiondefault void
stepInstruction
(long count) RepeatstepInstruction()
count timesvoid
Apply a patch to the emulatorvoid
Step emulation a single p-code operationdefault void
stepPcodeOp
(long count) RepeatstepPcodeOp()
count times
-
Method Details
-
getName
String getName()Get the name of this thread- Returns:
- the name
-
getMachine
PcodeMachine<T> getMachine()Get the machine within which this thread executes- Returns:
- the containing machine
-
setCounter
Set the thread's program counter without writing to its executor state- Parameters:
counter
- the new target address- See Also:
-
getCounter
Address getCounter()Get the value of the program counter of this thread- Returns:
- the value
-
overrideCounter
Set the thread's program counter and write the pc register of its executor stateWarning: Setting the counter into the middle of group constructs, e.g., parallel instructions or delay-slotted instructions, may cause undefined behavior.
- Parameters:
counter
- the new target address- See Also:
-
assignContext
Adjust the thread's decoding context without writing to its executor stateAs in
RegisterValue.assign(Register, RegisterValue)
, only those bits having a value in the given context are applied to the current context.- Parameters:
context
- the new context- See Also:
-
getContext
RegisterValue getContext()Get the thread's decoding context- Returns:
- the context
-
overrideContext
Adjust the thread's decoding context and write the contextreg of its executor state- Parameters:
context
- the new context- See Also:
-
overrideContextWithDefault
void overrideContextWithDefault()Set the context at the current counter to the default given by the languageThis also writes the context to the thread's state. For languages without context, this call does nothing.
-
reInitialize
void reInitialize()Re-sync the decode context and counter address from the machine state -
stepInstruction
void stepInstruction()Step emulation a single instructionNote 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
stepPcodeOp()
. -
stepInstruction
default void stepInstruction(long count) RepeatstepInstruction()
count times- Parameters:
count
- the number of instructions to step
-
stepPcodeOp
void stepPcodeOp()Step emulation a single p-code operationExecution 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. -
stepPcodeOp
default void stepPcodeOp(long count) RepeatstepPcodeOp()
count times- Parameters:
count
- the number of p-code operations to step
-
skipPcodeOp
void skipPcodeOp()Skip emulation of a single p-code operationIf there is no current frame, this behaves as in
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 instepPcodeOp()
. 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. -
stepPatch
Apply a patch to the emulator- Parameters:
sleigh
- a line of sleigh semantic source to execute (excluding the final semicolon)
-
getFrame
PcodeFrame getFrame()Get the current frame, if presentIf the client only calls
stepInstruction()
and execution completes normally, this method will always returnnull
. 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 framePcodeFrame.isFinished()
,- Returns:
- the current frame
-
getInstruction
Instruction getInstruction()Get the current decoded instruction, if applicable- Returns:
- the instruction
-
executeInstruction
void executeInstruction()Execute the next instruction, ignoring injectsWARNING: 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
stepInstruction()
instead.- Throws:
IllegalStateException
- if the emulator is still in the middle of an instruction. That can happen if the machine is interrupted, or if the client has calledstepPcodeOp()
.
-
finishInstruction
void finishInstruction()Finish execution of the current instruction or injectIn 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.
- Throws:
IllegalStateException
- if there is no current instruction, i.e., the emulator has not started executing the next instruction, yet.
-
skipInstruction
void skipInstruction()Decode, but skip the next instruction -
dropInstruction
void dropInstruction()If there is a current instruction, drop its frame of executionWARNING: 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
stepInstruction()
will re-start the same instruction. If there is no current instruction, this method has no effect. -
run
void run()Emulate indefinitelyThis 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.
-
setSuspended
void setSuspended(boolean suspended) Set the suspension state of the thread's executorWhen
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 callfinishInstruction()
ordropInstruction()
.- Parameters:
suspended
- true to suspend the machine, false to let it run- See Also:
-
isSuspended
boolean isSuspended()Check the suspension state of the thread's executor- Returns:
- true if suspended
-
getLanguage
SleighLanguage getLanguage()Get the thread's Sleigh language (processor model)- Returns:
- the language
-
getArithmetic
PcodeArithmetic<T> getArithmetic()Get the thread's p-code arithmetic- Returns:
- the arithmetic
-
getExecutor
PcodeExecutor<T> getExecutor()Get the thread's p-code executorThis 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.
- Returns:
- the executor
-
getUseropLibrary
PcodeUseropLibrary<T> getUseropLibrary()Get the complete userop library for this thread- Returns:
- the library
-
getState
ThreadPcodeExecutorState<T> getState()Get the thread's memory and register stateThe memory part of this state is shared among all threads in the same machine. See
PcodeMachine.getSharedState()
.- Returns:
- the state
-
inject
Override the p-code at the given address with the given Sleigh source for only this threadThis 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.- Parameters:
address
- the address to inject atsource
- the Sleigh source to compile and inject
-
clearInject
Remove the per-thread inject, if present, at the given addressThis 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.
- Parameters:
address
- the address to clear
-
clearAllInjects
void clearAllInjects()Remove all per-thread injects from this threadAll machine-level injects are still effective after this call.
-