| java.lang.Object | |
| ↳ | com.pnfsoftware.jeb.core.units.code.asm.decompiler.AbstractConverter<InsnType extends com.pnfsoftware.jeb.core.units.code.IInstruction> |
A skeleton for code converters. TODO: documentation + examples.
| Fields | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| protected IERoutineContext | ctx | Per-routine data - works because convert() is not re-entrant (same found in X86ConvXxx helper classes). | |||||||||
| protected boolean | doNotGenerateNops | ||||||||||
| protected IEGlobalContext | gCtx | ||||||||||
| protected int | methodConversionCountFailure | ||||||||||
| protected int | methodConversionCountSuccess | ||||||||||
| protected Set<Integer> | parameterRegistersForAllCC | ||||||||||
| protected IProcessor<InsnType extends IInstruction> | proc | ||||||||||
| protected int | regNormalBitsize | ||||||||||
| protected Set<Integer> | spoiledRegistersForAllCC | ||||||||||
| Protected Constructors | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| AbstractConverter(IProcessor<InsnType> proc, int regNormalBitsize) | |||||||||||
| Public Methods | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| IWildcardPrototype |
buildFailsafePrototype(IERoutineContext ctx, IEStatement stm)
Create a simple, failsafe prototype for the given routine.
| ||||||||||
| IERoutineContext |
convert(INativeMethodItem routine)
Convert a routine.
| ||||||||||
| IERoutineContext |
convert(INativeMethodItem routine, boolean delayBuild)
Convert the blocks of the native routine's CFG after the other.
| ||||||||||
| final List<IEStatement> |
convertBlockForTest(BasicBlock<InsnType> b)
Should be accessed externally for testing only.
| ||||||||||
| List<IEGeneric> |
convertParameterExpressions(IERoutineContext ctx, IWildcardPrototype prototype, INativeMethodItem targetRoutine, int addSlotCount)
Given a prototype, determine the list of IR expressions representing the input expressions
(would also contain implicitly read registers).
| ||||||||||
| List<IEGeneric> |
convertReturnExpressions(IERoutineContext ctx, IWildcardPrototype prototype)
Given a prototype, determine the list of IR expressions representing the output expressions
(would also contain spoiled registers, which are implicitly written).
| ||||||||||
| IEGeneric |
convertReturnLocation(IERoutineContext ctx, IWildcardPrototype prototype)
Given a prototype, determine the IR expression representing the return address
location of a call to a method of said prototype.
| ||||||||||
| IEMem |
createStackMemoryAccess(IEGeneric address, int bitsize)
The default implementation assumes a segment-less memory model (The EMem segment is set to
null).
| ||||||||||
| int |
defaultPCConversion(IERoutineContext ctx)
Convert PC-assignment to EJumpFar statements.
| ||||||||||
| Integer |
determineStackPointerDeltaAfterIRCall(IWildcardPrototype prototype, int addSlotCount)
Given a prototype, determine the stack pointer delta (in bytes) after the ECall
executed and returned.
| ||||||||||
| Integer |
determineStackPointerDeltaFromSimulation(SimulationPointInformation simuinfo)
The default implementation returns null.
| ||||||||||
| String |
formatStatistics()
The default implementation formats basic details about the number of converted methods.
| ||||||||||
| int |
getAddressBitsize()
The default implementation returns the size of the program counter.
| ||||||||||
| INativeDecompilerUnit<InsnType> |
getDecompiler()
Reserved.
| ||||||||||
| IEGlobalContext |
getGlobalContext()
Retrieve the global program context.
| ||||||||||
| long |
getNativeRegisterIdFromRegisterVariable(IEVar regVar)
The default implementation throws.
| ||||||||||
| int |
getProcessorMode(IEState state)
Retrieve the current processor mode relative to this EState.
| ||||||||||
| IEPrototypeHandler |
getPrototypeHandler(IERoutineContext ctx)
Create an instance of a prototype handler.
| ||||||||||
| int |
getRegisterBitsize()
The default implementation returns the address bitsize.
| ||||||||||
| IEVar |
getRegisterVariableFromNativeRegisterId(long nativeRegId)
The default implementation throws.
| ||||||||||
| IEVar |
getReturnAddressRegister()
The default implementation considers that there is no specific Return Address Register.
| ||||||||||
| int |
getStackSlotSize()
Get the size of standard slot on the stack, in bytes.
| ||||||||||
| void |
initializeStateRegisters(IEState state, Long optionalNativeProgramCounter)
The default implementation initializes and sets all physical registers declared by this
converter to 0, except for the ones possibly used as arguments that are kept undefined (see
#isPossibleParameterRegisterForProcessorCallingConventions(IEGeneric)).
| ||||||||||
| int |
insertReturns(IERoutineContext _ctx)
This method introduces EReturn statements into the IR.
| ||||||||||
| boolean | isDoNotGenerateNops() | ||||||||||
| boolean |
isPossibleParameterRegisterForProcessorCallingConventions(long nativeRegId)
Check if a native register id corresponds to a register that can possibly be used as a
routine parameter on this processor.
| ||||||||||
| boolean |
isPossibleSpoiledRegistersForProcessorCallingConventions(long nativeRegId)
Check if a native register id corresponds to a physical register that can possibly be spoiled
by a routine call on this processor.
| ||||||||||
| boolean |
resolveCustomCalls(INativeCodeUnit<?> pbcu, IERoutineContext ctx)
Implementations should be aggressive and fast: calls to this method should always be enclosed
in a try-catch.
| ||||||||||
| void |
setDecompiler(INativeDecompilerUnit<InsnType> decompiler)
Reserved.
| ||||||||||
| void | setDoNotGenerateNops(boolean doNotGenerateNops) | ||||||||||
| Protected Methods | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| abstract void |
convertBlock(BasicBlock<InsnType> b, List<IEStatement> interlist)
Convert a block.
| ||||||||||
| boolean |
insertOptionalEntryPointTrampoline(IERoutineContext ctx, List<IEStatement> IRStatementList)
For native routines that have their entry point in-the-middle (ie, not at their lowest
address), insert a synthetic
IEJump as the first instruction of the converted method. | ||||||||||
| boolean |
isPCRightValueCompatibleReturnValue(BasicBlock<IEStatement> b, IEGeneric PCRightVal, IEGeneric expectedReturnAddress)
Can be overridden by implementors when complex return expression matching is needed.
| ||||||||||
| void |
postBlockConversion(CFG<InsnType> cfg, BasicBlock<InsnType> b, List<IEStatement> interlist, int cnt)
This method is called after
convertBlock(BasicBlock, List) is called. | ||||||||||
| void |
postRoutineConversion(INativeMethodItem routine, IERoutineContext ctx)
Executed by
convert after converting the blocks. | ||||||||||
| BasicBlock<InsnType> |
preBlockConversion(CFG<InsnType> cfg, BasicBlock<InsnType> b, List<IEStatement> interlist)
This method is called before
convertBlock(BasicBlock, List) is called. | ||||||||||
| void |
preRoutineConversion(INativeMethodItem routine, IERoutineContext ctx)
Executed by
convert before converting the
blocks. | ||||||||||
| void |
setCurrentContext(IERoutineContext ctx)
setup the helper converter classes
| ||||||||||
|
[Expand]
Inherited Methods | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
From class
java.lang.Object
| |||||||||||
From interface
com.pnfsoftware.jeb.core.units.code.asm.decompiler.IEConverter
| |||||||||||
Per-routine data - works because convert() is not re-entrant (same found in X86ConvXxx helper
classes).
Should be set before converting a routine, and reset to null after it's done.
Create a simple, failsafe prototype for the given routine.
| ctx | routine for which a failsafe prototype is to be generated |
|---|---|
| stm | optional statement calling into the routine |
Convert a routine. Convenience method for convert(routine, false).
Convert the blocks of the native routine's CFG after the other. The blocks' edges are not considered.
| routine | the routine to be converted; must have a data definition |
|---|---|
| delayBuild | if true, the IR validation and CFG building will not take place (in that
case, getCfg() would return false) |
Should be accessed externally for testing only.
Given a prototype, determine the list of IR expressions representing the input expressions (would also contain implicitly read registers).
Used by ECall.
| prototype | mandatory prototype |
|---|---|
| targetRoutine | (optional) may be null; if provided, can be used with addSlotCount (if non 0) |
| addSlotCount | (optional) may be non-zero for a var-arg routine; the implementation should do its best to determine what are the additional (not specified in the prototype) parameters |
Given a prototype, determine the list of IR expressions representing the output expressions (would also contain spoiled registers, which are implicitly written).
Used by ECall.
Given a prototype, determine the IR expression representing the return address location of a call to a method of said prototype.
Used by ECall.
The default implementation assumes a segment-less memory model (The EMem segment is set to null).
Convert PC-assignment to EJumpFar statements. This method is a fail-safe converter for PC-assignments, and should be called as late as possible in the IR conversion phases.
Given a prototype, determine the stack pointer delta (in bytes) after the ECall
executed and returned.
Careful: "IR-Call" and the "native-call" may not have the same structure; it depends on how
the conversion of "native-call" is implemented, and therefore is converter-dependent. The SP
delta returned by this method is the one after an execution over ECall.
Used by ECall.
The default implementation returns null.
| simuinfo | state of IR execution; PC is assumed to be on the target routine entry-point |
|---|
The default implementation formats basic details about the number of converted methods.
The default implementation returns the size of the program counter.
Retrieve the global program context. There is a single global context per decompiler, common to all ERoutineContext routine contexts.
The default implementation throws.
Retrieve the current processor mode relative to this EState. A bit can be set in the EState to indicate the current mode (for example ARM Thumb Bit).
| state | current state |
|---|
Create an instance of a prototype handler.
The default implementation returns the address bitsize.
The default implementation throws.
The default implementation considers that there is no specific Return Address Register. Override if one exists.
Get the size of standard slot on the stack, in bytes.
The default implementation initializes and sets all physical registers declared by this converter to 0, except for the ones possibly used as arguments that are kept undefined (see #isPossibleParameterRegisterForProcessorCallingConventions(IEGeneric)).
| state | input state to be initialized |
|---|---|
| optionalNativeProgramCounter | optional current native PC |
This method introduces EReturn statements into the IR. Must be performed only after prototype discovery is completed.
Data chains: not used, may be invalidated; in the latter case, this method is responsible for recalculating them.
| _ctx | the routine context |
|---|
Check if a native register id corresponds to a register that can possibly be used as a routine parameter on this processor.
To do so, the given id is compared against all input registers for all known calling conventions for the current processor. In particular, this method does not rely on the routine prototype and calling convention being defined, and can therefore be used early on during decompilation.
Check if a native register id corresponds to a physical register that can possibly be spoiled by a routine call on this processor.
To do so, the given id is compared against all spoiled registers for all known calling conventions for the current processor. In particular, this method does not rely on the routine prototype and calling convention being defined, and can therefore be used early on during decompilation.
Implementations should be aggressive and fast: calls to this method should always be enclosed in a try-catch.
TODO: MOVE to the CBDU
Convert a block.
| b | block to be converted |
|---|---|
| interlist | output list of converted IR statements |
For native routines that have their entry point in-the-middle (ie, not at their lowest
address), insert a synthetic IEJump as the first instruction of the converted method.
By using this trick, we ensure that native routines that have their entry-point in the middle of their code can be converted to IR routines with an entry-point always set to offset 0 (the beginning of the IR code). The reason is that this helps with graph manipulation passes that come later on, in the AST phases.
| ctx | translation context |
|---|---|
| IRStatementList | global list of converted IR-statements, should be empty when this method is called |
Can be overridden by implementors when complex return expression matching is needed.
| b | BasicBlock containing the PC assign instruction |
|---|---|
| PCRightVal | right Value of the PC assign instruction |
| expectedReturnAddress | Expected IEVar as per current Calling Convention |
This method is called after convertBlock(BasicBlock, List) is called. The default
implementation makes sure the block end is valid by inserting an IEJumpFar if it does
not appear to be properly terminated.
| cfg | the native CFG of the method being converted |
|---|---|
| b | the native basic block that was just converted |
| interlist | the current list of IR statements for the routine (not only for the provided block!); the last IR statements in that list are those of the routine that was just converted |
| cnt | the number of IR statements that correspond to the conversion of the provided native block |
Executed by convert after converting the blocks.
The default implementation does nothing.
This method is called before convertBlock(BasicBlock, List) is called. It can be
overridden; sub-classes do not need to call the default implementation. The default returns
the provided input block.
| cfg | the CFG |
|---|---|
| b | block about to be converted |
Executed by convert before converting the
blocks. The default implementation does nothing.