Search in sources :

Example 6 with BuilderInstruction

use of org.jf.dexlib2.builder.BuilderInstruction in project atlas by alibaba.

the class PatchMethodTool method modifyMethodAndFix.

private static MethodImplementation modifyMethodAndFix(@Nonnull MethodImplementation implementation, Method method) {
    MutableMethodImplementation mutableImplementation = new MutableMethodImplementation(implementation);
    System.out.println(mutableImplementation.getRegisterCount());
    List<BuilderInstruction> instructions = mutableImplementation.getInstructions();
    mutableImplementation.addInstruction(0, new BuilderInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference("AndFix:" + method.getDefiningClass().replace("/", "."))));
    mutableImplementation.addInstruction(1, new BuilderInstruction35c(Opcode.INVOKE_STATIC, 1, 0, 0, 0, 0, 0, new ImmutableMethodReference("Landroid/util/Log;", "e", Lists.newArrayList("Ljava/lang/String;", "Ljava/lang/String;"), "I")));
    return mutableImplementation;
}
Also used : ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) BuilderInstruction(org.jf.dexlib2.builder.BuilderInstruction) BuilderInstruction35c(org.jf.dexlib2.builder.instruction.BuilderInstruction35c) BuilderInstruction21c(org.jf.dexlib2.builder.instruction.BuilderInstruction21c) MutableMethodImplementation(org.jf.dexlib2.builder.MutableMethodImplementation) ImmutableStringReference(org.jf.dexlib2.immutable.reference.ImmutableStringReference)

Example 7 with BuilderInstruction

use of org.jf.dexlib2.builder.BuilderInstruction in project atlas by alibaba.

the class PatchMethodTool method modifyMethodTpatch.

private static MethodImplementation modifyMethodTpatch(@Nonnull MethodImplementation implementation, Method method) {
    MutableMethodImplementation mutableImplementation = new MutableMethodImplementation(implementation);
    System.out.println(mutableImplementation.getRegisterCount());
    List<BuilderInstruction> instructions = mutableImplementation.getInstructions();
    boolean isModified = false;
    for (int i = 0; i < instructions.size(); i++) {
        isModified = false;
        if (instructions.get(i).getOpcode() == Opcode.INVOKE_DIRECT) {
            if (!isModified) {
                mutableImplementation.addInstruction(i++, new BuilderInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference("tpatch:" + method.getDefiningClass().replace("/", "."))));
                mutableImplementation.addInstruction(i++, new BuilderInstruction35c(Opcode.INVOKE_STATIC, 1, 0, 0, 0, 0, 0, new ImmutableMethodReference("Landroid/util/Log;", "e", Lists.newArrayList("Ljava/lang/String;", "Ljava/lang/String;"), "I")));
                isModified = true;
                break;
            }
        }
    // mutableImplementation.addInstruction(instructions.get(i));
    }
    return mutableImplementation;
}
Also used : ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) BuilderInstruction(org.jf.dexlib2.builder.BuilderInstruction) BuilderInstruction35c(org.jf.dexlib2.builder.instruction.BuilderInstruction35c) BuilderInstruction21c(org.jf.dexlib2.builder.instruction.BuilderInstruction21c) MutableMethodImplementation(org.jf.dexlib2.builder.MutableMethodImplementation) ImmutableStringReference(org.jf.dexlib2.immutable.reference.ImmutableStringReference)

Example 8 with BuilderInstruction

use of org.jf.dexlib2.builder.BuilderInstruction 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)

Example 9 with BuilderInstruction

use of org.jf.dexlib2.builder.BuilderInstruction in project soot by Sable.

the class DexPrinter method fixLongJumps.

/**
 * Fixes long jumps that exceed the maximum distance for the respective jump
 * type
 *
 * @param instructions
 *            The list of generated dalvik instructions
 * @param labelAssigner
 *            The label assigner that maps statements to labels
 * @param stmtV
 *            The statement visitor used to produce the dalvik instructions
 */
private void fixLongJumps(List<BuilderInstruction> instructions, LabelAssigner labelAssigner, StmtVisitor stmtV) {
    // Only construct the maps once and update them afterwards
    Map<Instruction, Integer> instructionsToIndex = new HashMap<Instruction, Integer>();
    List<Integer> instructionsToOffsets = new ArrayList<Integer>();
    Map<Label, Integer> labelsToOffsets = new HashMap<Label, Integer>();
    Map<Label, Integer> labelsToIndex = new HashMap<Label, Integer>();
    boolean hasChanged;
    l0: do {
        // Look for changes anew every time
        hasChanged = false;
        instructionsToOffsets.clear();
        // Build a mapping between instructions and offsets
        {
            int offset = 0;
            int idx = 0;
            for (BuilderInstruction bi : instructions) {
                instructionsToIndex.put(bi, idx);
                instructionsToOffsets.add(offset);
                Stmt origStmt = stmtV.getStmtForInstruction(bi);
                if (origStmt != null) {
                    Label lbl = labelAssigner.getLabelUnsafe(origStmt);
                    if (lbl != null) {
                        labelsToOffsets.put(lbl, offset);
                        labelsToIndex.put(lbl, idx);
                    }
                }
                offset += (bi.getFormat().size / 2);
                idx++;
            }
        }
        // Look for references to labels
        for (int j = 0; j < instructions.size(); j++) {
            BuilderInstruction bj = instructions.get(j);
            if (bj instanceof BuilderOffsetInstruction) {
                BuilderOffsetInstruction boj = (BuilderOffsetInstruction) bj;
                // Compute the distance between the instructions
                Insn jumpInsn = stmtV.getInsnForInstruction(boj);
                if (jumpInsn instanceof InsnWithOffset) {
                    InsnWithOffset offsetInsn = (InsnWithOffset) jumpInsn;
                    Integer targetOffset = labelsToOffsets.get(boj.getTarget());
                    if (targetOffset == null)
                        continue;
                    int distance = instructionsToOffsets.get(j) - targetOffset;
                    if (Math.abs(distance) > offsetInsn.getMaxJumpOffset()) {
                        // We need intermediate jumps
                        insertIntermediateJump(labelsToIndex.get(boj.getTarget()), j, stmtV, instructions, labelAssigner);
                        hasChanged = true;
                        continue l0;
                    }
                }
            }
        }
    } while (hasChanged);
}
Also used : Insn(soot.toDex.instructions.Insn) BuilderOffsetInstruction(org.jf.dexlib2.builder.BuilderOffsetInstruction) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) BuilderInstruction(org.jf.dexlib2.builder.BuilderInstruction) ArrayList(java.util.ArrayList) Label(org.jf.dexlib2.builder.Label) InsnWithOffset(soot.toDex.instructions.InsnWithOffset) BuilderOffsetInstruction(org.jf.dexlib2.builder.BuilderOffsetInstruction) BuilderInstruction(org.jf.dexlib2.builder.BuilderInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) NopStmt(soot.jimple.NopStmt) Stmt(soot.jimple.Stmt) IdentityStmt(soot.jimple.IdentityStmt) MonitorStmt(soot.jimple.MonitorStmt)

Example 10 with BuilderInstruction

use of org.jf.dexlib2.builder.BuilderInstruction in project tinker by Tencent.

the class BuilderMutableMethodImplementation method fixInstructions.

private void fixInstructions() {
    HashSet<MethodLocation> payloadLocations = Sets.newHashSet();
    for (MethodLocation location : instructionList) {
        BuilderInstruction instruction = location.instruction;
        if (instruction != null) {
            switch(instruction.getOpcode()) {
                case SPARSE_SWITCH:
                case PACKED_SWITCH:
                    {
                        MethodLocation targetLocation = ((BuilderOffsetInstruction) instruction).getTarget().getLocation();
                        BuilderInstruction targetInstruction = targetLocation.instruction;
                        if (targetInstruction == null) {
                            throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d points to the end of the method.", location.codeAddress, location.index));
                        }
                        if (targetInstruction.getOpcode() == Opcode.NOP) {
                            targetInstruction = getFirstNonNop(targetLocation.index + 1);
                        }
                        if (targetInstruction == null || !(targetInstruction instanceof BuilderSwitchPayload)) {
                            throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d does not refer to a payload instruction.", location.codeAddress, location.index));
                        }
                        if ((instruction.opcode == Opcode.PACKED_SWITCH && targetInstruction.getOpcode() != Opcode.PACKED_SWITCH_PAYLOAD) || (instruction.opcode == Opcode.SPARSE_SWITCH && targetInstruction.getOpcode() != Opcode.SPARSE_SWITCH_PAYLOAD)) {
                            throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d refers to the wrong type of payload instruction.", location.codeAddress, location.index));
                        }
                        if (!payloadLocations.add(targetLocation)) {
                            throw new IllegalStateException("Multiple switch instructions refer to the same payload. " + "This is not currently supported. Please file a bug :)");
                        }
                        ((BuilderSwitchPayload) targetInstruction).referrer = location;
                        break;
                    }
                default:
                    {
                        break;
                    }
            }
        }
    }
    boolean madeChanges;
    do {
        madeChanges = false;
        for (int index = 0; index < instructionList.size(); index++) {
            MethodLocation location = instructionList.get(index);
            BuilderInstruction instruction = location.instruction;
            if (instruction != null) {
                switch(instruction.getOpcode()) {
                    case GOTO:
                        {
                            int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
                            if (offset < Byte.MIN_VALUE || offset > Byte.MAX_VALUE) {
                                BuilderOffsetInstruction replacement;
                                if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
                                    replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
                                } else {
                                    replacement = new BuilderInstruction20t(Opcode.GOTO_16, ((BuilderOffsetInstruction) instruction).getTarget());
                                }
                                replaceInstruction(location.index, replacement);
                                madeChanges = true;
                            }
                            break;
                        }
                    case GOTO_16:
                        {
                            int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
                            if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
                                BuilderOffsetInstruction replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
                                replaceInstruction(location.index, replacement);
                                madeChanges = true;
                            }
                            break;
                        }
                    case SPARSE_SWITCH_PAYLOAD:
                    case PACKED_SWITCH_PAYLOAD:
                        if (((BuilderSwitchPayload) instruction).referrer == null) {
                            // if the switch payload isn't referenced, just remove it
                            removeInstruction(index);
                            index--;
                            madeChanges = true;
                            break;
                        }
                    // intentional fall-through
                    case ARRAY_PAYLOAD:
                        {
                            if ((location.codeAddress & 0x01) != 0) {
                                int previousIndex = location.index - 1;
                                MethodLocation previousLocation = instructionList.get(previousIndex);
                                Instruction previousInstruction = previousLocation.instruction;
                                assert previousInstruction != null;
                                if (previousInstruction.getOpcode() == Opcode.NOP) {
                                    removeInstruction(previousIndex);
                                    index--;
                                } else {
                                    addInstruction(location.index, new BuilderInstruction10x(Opcode.NOP));
                                    index++;
                                }
                                madeChanges = true;
                            }
                            break;
                        }
                    default:
                        {
                            break;
                        }
                }
            }
        }
    } while (madeChanges);
    fixInstructions = false;
}
Also used : BuilderInstruction10x(org.jf.dexlib2.builder.instruction.BuilderInstruction10x) BuilderInstruction20t(org.jf.dexlib2.builder.instruction.BuilderInstruction20t) BuilderInstruction30t(org.jf.dexlib2.builder.instruction.BuilderInstruction30t) Instruction(org.jf.dexlib2.iface.instruction.Instruction)

Aggregations

BuilderInstruction (org.jf.dexlib2.builder.BuilderInstruction)8 Instruction (org.jf.dexlib2.iface.instruction.Instruction)7 ImmutableStringReference (org.jf.dexlib2.immutable.reference.ImmutableStringReference)5 MutableMethodImplementation (org.jf.dexlib2.builder.MutableMethodImplementation)4 BuilderInstruction21c (org.jf.dexlib2.builder.instruction.BuilderInstruction21c)4 BuilderInstruction35c (org.jf.dexlib2.builder.instruction.BuilderInstruction35c)4 ImmutableMethodReference (org.jf.dexlib2.immutable.reference.ImmutableMethodReference)4 IdentityStmt (soot.jimple.IdentityStmt)3 MonitorStmt (soot.jimple.MonitorStmt)3 NopStmt (soot.jimple.NopStmt)3 Stmt (soot.jimple.Stmt)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 BuilderOffsetInstruction (org.jf.dexlib2.builder.BuilderOffsetInstruction)2 Label (org.jf.dexlib2.builder.Label)2 Insn (soot.toDex.instructions.Insn)2 InsnWithOffset (soot.toDex.instructions.InsnWithOffset)2 HashSet (java.util.HashSet)1 MethodImplementationBuilder (org.jf.dexlib2.builder.MethodImplementationBuilder)1