Class DefaultPcodeThread<T>
- Type Parameters:
T- the type of variables in the emulator
- 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
Nested ClassesModifier and TypeClassDescriptionstatic classA userop library exporting some methods for emulated thread controlstatic classAn executor for the p-code thread -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected final PcodeArithmetic<T> protected final Registerprotected final InstructionDecoderprotected final ProgramContextImplprotected final DefaultPcodeThread.PcodeThreadExecutor<T> protected PcodeFrameprotected final Map<Address, PcodeProgram> protected Instructionprotected final SleighLanguageprotected final Registerprotected final ThreadPcodeExecutorState<T> -
Constructor Summary
ConstructorsConstructorDescriptionDefaultPcodeThread(String name, AbstractPcodeMachine<T> machine) Construct a new thread -
Method Summary
Modifier and TypeMethodDescriptionprotected voidResolve a finished instruction, advancing the program counter if necessaryprotected voidA sanity-checking measure: Cannot start a new instruction while one is still being executedprotected voidA sanity-checking measure: Cannot finish an instruction unless one is currently being executedvoidassignContext(RegisterValue context) Adjust the thread's decoding context without writing to its executor stateprotected voidStart execution of the instruction or inject at the program counterprotected voidbranchToAddress(Address target) protected voidcheckLoad(AddressSpace space, T offset, int size) Perform checks on a requested LOADprotected voidcheckStore(AddressSpace space, T offset, int size) Perform checks on a requested STOREvoidRemove all per-thread injects from this threadvoidclearInject(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 SleighInstructionDecodercreateInstructionDecoder(PcodeExecutorState<T> sharedState) A factory method for the instruction decoderprotected ThreadPcodeExecutorState<T> createThreadState(PcodeExecutorState<T> sharedState, PcodeExecutorState<T> localState) A factory method for the thread's (multiplexed) stateprotected PcodeUseropLibrary<T> A factory method to create the complete userop library for this threadprotected voidExecute the initializer upon this thread, if applicablevoidIf there is a current instruction, drop its frame of executionvoidExecute the next instruction, ignoring injectsvoidFinish execution of the current instruction or injectGet the thread's p-code arithmeticGet the thread's decoding contextprotected RegisterValuestatic RegisterValuegetContextAfterCommits(Instruction instruction, long counter) Get the value of the program counter of this threadGet the thread's p-code executorgetFrame()Get the current frame, if presentprotected PcodeProgramCheck 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 threadvoidOverride the p-code at the given address with the given Sleigh source for only this threadbooleanCheck the suspension state of the thread's executorprotected booleanonMissingUseropDef(PcodeOp op, String opName) Extension point: Behavior when a p-code userop definition is not foundvoidoverrideContext(RegisterValue context) Adjust the thread's decoding context and write the contextreg of its executor statevoidSet the context at the current counter to the default given by the languagevoidoverrideCounter(Address counter) Set the thread's program counter and write the pc register of its executor stateprotected voidExtension point: Extra behavior after executing an instructionprotected voidExtension point: Extra behavior before executing an instructionvoidRe-sync the decode context and counter address from the machine statevoidrun()Emulate indefinitelyvoidsetCounter(Address counter) Set the thread's program counter without writing to its executor statevoidsetSuspended(boolean suspended) Set the suspension state of the thread's executorvoidDecode, but skip the next instructionvoidSkip emulation of a single p-code operationvoidStep emulation a single instructionvoidApply a patch to the emulatorvoidStep emulation a single p-code operationprotected voidstepped()Notify the machine a thread has been stepped a p-code op, so that it may re-enable software interrupts, if applicableprotected voidswi()Throw a software interrupt exception if those interrupts are activeprotected final voidwriteContext(RegisterValue context) protected final voidwriteCounter(Address counter) Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface ghidra.pcode.emu.PcodeThread
stepInstruction, stepPcodeOp
-
Field Details
-
language
-
arithmetic
-
state
-
decoder
-
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
-
createThreadState
protected ThreadPcodeExecutorState<T> createThreadState(PcodeExecutorState<T> sharedState, PcodeExecutorState<T> localState) A factory method for the thread's (multiplexed) state- Parameters:
sharedState- the shared part of the statelocalState- the thread-local part of the state- Returns:
- the complete state
-
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:PcodeThreadGet the name of this thread- Specified by:
getNamein interfacePcodeThread<T>- Returns:
- the name
-
getMachine
Description copied from interface:PcodeThreadGet the machine within which this thread executes- Specified by:
getMachinein interfacePcodeThread<T>- Returns:
- the containing machine
-
setCounter
Description copied from interface:PcodeThreadSet the thread's program counter without writing to its executor state- Specified by:
setCounterin interfacePcodeThread<T>- Parameters:
counter- the new target address- See Also:
-
getCounter
Description copied from interface:PcodeThreadGet the value of the program counter of this thread- Specified by:
getCounterin interfacePcodeThread<T>- Returns:
- the value
-
branchToAddress
-
writeCounter
-
overrideCounter
Description copied from interface:PcodeThreadSet 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:
overrideCounterin interfacePcodeThread<T>- Parameters:
counter- the new target address- See Also:
-
assignContext
Description copied from interface:PcodeThreadAdjust 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:
assignContextin interfacePcodeThread<T>- Parameters:
context- the new context- See Also:
-
getContext
Description copied from interface:PcodeThreadGet the thread's decoding context- Specified by:
getContextin interfacePcodeThread<T>- Returns:
- the context
-
writeContext
-
overrideContext
Description copied from interface:PcodeThreadAdjust the thread's decoding context and write the contextreg of its executor state- Specified by:
overrideContextin interfacePcodeThread<T>- Parameters:
context- the new context- See Also:
-
overrideContextWithDefault
public void overrideContextWithDefault()Description copied from interface:PcodeThreadSet 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:
overrideContextWithDefaultin interfacePcodeThread<T>
-
doPluggableInitialization
protected void doPluggableInitialization()Execute the initializer upon this thread, if applicable- See Also:
-
reInitialize
public void reInitialize()Description copied from interface:PcodeThreadRe-sync the decode context and counter address from the machine state- Specified by:
reInitializein interfacePcodeThread<T>
-
stepInstruction
public void stepInstruction()Description copied from interface:PcodeThreadStep 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:
stepInstructionin interfacePcodeThread<T>
-
stepPcodeOp
public void stepPcodeOp()Description copied from interface:PcodeThreadStep 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:
stepPcodeOpin interfacePcodeThread<T>
-
skipPcodeOp
public void skipPcodeOp()Description copied from interface:PcodeThreadSkip 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:
skipPcodeOpin interfacePcodeThread<T>
-
stepPatch
Description copied from interface:PcodeThreadApply a patch to the emulator- Specified by:
stepPatchin 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
-
getContextAfterCommits
-
advanceAfterFinished
protected void advanceAfterFinished()Resolve a finished instruction, advancing the program counter if necessary -
getFrame
Description copied from interface:PcodeThreadGet 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:
getFramein interfacePcodeThread<T>- Returns:
- the current frame
-
getInstruction
Description copied from interface:PcodeThreadGet the current decoded instruction, if applicable- Specified by:
getInstructionin 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
Emulatorframework. 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
Emulatorframework. 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:PcodeThreadExecute 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:
executeInstructionin interfacePcodeThread<T>
-
finishInstruction
public void finishInstruction()Description copied from interface:PcodeThreadFinish 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:
finishInstructionin interfacePcodeThread<T>
-
skipInstruction
public void skipInstruction()Description copied from interface:PcodeThreadDecode, but skip the next instruction- Specified by:
skipInstructionin interfacePcodeThread<T>
-
dropInstruction
public void dropInstruction()Description copied from interface:PcodeThreadIf 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:
dropInstructionin interfacePcodeThread<T>
-
run
public void run()Description copied from interface:PcodeThreadEmulate 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:
runin interfacePcodeThread<T>
-
setSuspended
public void setSuspended(boolean suspended) Description copied from interface:PcodeThreadSet 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:
setSuspendedin interfacePcodeThread<T>- Parameters:
suspended- true to suspend the machine, false to let it run- See Also:
-
isSuspended
public boolean isSuspended()Description copied from interface:PcodeThreadCheck the suspension state of the thread's executor- Specified by:
isSuspendedin interfacePcodeThread<T>- Returns:
- true if suspended
-
getLanguage
Description copied from interface:PcodeThreadGet the thread's Sleigh language (processor model)- Specified by:
getLanguagein interfacePcodeThread<T>- Returns:
- the language
-
getArithmetic
Description copied from interface:PcodeThreadGet the thread's p-code arithmetic- Specified by:
getArithmeticin interfacePcodeThread<T>- Returns:
- the arithmetic
-
getExecutor
Description copied from interface:PcodeThreadGet 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:
getExecutorin interfacePcodeThread<T>- Returns:
- the executor
-
getUseropLibrary
Description copied from interface:PcodeThreadGet the complete userop library for this thread- Specified by:
getUseropLibraryin interfacePcodeThread<T>- Returns:
- the library
-
getState
Description copied from interface:PcodeThreadGet 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:
getStatein 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:PcodeThreadOverride 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:
injectin interfacePcodeThread<T>- Parameters:
address- the address to inject atsource- the Sleigh source to compile and inject
-
clearInject
Description copied from interface:PcodeThreadRemove 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:
clearInjectin interfacePcodeThread<T>- Parameters:
address- the address to clear
-
clearAllInjects
public void clearAllInjects()Description copied from interface:PcodeThreadRemove all per-thread injects from this threadAll machine-level injects are still effective after this call.
- Specified by:
clearAllInjectsin 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
-