use of soot.toDex.instructions.Insn30t in project soot by Sable.
the class DexPrinter method insertIntermediateJump.
/**
* Creates an intermediate jump instruction between the original jump
* instruction and its target
*
* @param targetInsPos
* The jump target index
* @param jumpInsPos
* The position of the jump instruction
* @param stmtV
* The statement visitor used for constructing the instructions
* @param instructions
* The list of Dalvik instructions
* @param labelAssigner
* The label assigner to be used for creating new labels
*/
private void insertIntermediateJump(int targetInsPos, int jumpInsPos, StmtVisitor stmtV, List<BuilderInstruction> instructions, LabelAssigner labelAssigner) {
// Get the original jump instruction
BuilderInstruction originalJumpInstruction = instructions.get(jumpInsPos);
Insn originalJumpInsn = stmtV.getInsnForInstruction(originalJumpInstruction);
if (originalJumpInsn == null)
return;
if (!(originalJumpInsn instanceof InsnWithOffset))
throw new RuntimeException("Unexpected jump instruction target");
InsnWithOffset offsetInsn = (InsnWithOffset) originalJumpInsn;
// If this is goto instruction, we can just replace it
if (originalJumpInsn instanceof Insn10t) {
if (originalJumpInsn.getOpcode() == Opcode.GOTO) {
Insn30t newJump = new Insn30t(Opcode.GOTO_32);
newJump.setTarget(((Insn10t) originalJumpInsn).getTarget());
BuilderInstruction newJumpInstruction = newJump.getRealInsn(labelAssigner);
instructions.remove(jumpInsPos);
instructions.add(jumpInsPos, newJumpInstruction);
stmtV.fakeNewInsn(stmtV.getStmtForInstruction(originalJumpInstruction), newJump, newJumpInstruction);
return;
}
}
// Find a position where we can jump to
int distance = Math.max(targetInsPos, jumpInsPos) - Math.min(targetInsPos, jumpInsPos);
if (distance == 0)
return;
int newJumpIdx = Math.min(targetInsPos, jumpInsPos) + (distance / 2);
int sign = (int) Math.signum(targetInsPos - jumpInsPos);
// label may otherwise be attached to the wrong statement
do {
Stmt newStmt = stmtV.getStmtForInstruction(instructions.get(newJumpIdx));
Stmt prevStmt = newJumpIdx > 0 ? stmtV.getStmtForInstruction(instructions.get(newJumpIdx - 1)) : null;
if (newStmt == null || newStmt == prevStmt) {
newJumpIdx -= sign;
if (newJumpIdx < 0 || newJumpIdx >= instructions.size())
throw new RuntimeException("No position for inserting intermediate " + "jump instruction found");
} else
break;
} while (true);
// Create a jump instruction from the middle to the end
NopStmt nop = Jimple.v().newNopStmt();
Insn30t newJump = new Insn30t(Opcode.GOTO_32);
newJump.setTarget(stmtV.getStmtForInstruction(instructions.get(targetInsPos)));
BuilderInstruction newJumpInstruction = newJump.getRealInsn(labelAssigner);
instructions.add(newJumpIdx, newJumpInstruction);
stmtV.fakeNewInsn(nop, newJump, newJumpInstruction);
// We have added something, so we need to fix indices
if (newJumpIdx <= jumpInsPos)
jumpInsPos++;
if (newJumpIdx <= targetInsPos)
targetInsPos++;
// Jump from the original instruction to the new one in the middle
offsetInsn.setTarget(nop);
BuilderInstruction replacementJumpInstruction = offsetInsn.getRealInsn(labelAssigner);
assert instructions.get(jumpInsPos) == originalJumpInstruction;
instructions.remove(jumpInsPos);
instructions.add(jumpInsPos, replacementJumpInstruction);
stmtV.fakeNewInsn(stmtV.getStmtForInstruction(originalJumpInstruction), originalJumpInsn, replacementJumpInstruction);
// Our indices are still fine, because we just replaced something
Stmt afterNewJump = stmtV.getStmtForInstruction(instructions.get(newJumpIdx + 1));
// Make the original control flow jump around the new artificial jump
// instruction
Insn10t jumpAround = new Insn10t(Opcode.GOTO);
jumpAround.setTarget(afterNewJump);
BuilderInstruction jumpAroundInstruction = jumpAround.getRealInsn(labelAssigner);
instructions.add(newJumpIdx, jumpAroundInstruction);
stmtV.fakeNewInsn(Jimple.v().newNopStmt(), jumpAround, jumpAroundInstruction);
}
Aggregations