Interface IDInstruction
- All Superinterfaces:
IDElement,IDExpression,IInstruction,IInstructionOperand,ILocatedInstruction
dexdec IR instruction object. Each intermediate representation instruction has:- an opcode: refer to
DOpcodeType- zero, one, or two operands, of type
IDElement- an offset (in the IR)
- a size
IR CFGs consist of basic blocks made of IR instructions. An IDMethodContext references it
IR CFG. IR instructions can also be created via the createXxx methods of the context
object.
When creating IR instructions, the default size is set to 1. The offset is not set (-1), and needs to be set manually. The size of an IR instruction can be set to any strictly positive value. In a CFG, it is important that all instructions be contiguous (i.e. there is no gap): if an instruction has offset O and size S, the next instruction must be at offset O+S.
-
Field Summary
FieldsFields inherited from interface com.pnfsoftware.jeb.core.units.code.android.ir.IDElement
DEFAULT_COMPARE_WITH_FULL_EQUALITY -
Method Summary
Modifier and TypeMethodDescriptionvoidadjustSize(int delta) Adjust this instruction's IR size.copy(DCopyOptions opt) Copy this element.voidcopyBaseFields(IDInstruction sourceInsn) Copy all base fields, that is all fields but the opcode and operands of the source instruction to this instruction.intcountUsedVariable(IDVar var) Count the number of times the provided variable is used (read) by this instruction.Deep copy of this instruction.duplicateForReplacement(IDInstruction replacedInsn) Duplicate this instruction with the intent to replace the source instruction.duplicateWithOffsetAndSize(long offset, int size) Convenience method: evaluate the IR instruction using the provided set a variable values.intRetrieve the IR method context to which this instruction belongs.Get the identifier defined (written) by this method, if there is one.Get the condition predicate (if the instruction is a JCOND).longIR offsets are 32-bit integers; they can be safely cast to int.longRetrieve the end offset (exclusive) of this instructionGet this instruction opcode.Get the first operand.Get the second operand.Get the variables used (read) by this instruction.booleanhasUseSideEffects(boolean includeCanThrow) Determine whether the used components of the statement may have side-effects.booleanisAssign()default booleandefault booleanisAssignFromVar(int wantedVarId) default booleandefault booleanisAssignFromVarToVar(int wantedSrcVarId, int wantedDstVarId) default booleandefault booleanisAssignToVar(int wantedVarId) booleanisInvoke()booleanisJcond()booleanbooleanisJcondTo(int wantedTarget) booleanisJump()booleanbooleanisJumpOrJcondTo(int wantedTarget) booleanisJumpTo(int wantedTarget) booleanbooleanbooleanisNop()booleanisOpcode(DOpcodeType... candidateOpcodes) Determine if this instruction's opcode is any of the provided candidates.booleanisReturn()booleanbooleanbooleanisSwitch()booleanbooleanbooleanisThrow()voidmorph(DOpcodeType opcode, IDElement opnd1, IDElement opnd2) This dangerous method allows changing an IR instruction into a different one, while keeping metadata (e.g.intreplaceDefinedVariable(IDVar var, IDExpression repl) Replace the variable defined by this statement (if there is any).intreplaceUsedVariable(IDVar var, IDExpression repl) Deep replace all matching used variables of this instruction.voidintsetBranchTarget(int offset) Update the branch target for unconditional and conditional jumps only.Update the instruction context.voidsetOffset(long offset) Set this instruction's IR offset.voidsetOpcode(DOpcodeType opcode) Change the instruction opcode.voidsetOperand1(IDElement opnd) Change the instruction first operand.voidsetOperand2(IDElement opnd) Change the instruction second operand.voidsetSize(int size) Set this instruction's IR size.setSwitchData(IDSwitchData swdata) voidTransform a conditional jump instruction to a conditional-predicate assignment.voidTransform a conditional jump instruction to a jump.booleanTransform a single-case switch into a conditional jump.voidtransformToJump(int offset) Transform any instruction to a jump, and update the jump target.voidtransformToJump(IDTarget target) Transform any instruction to a jump, and update the jump target.voidTransform any instruction to a NOP.intupdateTargets(Map<Integer, Integer> oldToNewOffsets) Update the targets of a branching instruction.intupdateTargets(Map<Integer, Integer> oldToNewOffsets, boolean failOnMissedEntry) Update the targets of a branching instruction.voidverify()Verify this instruction.booleanvisitInstruction(IDVisitor visitor) Visit this instruction and its constituents.booleanvisitInstruction(IDVisitor visitor, boolean skipAssignmentDestination) Visit this instruction and its constituents.booleanvisitInstructionPostOrder(IDVisitor visitor, boolean skipAssignmentDestination) Visit this instruction and its constituents.booleanvisitInstructionPreOrder(IDVisitor visitor, boolean skipAssignmentDestination) Visit this instruction and its constituents.withOffset(long offset) Update the instruction offset.withSize(int size) Update the instruction size.Methods inherited from interface com.pnfsoftware.jeb.core.units.code.android.ir.IDElement
equalsEx, format, toString, toStringMethods inherited from interface com.pnfsoftware.jeb.core.units.code.android.ir.IDExpression
asArrayElt, asCallInfo, asImm, asInstanceField, asInstruction, asNewArrayInfo, asNewInfo, asOperation, asReferenceType, asStaticField, asVar, canThrow, checkType, collectAllPhysicalMethodIndices, collectAllPhysicalOffsets, collectSubExpressions, collectVarIds, countVariable, evaluate, evaluate, evaluate, find, findByType, findByType, findParent, findParent, generateAST, getCustomCanThrow, getData, getOrigin, getPhysicalMethodIndex, getPhysicalOffset, getSubExpressions, getType, getVarIds, hasSideEffects, isArrayElt, isCallInfo, isCallInfo, isCastOperation, isCastOperation, isConstantImm, isConstantImm, isImm, isInstanceField, isInstruction, isNewArrayInfo, isNewInfo, isOperation, isOperation, isOperation, isOperation, isOperation, isOperation, isOperation, isReferenceType, isStaticField, isStringImm, isVar, isVar, removeData, replaceSubExpression, replaceVariable, setCustomCanThrow, setData, setOrigin, setPhysicalMethodIndex, setPhysicalOffset, setType, setType, setType, spawn, transferMetadataFrom, updateAllPhysicalMethodIndices, updateAllPhysicalOffsets, updateTypes, visitDepthPost, visitDepthPost, visitDepthPost, visitDepthPre, visitDepthPre, visitDepthPreMethods inherited from interface com.pnfsoftware.jeb.core.units.code.IInstruction
canThrow, collectIndirectCallReferences, format, getACS, getBreakingFlow, getCode, getCountOfOperands, getDefUse, getDefUse, getDefUseInfo, getInstructionFlags, getMnemonic, getOperand, getOperands, getPrefix, getPrimaryBranchAddress, getProcessorMode, getRoutineCall, getSizeMethods inherited from interface com.pnfsoftware.jeb.core.units.code.IInstructionOperand
formatMethods inherited from interface com.pnfsoftware.jeb.core.units.code.ILocatedInstruction
collectIndirectCallReferences, getBreakingFlow, getPrimaryBranchAddress, getRoutineCall
-
Field Details
-
Method Details
-
duplicate
IDInstruction duplicate()Deep copy of this instruction.- Specified by:
duplicatein interfaceIDElement- Specified by:
duplicatein interfaceIDExpression- Returns:
- a deep copy of this element; the type of the duplicated element should be the same as this element's type
-
copy
Description copied from interface:IDElementCopy this element. This operation can be seen as a custom duplication; the resulting element may not be of the same type as this element.- Specified by:
copyin interfaceIDElement- Specified by:
copyin interfaceIDExpression- Parameters:
opt- optional; if one is provided,DCopyOptions.onDup(IDExpression)will be tried first to create a copy- Returns:
- the copied element
-
duplicateForReplacement
Duplicate this instruction with the intent to replace the source instruction. The offset and size of the source instruction are copied over to the newly created instruction.- Returns:
-
duplicateWithOffsetAndSize
- Parameters:
offset-size-- Returns:
-
copyBaseFields
Copy all base fields, that is all fields but the opcode and operands of the source instruction to this instruction.- Parameters:
sourceInsn-
-
getContext
IDMethodContext getContext()Retrieve the IR method context to which this instruction belongs. The method context holds all information regarding a current method decompilation. It is also a factory to create moreIDInstructionobjects.- Returns:
-
setContext
Update the instruction context. It is important to update the context when transferring the instructions from a CFG (from context A) to another CFG (of contextB).- Parameters:
ctx- new context- Returns:
- the previous context
-
getOffset
long getOffset()IR offsets are 32-bit integers; they can be safely cast to int.- Specified by:
getOffsetin interfaceILocatedInstruction- Returns:
- the instruction offset/address
-
getOffsetEnd
long getOffsetEnd()Retrieve the end offset (exclusive) of this instruction- Specified by:
getOffsetEndin interfaceILocatedInstruction- Returns:
getOffset()+IInstruction.getSize()
-
setOffset
void setOffset(long offset) Set this instruction's IR offset. Dangerous method. Make sure to ensure CFG consistency if this instruction is part of a CFG.- Parameters:
offset-
-
withOffset
Update the instruction offset.- Parameters:
offset- new offset- Returns:
- this object
-
setSize
void setSize(int size) Set this instruction's IR size. Dangerous method. Make sure to ensure CFG consistency if this instruction is part of a CFG.- Parameters:
size- new size
-
withSize
Update the instruction size.- Parameters:
size- new size- Returns:
- this object
-
adjustSize
void adjustSize(int delta) Adjust this instruction's IR size. Dangerous method. Make sure to ensure CFG consistency if this instruction is part of a CFG.- Parameters:
delta- added to the currentsize
-
getOpcode
DOpcodeType getOpcode()Get this instruction opcode.- Returns:
-
setOpcode
Change the instruction opcode. This method is dangerous. Instruction operands may require an update as well.- Parameters:
opcode-
-
isOpcode
Determine if this instruction's opcode is any of the provided candidates.- Parameters:
candidateOpcodes- a list of candidate opcodes- Returns:
- true if this instruction's opcode was one of the candidates
-
getOperand1
IDElement getOperand1()Get the first operand. May be null if the opcode does not specify one. Refer togetOpcode()andDOpcodeType.- Returns:
-
setOperand1
Change the instruction first operand. This method is dangerous. Other instruction attributes may require an update as well.- Parameters:
opnd-
-
getOperand2
IDElement getOperand2()Get the second operand. May be null if the opcode does not specify one. Refer togetOpcode()andDOpcodeType.- Returns:
-
setOperand2
Change the instruction second operand. This method is dangerous. Other instruction attributes may require an update as well.- Parameters:
opnd-
-
hasUseSideEffects
boolean hasUseSideEffects(boolean includeCanThrow) Determine whether the used components of the statement may have side-effects.This method is not fail-safe, it works on a best-effort basis. Refer to
IDExpression.hasSideEffects(IDMethodContext, boolean)for more information.- Parameters:
includeCanThrow-- Returns:
-
isNop
boolean isNop()- Returns:
- true if this instruction is a
nop
-
isAssign
boolean isAssign()- Returns:
- true if this instruction is an
assignment
-
getAssignDestination
IDExpression getAssignDestination() -
setAssignDestination
-
getAssignSource
IDExpression getAssignSource() -
setAssignSource
-
isAssignToVar
default boolean isAssignToVar() -
isAssignToVar
default boolean isAssignToVar(int wantedVarId) -
isAssignFromVar
default boolean isAssignFromVar() -
isAssignFromVar
default boolean isAssignFromVar(int wantedVarId) -
isAssignFromVarToVar
default boolean isAssignFromVarToVar() -
isAssignFromVarToVar
default boolean isAssignFromVarToVar(int wantedSrcVarId, int wantedDstVarId) -
isInvoke
boolean isInvoke()- Returns:
- true if this instruction is an
invocation(call, new, new-array, alloc-object)
-
getInvokeData
IDInvokeInfo getInvokeData()- Returns:
- the invocation information, if the instruction
is an invocation
-
setBranchTarget
int setBranchTarget(int offset) Update the branch target for unconditional and conditional jumps only. This function fails for all other opcodes, including switches.- Parameters:
offset- the new offset- Returns:
- previous value
-
getBranchTarget
int getBranchTarget() -
isJump
boolean isJump()- Returns:
- true if this instruction is a
jump(goto)
-
isJumpTo
boolean isJumpTo(int wantedTarget) -
isJcond
boolean isJcond()- Returns:
- true if this instruction is a
conditional jump
-
isJcondTo
boolean isJcondTo(int wantedTarget) -
isJumpOrJcond
boolean isJumpOrJcond() -
isJumpOrJcondTo
boolean isJumpOrJcondTo(int wantedTarget) -
isJcondOrSwitch
boolean isJcondOrSwitch() -
getJcondCondition
IDExpression getJcondCondition()Get the condition predicate (if the instruction is a JCOND).- Returns:
-
setJcondCondition
- Parameters:
cond-- Returns:
-
reverseJcondCondition
void reverseJcondCondition() -
isSwitch
boolean isSwitch()- Returns:
- true if this instruction is a
switch
-
isSwitchOnInt
boolean isSwitchOnInt() -
isSwitchOnString
boolean isSwitchOnString() -
getSwitchData
IDSwitchData getSwitchData() -
setSwitchData
-
getSwitchExpression
IDExpression getSwitchExpression() -
setSwitchExpression
-
isReturn
boolean isReturn()- Returns:
- true if this instruction is a
return
-
getReturnExpression
IDExpression getReturnExpression() -
setReturnExpression
-
isThrow
boolean isThrow()- Returns:
- true if this instruction is a
throw
-
getThrowExpression
IDExpression getThrowExpression() -
setThrowExpression
-
isReturnOrThrow
boolean isReturnOrThrow() -
isStoreException
boolean isStoreException()- Returns:
- true if this instruction is a
store-exception(special opcode)
-
getStoredExceptionVariable
IDVar getStoredExceptionVariable()- Returns:
- the exception variable set up by a
store-exceptioninstruction
-
setStoredExceptionVariable
- Parameters:
ex- a new exception variable for astore-exceptioninstruction- Returns:
- the previous variable
-
isMonitorEnter
boolean isMonitorEnter()- Returns:
- true if this instruction is a
monitor-enter
-
isMonitorExit
boolean isMonitorExit()- Returns:
- true if this instruction is a
monitor-exit
-
transformToNop
void transformToNop()Transform any instruction to a NOP. -
transformJcondToJump
void transformJcondToJump()Transform a conditional jump instruction to a jump. It is the caller's responsibility to verify that the instruction is a JCOND.IF pred GOTO target ==> GOTO target
-
transformToJump
void transformToJump(int offset) Transform any instruction to a jump, and update the jump target.- Parameters:
offset- target offset
-
transformToJump
Transform any instruction to a jump, and update the jump target.- Parameters:
target- a target
-
transformJcondToAssign
Transform a conditional jump instruction to a conditional-predicate assignment. It is the caller's responsibility to verify that the instruction is a JCOND.IF pred GOTO target ==> dst = pred
- Parameters:
dst- the destination operand for the predicate
-
transformSwitchToJcond
boolean transformSwitchToJcond()Transform a single-case switch into a conditional jump.SWITCH(VAR) { CASE X: GOTO target; } // fall-through => IF VAR==X GOTO target; // fall-through- Returns:
- success indicators (if the switch has several cases, this method will fail)
-
updateTargets
Update the targets of a branching instruction. This method has no effect on IR opcodes other thanJUMP,JCOND, andSWITCH.- Parameters:
oldToNewOffsets- a map of current IR offsets to new IR offsets- Returns:
- the number of updated targets
-
updateTargets
Update the targets of a branching instruction. This method has no effect on IR opcodes other thanJUMP,JCOND, andSWITCH.- Parameters:
oldToNewOffsets- a map of current IR offsets to new IR offsetsfailOnMissedEntry- if true, the method will raise if a (current) branch target cannot be mapped to a new target (i.e., if there is no entry for a branch target in the map)- Returns:
- the number of updated targets
-
morph
This dangerous method allows changing an IR instruction into a different one, while keeping metadata (e.g. offset, size, etc.) intact. If possible, use one of thetransformXxxinstructions instead.- Parameters:
opcode- new opcodeopnd1- new operand 1 (if any) - refer toDOpcodeType's type for operand typeopnd2- new operand 2 (if any) - refer toDOpcodeType's type for operand type
-
verify
Verify this instruction.Currently, this method verifies that the instruction operands match the
current opcodespecifications (seeDOpcodeType).- Throws:
IllegalStateException- throw on error
-
replaceUsedVariable
Deep replace all matching used variables of this instruction. The replacement expression is duplicated to avoid reuse. Defined identifiers (if any) are not replaced.- Parameters:
var- target variable to be replacedrepl- expression that will replace the variable- Returns:
- the number of replacements
-
replaceDefinedVariable
Replace the variable defined by this statement (if there is any).- Parameters:
var- target variable to be replacedrepl- expression that will replace the variable- Returns:
- the number of replacements (usually 0, potentially 1 for an assigment-like instruction)
-
getUsedVariables
Get the variables used (read) by this instruction.- Returns:
- the list of all variables used, which may contain duplicates variables if the
instruction uses the same variable multiple times (example:
z = x + (y * x)would return[y, x, x].
-
getDefinedVariable
IDVar getDefinedVariable()Get the identifier defined (written) by this method, if there is one. OnlyDOpcodeType.IR_ASSIGNandDOpcodeType.IR_STORE_EXCEPTIONmay define (write) identifiers.- Returns:
-
countUsedVariable
Count the number of times the provided variable is used (read) by this instruction.Example (ASSIGN opcode):
x = y * (y + z)=> x is not used; y is used twice; z is used once- Parameters:
var-- Returns:
-
visitInstruction
Visit this instruction and its constituents. The visit is made depth-first, pre-order, and parents are recorded. (Refer toIVisitResultsfor details.)Same as
visitInstructionPreOrder. Replacements must be reported (refer toIDExpression.visitDepthPre(IDVisitor)for details).- Parameters:
visitor- visitor object- Returns:
- success indicator; true unless a different value was specified in
DVisitResultswhen visiting an element
-
visitInstruction
Visit this instruction and its constituents. The visit is made depth-first, pre-order, and parents are recorded. (Refer toIVisitResultsfor details.)Same as
visitInstructionPreOrder. Replacements must be reported (refer toIDExpression.visitDepthPre(IDVisitor)for details).- Parameters:
visitor- visitor objectskipAssignmentDestination- true to skip visiting the destination ofDOpcodeType.IR_ASSIGNorDOpcodeType.IR_STORE_EXCEPTION- Returns:
- success indicator; true unless a different value was specified in
DVisitResultswhen visiting an element
-
visitInstructionPreOrder
Visit this instruction and its constituents. The visit is made depth-first, pre-order, and parents are recorded. (Refer toIVisitResultsfor details.)Replacements must be reported (refer to
IDExpression.visitDepthPre(IDVisitor)for details).- Parameters:
visitor- visitor objectskipAssignmentDestination- true to skip visiting the destination ofDOpcodeType.IR_ASSIGNorDOpcodeType.IR_STORE_EXCEPTION- Returns:
- success indicator; true unless a different value was specified in
DVisitResultswhen visiting an element
-
visitInstructionPostOrder
Visit this instruction and its constituents. The visit is made depth-first, post-order, and parents are recorded. (Refer toIVisitResultsfor details.)Replacements need not be reported.
- Parameters:
visitor- visitor objectskipAssignmentDestination- true to skip visiting the destination ofDOpcodeType.IR_ASSIGNorDOpcodeType.IR_STORE_EXCEPTION- Returns:
- success indicator; true unless a different value was specified in
DVisitResultswhen visiting an element
-
evaluate
Convenience method: evaluate the IR instruction using the provided set a variable values.- Parameters:
varmap- a map of variable values to be used when evaluating the expression (this map will not be modified after evaluation of the instruction; for full-control of the emulation, useIDExpression.evaluate(IDState)instead of this method)- Returns:
- the offset of the next IR instruction to be executed; null if none (e.g. a Return was executed)
- Throws:
DexDecEvaluationException
-