Class AbstractPcodeMachine<T>
- Type Parameters:
T
- the type of objects in the machine's state
- All Implemented Interfaces:
PcodeMachine<T>
- Direct Known Subclasses:
AuxPcodeEmulator
,PcodeEmulator
PcodeMachine
suitable as a base for most implementations
A note regarding terminology: A p-code "machine" refers to any p-code-based machine simulator,
whether or not it operates on abstract or concrete values. The term "emulator" is reserved for
machines whose values always include a concrete piece. That piece doesn't necessarily have to be
a (derivative of) BytesPcodeExecutorStatePiece
, but it usually is. To be called an
"emulator" implies that PcodeArithmetic.toConcrete(Object, Purpose)
never throws
ConcretionError
for any value in its state.
For a complete example of a p-code emulator, see PcodeEmulator
. For an alternative
implementation incorporating an abstract piece, see the Taint Analyzer.
-
Nested Class Summary
Nested classes/interfaces inherited from interface ghidra.pcode.emu.PcodeMachine
PcodeMachine.AccessKind, PcodeMachine.SwiMode
-
Field Summary
Modifier and TypeFieldDescriptionprotected final SparseAddressRangeMap
<PcodeMachine.AccessKind> protected final PcodeArithmetic
<T> protected final Map
<Address, PcodeProgram> protected final SleighLanguage
protected final PcodeUseropLibrary
<T> protected final PcodeUseropLibrary
<T> protected boolean
protected PcodeMachine.SwiMode
protected final Map
<String, PcodeThread<T>> protected final Collection
<PcodeThread<T>> -
Constructor Summary
ConstructorDescriptionAbstractPcodeMachine
(Language language) Construct a p-code machine with the given language and arithmetic -
Method Summary
Modifier and TypeMethodDescriptionvoid
addAccessBreakpoint
(AddressRange range, PcodeMachine.AccessKind kind) Add an access breakpoint over the given rangevoid
addBreakpoint
(Address address, String sleighCondition) Add a conditional execution breakpoint at the given addressprotected static SleighLanguage
assertSleigh
(Language language) Check and cast the language to Sleighprotected 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 access breakpoints from this machinevoid
Remove all injects from this machinevoid
clearInject
(Address address) Remove the inject, if present, at the given addresscompileSleigh
(String sourceName, String source) Compile the given Sleigh code for execution by a thread of this machineprotected abstract PcodeArithmetic
<T> A factory method to create the arithmetic used by this machineprotected abstract PcodeExecutorState
<T> createLocalState
(PcodeThread<T> thread) A factory method to create the (register) state local to the given threadprotected abstract PcodeExecutorState
<T> A factory method to create the (memory) state shared by all threads in this machineprotected PcodeThread
<T> createThread
(String name) A factory method to create a new thread in this machineprotected PcodeUseropLibrary
<T> A factory method to create a stub library for compiling thread-local Sleigh sourceprotected abstract PcodeUseropLibrary
<T> A factory method to create the userop library shared by all threads in this machineprotected void
Execute the initializer upon this machine, if applicableCollection
<? extends PcodeThread<T>> Collect all threads present in the machineGet the arithmetic applied by the machineprotected PcodeProgram
Check for a p-code injection (override) at the given addressGet the machine's Sleigh language (processor model)protected static PcodeStateInitializer
getPluggableInitializer
(Language language) Search the classpath for an applicable state initializerGet the machine's shared (memory) stateGet the current software interrupt modeGet a userop library which at least declares all userops available in each thread userop library.Get the thread, if present, with the given nameGet the userop library common to all threads in the machine.void
Override the p-code at the given address with the given Sleigh sourceboolean
Check the suspension state of the machineCreate a new thread with a default name in this machineCreate a new thread with the given name in this machinevoid
Change the efficacy of p-code breakpointsvoid
setSuspended
(boolean suspended) Set the suspension state of the machineprotected 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 active
-
Field Details
-
language
-
arithmetic
-
library
-
stubLibrary
-
swiMode
-
threads
-
threadsView
-
suspended
protected volatile boolean suspended -
injects
-
accessBreakpoints
-
-
Constructor Details
-
AbstractPcodeMachine
Construct a p-code machine with the given language and arithmetic- Parameters:
language
- the processor language to be emulated
-
-
Method Details
-
assertSleigh
Check and cast the language to SleighSleigh is currently the only realization, but this should give a decent error should that ever change.
- Parameters:
language
- the language- Returns:
- the same language, cast to Sleigh
-
createArithmetic
A factory method to create the arithmetic used by this machine- Returns:
- the arithmetic
-
createUseropLibrary
A factory method to create the userop library shared by all threads in this machine- Returns:
- the library
-
getLanguage
Description copied from interface:PcodeMachine
Get the machine's Sleigh language (processor model)- Specified by:
getLanguage
in interfacePcodeMachine<T>
- Returns:
- the language
-
getArithmetic
Description copied from interface:PcodeMachine
Get the arithmetic applied by the machine- Specified by:
getArithmetic
in interfacePcodeMachine<T>
- Returns:
- the arithmetic
-
getUseropLibrary
Description copied from interface:PcodeMachine
Get the userop library common to all threads in the machine.Note that threads may have larger libraries, but each contains all the userops in this library.
- Specified by:
getUseropLibrary
in interfacePcodeMachine<T>
- Returns:
- the userop library
-
getStubUseropLibrary
Description copied from interface:PcodeMachine
Get a userop library which at least declares all userops available in each thread userop library.Thread userop libraries may have more userops than are defined in the machine's userop library. However, to compile Sleigh programs linked to thread libraries, the thread's userops must be known to the compiler. The stub library will name all userops common among the threads, even if their definitions vary. WARNING: The stub library is not required to provide implementations of the userops. Often they will throw exceptions, so do not attempt to use the returned library in an executor.
- Specified by:
getStubUseropLibrary
in interfacePcodeMachine<T>
- Returns:
- the stub library
-
createLocalState
A factory method to create the (register) state local to the given thread- Parameters:
thread
- the thread- Returns:
- the thread-local state
-
createThreadStubLibrary
A factory method to create a stub library for compiling thread-local Sleigh sourceBecause threads may introduce p-code userops using libraries unique to that thread, it becomes necessary to at least export stub symbols, so that p-code programs can be compiled from Sleigh source before the thread has necessarily been created. A side effect of this strategy is that all threads, though they may have independent libraries, must export identically-named symbols.
- Returns:
- the stub library for all threads
-
setSoftwareInterruptMode
Description copied from interface:PcodeMachine
Change the efficacy of p-code breakpointsThis is used to prevent breakpoints from interrupting at inappropriate times, e.g., upon continuing from a breakpoint.
- Specified by:
setSoftwareInterruptMode
in interfacePcodeMachine<T>
- Parameters:
mode
- the new mode
-
getSoftwareInterruptMode
Description copied from interface:PcodeMachine
Get the current software interrupt mode- Specified by:
getSoftwareInterruptMode
in interfacePcodeMachine<T>
- Returns:
- the mode
-
createThread
A factory method to create a new thread in this machine- Parameters:
name
- the name of the new thread- Returns:
- the new thread
- See Also:
-
getPluggableInitializer
Search the classpath for an applicable state initializerIf found, the initializer is executed immediately upon creating this machine's shared state and upon creating each thread.
TODO: This isn't really being used. At one point in development it was used to initialize x86's FS_OFFSET and GS_OFFSET registers. Those only exist in p-code, not the real processor, and replace what might have been
segment(FS)
. There seems more utility in detecting when those registers are uninitialized, requiring the user to initialize them, than it is to silently initialize them to 0. Unless we find utility in this, it will likely be removed in the near future.- Parameters:
language
- the language requiring pluggable initialization- Returns:
- the initializer
- See Also:
-
doPluggableInitialization
protected void doPluggableInitialization()Execute the initializer upon this machine, if applicable- See Also:
-
newThread
Description copied from interface:PcodeMachine
Create a new thread with a default name in this machine- Specified by:
newThread
in interfacePcodeMachine<T>
- Returns:
- the new thread
-
newThread
Description copied from interface:PcodeMachine
Create a new thread with the given name in this machine- Specified by:
newThread
in interfacePcodeMachine<T>
- Parameters:
name
- the name- Returns:
- the new thread
-
getThread
Description copied from interface:PcodeMachine
Get the thread, if present, with the given name- Specified by:
getThread
in interfacePcodeMachine<T>
- Parameters:
name
- the namecreateIfAbsent
- create a new thread if the thread does not already exist- Returns:
- the thread, or
null
if absent and not created
-
getAllThreads
Description copied from interface:PcodeMachine
Collect all threads present in the machine- Specified by:
getAllThreads
in interfacePcodeMachine<T>
- Returns:
- the collection of threads
-
setSuspended
public void setSuspended(boolean suspended) Description copied from interface:PcodeMachine
Set the suspension state of the machineThis does not simply suspend all threads, but sets a machine-wide flag. A thread is suspended if either the thread's flag is set, or the machine's flag is set.
- Specified by:
setSuspended
in interfacePcodeMachine<T>
- Parameters:
suspended
- true to suspend the machine, false to let it run- See Also:
-
isSuspended
public boolean isSuspended()Description copied from interface:PcodeMachine
Check the suspension state of the machine- Specified by:
isSuspended
in interfacePcodeMachine<T>
- Returns:
- true if suspended
- See Also:
-
getInject
Check for a p-code injection (override) at the given address- Parameters:
address
- the address, usually the program counter- Returns:
- the injected program, most likely
null
-
compileSleigh
Description copied from interface:PcodeMachine
Compile the given Sleigh code for execution by a thread of this machineThis links in the userop library given at construction time and those defining the emulation userops, e.g.,
emu_swi
.- Specified by:
compileSleigh
in interfacePcodeMachine<T>
- Parameters:
sourceName
- a user-defined source name for the resulting "program"source
- the Sleigh source- Returns:
- the compiled program
-
inject
Description copied from interface:PcodeMachine
Override the p-code at the given address with the given Sleigh sourceThis will attempt to compile the given source against this machine's userop library and then inject it at the given address. The resulting p-code replaces that which would be executed by decoding the instruction at the given address. The means the machine will not decode, nor advance its counter, unless the Sleigh causes it. In most cases, the Sleigh will call
DefaultPcodeThread.PcodeEmulationLibrary.emu_exec_decoded()
to cause the machine to decode and execute the overridden instruction.Each address can have at most a single inject. If there is already one present, it is replaced and the old inject completely forgotten. The injector does not support chaining or double-wrapping, etc.
No synchronization is provided on the internal injection storage. Clients should ensure the machine is not executing when injecting p-code. Additionally, the client must ensure only one thread is injecting p-code to the machine at a time.
- Specified by:
inject
in interfacePcodeMachine<T>
- Parameters:
address
- the address to inject atsource
- the Sleigh source to compile and inject
-
clearInject
Description copied from interface:PcodeMachine
Remove the inject, if present, at the given address- Specified by:
clearInject
in interfacePcodeMachine<T>
- Parameters:
address
- the address to clear
-
clearAllInjects
public void clearAllInjects()Description copied from interface:PcodeMachine
Remove all injects from this machineThis will clear execution breakpoints, but not access breakpoints. See
PcodeMachine.clearAccessBreakpoints()
.- Specified by:
clearAllInjects
in interfacePcodeMachine<T>
-
addBreakpoint
Description copied from interface:PcodeMachine
Add a conditional execution breakpoint at the given addressBreakpoints are implemented at the p-code level using an inject, without modification to the emulated image. As such, it cannot coexist with another inject. A client needing to break during an inject must use
DefaultPcodeThread.PcodeEmulationLibrary.emu_swi()
in the injected Sleigh.No synchronization is provided on the internal breakpoint storage. Clients should ensure the machine is not executing when adding breakpoints. Additionally, the client must ensure only one thread is adding breakpoints to the machine at a time.
- Specified by:
addBreakpoint
in interfacePcodeMachine<T>
- Parameters:
address
- the address at which to breaksleighCondition
- a Sleigh expression which controls the breakpoint
-
addAccessBreakpoint
Description copied from interface:PcodeMachine
Add an access breakpoint over the given rangeAccess breakpoints are implemented out of band, without modification to the emulated image. The breakpoints are only effective for p-code
PcodeOp.LOAD
andPcodeOp.STORE
operations with concrete offsets. Thus, an operation that refers directly to a memory address, e.g., a memory-mapped register, will not be trapped. Similarly, access breakpoints on registers or unique variables will not work. Access to an abstract offset that cannot be made concrete, i.e., viaPcodeArithmetic.toConcrete(Object, Purpose)
cannot be trapped. To interrupt on direct and/or abstract accesses, consider wrapping the relevant state and/or overridingPcodeExecutorStatePiece.getVar(Varnode, Reason)
and related. For accesses to abstract offsets, consider overridingcheckLoad(AddressSpace, Object, int)
and/orcheckStore(AddressSpace, Object, int)
instead.A breakpoint's range cannot cross more than one page boundary. Pages are 4096 bytes each. This allows implementations to optimize checking for breakpoints. If a breakpoint does not follow this rule, the behavior is undefined. Breakpoints may overlap, but currently no indication is given as to which breakpoint interrupted emulation.
No synchronization is provided on the internal breakpoint storage. Clients should ensure the machine is not executing when adding breakpoints. Additionally, the client must ensure only one thread is adding breakpoints to the machine at a time.
- Specified by:
addAccessBreakpoint
in interfacePcodeMachine<T>
- Parameters:
range
- the address range to trapkind
- the kind of access to trap
-
clearAccessBreakpoints
public void clearAccessBreakpoints()Description copied from interface:PcodeMachine
Remove all access breakpoints from this machine- Specified by:
clearAccessBreakpoints
in interfacePcodeMachine<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
-