Class JitPcodeThread
- All Implemented Interfaces:
PcodeThread<byte[]>
This class implements the actual JIT-accelerated execution loop. In contrast to the normal
per-instruction Fetch-Execute-Store loop inherited from DefaultPcodeThread
, this thread's
run()
method implements a per-passage Fetch-Decode-Translate-Execute loop.
Fetch
The Fetch step involves checking the code cache for an existing translation at the thread's current counter and decode context. Cache entries are keyed by passage entry point, that is an address (and context reg value, if applicable) within a passage where execution is permitted to enter. This typically consists of the passage's seed as well as each branch target in the same passage. If one is found, we skip the Decode and Translate steps, and proceed directly to Execute.
Decode
The Decode step involves decoding and selecting several instructions into a passage. A
passage may comprise of several instructions connected by control flow. Often it is a few long
strides of instructions connected by a few branches. The decoder will avoid selecting
instructions that are already included in an existing translated passage. The reason for this
complexity is that JVM bytecode cannot be rewritten or patched once loaded. For more details, see
JitPassageDecoder
.
Translate
The Translate step involves translating the selected passage of instructions. The result of this
translation implements JitCompiledPassage
. For details of this translation process, see
JitCompiler
. The compiled passage provides a list of its entry points. Each is added to
the emulator's code cache. Among those should be the seed required by this iteration of the
execution loop, and so that entry point is chosen.
Execute
The chosen entry point is then executed. This step is as simple as invoking the
JitCompiledPassage.EntryPoint.run()
method. This, in turn, invokes JitCompiledPassage.run(int)
,
providing the entry point's index as an argument. The index identifies to the translated passage
the desired address of entry, and so it jumps directly to the corresponding translation. That
translation performs all the equivalent operations of the selected instructions, adhering to any
control flow within. When control flow exits the passage, the method returns, and the loop
repeats.
-
Nested Class Summary
Nested classes/interfaces inherited from class ghidra.pcode.emu.ModifiedPcodeThread
ModifiedPcodeThread.GlueEmulate
Nested classes/interfaces inherited from class ghidra.pcode.emu.DefaultPcodeThread
DefaultPcodeThread.PcodeEmulationLibrary<T>, DefaultPcodeThread.PcodeThreadExecutor<T>
-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected final Map
<JitPassage.AddrCtx, JitCompiledPassage.EntryPoint> This thread's cache of translations instantiated for this thread.protected final JitPassageDecoder
This thread's passage decoder, which is based on itsinstruction decoder
.Fields inherited from class ghidra.pcode.emu.ModifiedPcodeThread
emulate, modifier
Fields inherited from class ghidra.pcode.emu.DefaultPcodeThread
arithmetic, contextreg, decoder, defaultContext, executor, frame, injects, instruction, language, library, pc, state
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoid
count
(int instructions, int trailingOps) This is called before each basic block is executed.protected JitPassageDecoder
Create the passage decoderprotected ThreadPcodeExecutorState
<byte[]> createThreadState
(PcodeExecutorState<byte[]> sharedState, PcodeExecutorState<byte[]> localState) A factory method for the thread's (multiplexed) stateAn accessor so the passage decoder can retrieve its thread's instruction decoder.An accessor so the passage decoder can query the language's default program context.getEntry
(JitPassage.AddrCtx pcCtx) Get the translated and instantiated entry point for the given address and contextreg value.Check for a p-code injection (override) at the given addressGet the machine within which this thread executesgetState()
Get the thread's memory and register stateboolean
hasEntry
(JitPassage.AddrCtx pcCtx) Check if the emulator has an entry prototype for the given address and contextreg value.void
Override the p-code at the given address with the given Sleigh source for only this threadvoid
run()
Emulate indefinitelyMethods inherited from class ghidra.pcode.emu.ModifiedPcodeThread
createModifier, onMissingUseropDef, overrideCounter, postExecuteInstruction
Methods inherited from class ghidra.pcode.emu.DefaultPcodeThread
advanceAfterFinished, assertCompletedInstruction, assertMidInstruction, assignContext, beginInstructionOrInject, branchToAddress, checkLoad, checkStore, clearAllInjects, clearInject, createExecutor, createInstructionDecoder, createUseropLibrary, doPluggableInitialization, dropInstruction, executeInstruction, finishInstruction, getArithmetic, getContext, getContextAfterCommits, getContextAfterCommits, getCounter, getExecutor, getFrame, getInstruction, getLanguage, getName, getUseropLibrary, isSuspended, overrideContext, overrideContextWithDefault, preExecuteInstruction, reInitialize, setCounter, setSuspended, skipInstruction, skipPcodeOp, stepInstruction, stepPatch, stepPcodeOp, stepped, swi, writeCounter
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
-
passageDecoder
This thread's passage decoder, which is based on itsinstruction decoder
. -
codeCache
This thread's cache of translations instantiated for this thread.As an optimization, the translator generates classes which pre-fetch portions of the thread's state. Thus, the class must be instantiated for each particular thread needing to execute it.
TODO: Invalidation of entries. There are several reasons an entry may need to be invalidated: Expiration, eviction, or perhaps because the
JitCompiledPassage.EntryPointPrototype
(from the emulator) was invalidated.
-
-
Constructor Details
-
JitPcodeThread
Create a threadThis should only be called by the emulator and its test suites.
- Parameters:
name
- the name of the threadmachine
- the machine creating the thread
-
-
Method Details
-
createThreadState
protected ThreadPcodeExecutorState<byte[]> createThreadState(PcodeExecutorState<byte[]> sharedState, PcodeExecutorState<byte[]> localState) Description copied from class:DefaultPcodeThread
A factory method for the thread's (multiplexed) state- Overrides:
createThreadState
in classDefaultPcodeThread<byte[]>
- Parameters:
sharedState
- the shared part of the statelocalState
- the thread-local part of the state- Returns:
- the complete state
-
createPassageDecoder
Create the passage decoderThis is an extension point in case the decoder needs to be replaced with a further extension.
- Returns:
- the new passage decoder
-
getMachine
Description copied from interface:PcodeThread
Get the machine within which this thread executes- Specified by:
getMachine
in interfacePcodeThread<byte[]>
- Overrides:
getMachine
in classDefaultPcodeThread<byte[]>
- Returns:
- the containing machine
-
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<byte[]>
- Overrides:
getState
in classDefaultPcodeThread<byte[]>
- Returns:
- the state
-
getInject
Description copied from class:DefaultPcodeThread
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.
- Overrides:
getInject
in classDefaultPcodeThread<byte[]>
- Parameters:
address
- the address, usually the program counter- Returns:
- the injected program, most likely
null
-
getDecoder
An accessor so the passage decoder can retrieve its thread's instruction decoder.- Returns:
- the decoder
-
getDefaultContext
An accessor so the passage decoder can query the language's default program context.- Returns:
- the context
-
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<byte[]>
- Overrides:
inject
in classDefaultPcodeThread<byte[]>
- Parameters:
address
- the address to inject atsource
- the Sleigh source to compile and inject
-
hasEntry
Check if the emulator has an entry prototype for the given address and contextreg value.This simply passes through to the emulator. It does not matter whether or not this thread has instantiated the prototype or not. If any thread has caused the emulator to translate the given entry, this will return true.
- Parameters:
pcCtx
- the address and contextreg to check- Returns:
- true if the emulator has a translation which can be entered at the given pcCtx.
- See Also:
-
getEntry
Get the translated and instantiated entry point for the given address and contextreg value.An entry point is an instance of a class representing a translated passage and an index identifying the point at which to enter the passage. In essence, it is an instance of an entry prototype for this thread.
This will first check the cache for an existing instance. Then, it will delegate to the emulator. The emulator will check its cache for an existing translation. If one is found, we simply take it and instantiate it for this thread. Otherwise, the emulator translates a new passage at the given seed, and we instantiate it for this thread.
- Parameters:
pcCtx
- the counter and decoder context- Returns:
- the entry point
- See Also:
-
run
public 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.
We override only this method to accelerate execution using JIT translation. Implementing single stepping via JIT doesn't make much sense from an efficiency standpoint. However, this thread still supports stepping via interpretation (as inherited). Our implementation permits mixing the two execution paradigms; however, using JIT after a few single steps will incur some waste as the JIT translates an otherwise uncommon entry point. Depending on circumstances and the order of operations, the effect of this on overall efficiency may vary because of caching.
- Specified by:
run
in interfacePcodeThread<byte[]>
- Overrides:
run
in classDefaultPcodeThread<byte[]>
-
count
public void count(int instructions, int trailingOps) This is called before each basic block is executed.This gives the thread an opportunity to track and control execution, if desired. It provides the number of instructions and additional p-code ops about to be completed. If the counts exceed a desired schedule, or if the thread is suspended, this method may throw an exception to interrupt execution. This can be toggled in the emulator's configuration.
- Parameters:
instructions
- the number of instruction about to be completedtrailingOps
- the number of ops of a final partial instruction about to be completed. If the block does not complete any instruction, this is the number of ops continuing in the current (partial) instruction.- See Also:
-