Search in sources :

Example 1 with Insn30t

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);
}
Also used : Insn(soot.toDex.instructions.Insn) Insn30t(soot.toDex.instructions.Insn30t) BuilderInstruction(org.jf.dexlib2.builder.BuilderInstruction) Insn10t(soot.toDex.instructions.Insn10t) NopStmt(soot.jimple.NopStmt) InsnWithOffset(soot.toDex.instructions.InsnWithOffset) NopStmt(soot.jimple.NopStmt) Stmt(soot.jimple.Stmt) IdentityStmt(soot.jimple.IdentityStmt) MonitorStmt(soot.jimple.MonitorStmt)

Aggregations

BuilderInstruction (org.jf.dexlib2.builder.BuilderInstruction)1 IdentityStmt (soot.jimple.IdentityStmt)1 MonitorStmt (soot.jimple.MonitorStmt)1 NopStmt (soot.jimple.NopStmt)1 Stmt (soot.jimple.Stmt)1 Insn (soot.toDex.instructions.Insn)1 Insn10t (soot.toDex.instructions.Insn10t)1 Insn30t (soot.toDex.instructions.Insn30t)1 InsnWithOffset (soot.toDex.instructions.InsnWithOffset)1