Class DefaultPcodeThread<T>
- All Implemented Interfaces:
PcodeThread<T>
- Direct Known Subclasses:
ModifiedPcodeThread
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
Modifier and TypeClassDescriptionstatic class
A userop library exporting some methods for emulated thread controlstatic class
An executor for the p-code thread -
Field Summary
Modifier and TypeFieldDescriptionprotected final PcodeArithmetic
<T> protected final Register
protected final InstructionDecoder
protected final ProgramContextImpl
protected final DefaultPcodeThread.PcodeThreadExecutor
<T> protected PcodeFrame
protected final Map
<Address, PcodeProgram> protected Instruction
protected final SleighLanguage
protected final PcodeUseropLibrary
<T> protected final Register
protected final ThreadPcodeExecutorState
<T> -
Constructor Summary
ConstructorDescriptionDefaultPcodeThread
(String name, AbstractPcodeMachine<T> machine) Construct a new thread -
Method Summary
Modifier and TypeMethodDescriptionprotected void
Resolve a finished instruction, advancing the program counter if necessaryprotected void
A sanity-checking measure: Cannot start a new instruction while one is still being executedprotected void
A sanity-checking measure: Cannot finish an instruction unless one is currently being executedvoid
assignContext
(RegisterValue context) Adjust the thread's decoding context without writing to its executor stateprotected void
Start execution of the instruction or inject at the program counterprotected void
branchToAddress
(Address target) protected void
checkLoad
(AddressSpace space, T offset, int size) Perform checks on a requested LOADprotected void
checkStore
(AddressSpace space, T offset, int size) Perform checks on a requested STOREvoid
Remove all per-thread injects from this threadvoid
clearInject
(Address address) Remove the per-thread inject, if present, at the given addressprotected DefaultPcodeThread.PcodeThreadExecutor
<T> A factory method to create the executor for this threadprotected SleighInstructionDecoder
createInstructionDecoder
(PcodeExecutorState<T> sharedState) A factory method for the instruction decoderprotected PcodeUseropLibrary
<T> A factory method to create the complete userop library for this threadprotected void
Execute the initializer upon this thread, if applicablevoid
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 contextprotected RegisterValue
Get the value of the program counter of this threadGet the thread's p-code executorgetFrame()
Get the current frame, if presentprotected PcodeProgram
Check for a p-code injection (override) at the given addressGet 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 executorprotected boolean
onMissingUseropDef
(PcodeOp op, String opName) Extension point: Behavior when a p-code userop definition is not foundvoid
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 stateprotected void
Extension point: Extra behavior after executing an instructionprotected void
Extension point: Extra behavior before executing an instructionvoid
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 instructionvoid
Apply a patch to the emulatorvoid
Step emulation a single p-code operationprotected void
stepped()
Notify the machine a thread has been stepped a p-code op, so that it may re-enable software interrupts, if applicableprotected void
swi()
Throw a software interrupt exception if those interrupts are activeprotected 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
-
arithmetic
-
state
-
decoder
-
library
-
executor
-
pc
-
contextreg
-
instruction
-
frame
-
defaultContext
-
injects
-
-
Constructor Details
-
DefaultPcodeThread
Construct a new thread- Parameters:
name
- the name of the threadmachine
- the machine containing the thread- See Also:
-
-
Method Details
-
createInstructionDecoder
A factory method for the instruction decoder- Parameters:
sharedState
- the machine's shared (memory state)- Returns:
-
createUseropLibrary
A factory method to create the complete userop library for this threadThe returned library must compose the containing machine's shared userop library. See
PcodeUseropLibrary.compose(PcodeUseropLibrary)
.- Returns:
- the thread's complete userop library
-
createExecutor
A factory method to create the executor for this thread- Returns:
- the executor
-
getName
Description copied from interface:PcodeThread
Get the name of this thread- Specified by:
getName
in interfacePcodeThread<T>
- Returns:
- the name
-
getMachine
Description copied from interface:PcodeThread
Get the machine within which this thread executes- Specified by:
getMachine
in interfacePcodeThread<T>
- Returns:
- the containing machine
-
setCounter
Description copied from interface:PcodeThread
Set the thread's program counter without writing to its executor state- Specified by:
setCounter
in interfacePcodeThread<T>
- Parameters:
counter
- the new target address- See Also:
-
getCounter
Description copied from interface:PcodeThread
Get the value of the program counter of this thread- Specified by:
getCounter
in interfacePcodeThread<T>
- Returns:
- the value
-
branchToAddress
-
writeCounter
-
overrideCounter
Description copied from interface:PcodeThread
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.
- Specified by:
overrideCounter
in interfacePcodeThread<T>
- Parameters:
counter
- the new target address- See Also:
-
assignContext
Description copied from interface:PcodeThread
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.- Specified by:
assignContext
in interfacePcodeThread<T>
- Parameters:
context
- the new context- See Also:
-
getContext
Description copied from interface:PcodeThread
Get the thread's decoding context- Specified by:
getContext
in interfacePcodeThread<T>
- Returns:
- the context
-
overrideContext
Description copied from interface:PcodeThread
Adjust the thread's decoding context and write the contextreg of its executor state- Specified by:
overrideContext
in interfacePcodeThread<T>
- Parameters:
context
- the new context- See Also:
-
overrideContextWithDefault
public void overrideContextWithDefault()Description copied from interface:PcodeThread
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.
- Specified by:
overrideContextWithDefault
in interfacePcodeThread<T>
-
doPluggableInitialization
protected void doPluggableInitialization()Execute the initializer upon this thread, if applicable- See Also:
-
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 interfacePcodeThread<T>
-
stepInstruction
public void stepInstruction()Description copied from interface:PcodeThread
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
PcodeThread.stepPcodeOp()
.- Specified by:
stepInstruction
in interfacePcodeThread<T>
-
stepPcodeOp
public void stepPcodeOp()Description copied from interface:PcodeThread
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.- Specified by:
stepPcodeOp
in interfacePcodeThread<T>
-
skipPcodeOp
public void skipPcodeOp()Description copied from interface:PcodeThread
Skip emulation of a single p-code operationIf 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 inPcodeThread.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 interfacePcodeThread<T>
-
stepPatch
Description copied from interface:PcodeThread
Apply a patch to the emulator- Specified by:
stepPatch
in interfacePcodeThread<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
-
advanceAfterFinished
protected void advanceAfterFinished()Resolve a finished instruction, advancing the program counter if necessary -
getFrame
Description copied from interface:PcodeThread
Get the current frame, if presentIf the client only calls
PcodeThread.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()
,- Specified by:
getFrame
in interfacePcodeThread<T>
- Returns:
- the current frame
-
getInstruction
Description copied from interface:PcodeThread
Get the current decoded instruction, if applicable- Specified by:
getInstruction
in interfacePcodeThread<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 instructionThis 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 instructionThis is currently used for incorporating state modifiers from the older
Emulator
framework. There is likely utility here when porting those to this framework. -
onMissingUseropDef
Extension point: Behavior when a p-code userop definition is not found- Parameters:
op
- the opopName
- 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 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
PcodeThread.stepInstruction()
instead.- Specified by:
executeInstruction
in interfacePcodeThread<T>
-
finishInstruction
public void finishInstruction()Description copied from interface:PcodeThread
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.
- Specified by:
finishInstruction
in interfacePcodeThread<T>
-
skipInstruction
public void skipInstruction()Description copied from interface:PcodeThread
Decode, but skip the next instruction- Specified by:
skipInstruction
in interfacePcodeThread<T>
-
dropInstruction
public void dropInstruction()Description copied from interface:PcodeThread
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
PcodeThread.stepInstruction()
will re-start the same instruction. If there is no current instruction, this method has no effect.- Specified by:
dropInstruction
in interfacePcodeThread<T>
-
run
public void run()Description copied from interface:PcodeThread
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.
- Specified by:
run
in interfacePcodeThread<T>
-
setSuspended
public void setSuspended(boolean suspended) Description copied from interface:PcodeThread
Set the suspension state of the thread's executorWhen
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 callPcodeThread.finishInstruction()
orPcodeThread.dropInstruction()
.- Specified by:
setSuspended
in interfacePcodeThread<T>
- Parameters:
suspended
- true to suspend the machine, false to let it run- See Also:
-
isSuspended
public boolean isSuspended()Description copied from interface:PcodeThread
Check the suspension state of the thread's executor- Specified by:
isSuspended
in interfacePcodeThread<T>
- Returns:
- true if suspended
-
getLanguage
Description copied from interface:PcodeThread
Get the thread's Sleigh language (processor model)- Specified by:
getLanguage
in interfacePcodeThread<T>
- Returns:
- the language
-
getArithmetic
Description copied from interface:PcodeThread
Get the thread's p-code arithmetic- Specified by:
getArithmetic
in interfacePcodeThread<T>
- Returns:
- the arithmetic
-
getExecutor
Description copied from interface:PcodeThread
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.
- Specified by:
getExecutor
in interfacePcodeThread<T>
- Returns:
- the executor
-
getUseropLibrary
Description copied from interface:PcodeThread
Get the complete userop library for this thread- Specified by:
getUseropLibrary
in interfacePcodeThread<T>
- Returns:
- the library
-
getState
Description copied from interface:PcodeThread
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()
.- Specified by:
getState
in interfacePcodeThread<T>
- Returns:
- the state
-
getInject
Check for a p-code injection (override) at the given addressThis 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
Description copied from interface:PcodeThread
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.- Specified by:
inject
in interfacePcodeThread<T>
- Parameters:
address
- the address to inject atsource
- the Sleigh source to compile and inject
-
clearInject
Description copied from interface:PcodeThread
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.
- Specified by:
clearInject
in interfacePcodeThread<T>
- Parameters:
address
- the address to clear
-
clearAllInjects
public void clearAllInjects()Description copied from interface:PcodeThread
Remove all per-thread injects from this threadAll machine-level injects are still effective after this call.
- Specified by:
clearAllInjects
in interfacePcodeThread<T>
-
checkLoad
Perform checks on a requested LOADThrow an exception if the LOAD should cause an interrupt.
- Parameters:
space
- the address space being accessedoffset
- the offset being accessedsize
- the size of the variable being accessed
-
checkStore
Perform checks on a requested STOREThrow an exception if the STORE should cause an interrupt.
- Parameters:
space
- the address space being accessedoffset
- the offset being accessedsize
- 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
-