Search in sources :

Example 1 with MethodImplementationBuilder

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

the class DexPrinter method addRegisterAssignmentDebugInfo.

private void addRegisterAssignmentDebugInfo(LocalRegisterAssignmentInformation registerAssignment, Map<Local, Integer> seenRegisters, MethodImplementationBuilder builder) {
    Local local = registerAssignment.getLocal();
    String dexLocalType = SootToDexUtils.getDexTypeDescriptor(local.getType());
    StringReference localName = new ImmutableStringReference(local.getName());
    Register reg = registerAssignment.getRegister();
    int register = reg.getNumber();
    Integer beforeRegister = seenRegisters.get(local);
    if (beforeRegister != null) {
        if (beforeRegister == register)
            // No change
            return;
        builder.addEndLocal(beforeRegister);
    }
    builder.addStartLocal(register, localName, new ImmutableTypeReference(dexLocalType), new ImmutableStringReference(""));
    seenRegisters.put(local, register);
}
Also used : Local(soot.Local) ImmutableStringReference(org.jf.dexlib2.immutable.reference.ImmutableStringReference) ImmutableTypeReference(org.jf.dexlib2.immutable.reference.ImmutableTypeReference) StringReference(org.jf.dexlib2.iface.reference.StringReference) ImmutableStringReference(org.jf.dexlib2.immutable.reference.ImmutableStringReference)

Example 2 with MethodImplementationBuilder

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

the class DexPrinter method toMethodImplementation.

private MethodImplementation toMethodImplementation(SootMethod m) {
    if (m.isAbstract() || m.isNative()) {
        return null;
    }
    Body activeBody = m.retrieveActiveBody();
    // when installing the app
    if (m.getName().contains("<") || m.getName().equals(">"))
        if (!m.getName().equals("<init>") && !m.getName().equals("<clinit>"))
            throw new RuntimeException("Invalid method name: " + m.getName());
    // Switch statements may not be empty in dex, so we have to fix this
    // first
    EmptySwitchEliminator.v().transform(activeBody);
    // Dalvik requires synchronized methods to have explicit monitor calls,
    // so we insert them here. See
    // http://milk.com/kodebase/dalvik-docs-mirror/docs/debugger.html
    // We cannot place this upon the developer since it is only required
    // for Dalvik, but not for other targets.
    SynchronizedMethodTransformer.v().transform(activeBody);
    // Tries may not start or end at units which have no corresponding
    // Dalvik
    // instructions such as IdentityStmts. We reduce the traps to start at
    // the
    // first "real" instruction. We could also use a TrapTigthener, but that
    // would be too expensive for what we need here.
    FastDexTrapTightener.v().transform(activeBody);
    // Look for sequences of array element assignments that we can collapse
    // into bulk initializations
    DexArrayInitDetector initDetector = new DexArrayInitDetector();
    initDetector.constructArrayInitializations(activeBody);
    initDetector.fixTraps(activeBody);
    // Split the tries since Dalvik does not supported nested try/catch
    // blocks
    TrapSplitter.v().transform(activeBody);
    // word count of incoming parameters
    int inWords = SootToDexUtils.getDexWords(m.getParameterTypes());
    if (!m.isStatic()) {
        // extra word for "this"
        inWords++;
    }
    // word count of max outgoing parameters
    Collection<Unit> units = activeBody.getUnits();
    // register count = parameters + additional registers, depending on the
    // dex instructions generated (e.g. locals used and constants loaded)
    StmtVisitor stmtV = new StmtVisitor(m, initDetector);
    Chain<Trap> traps = activeBody.getTraps();
    Set<Unit> trapReferences = new HashSet<Unit>(traps.size() * 3);
    for (Trap t : activeBody.getTraps()) {
        trapReferences.add(t.getBeginUnit());
        trapReferences.add(t.getEndUnit());
        trapReferences.add(t.getHandlerUnit());
    }
    toInstructions(units, stmtV, trapReferences);
    int registerCount = stmtV.getRegisterCount();
    if (inWords > registerCount) {
        /*
			 * as the Dalvik VM moves the parameters into the last registers, the "in" word
			 * count must be at least equal to the register count. a smaller register count
			 * could occur if soot generated the method body, see e.g. the handling of
			 * phantom refs in SootMethodRefImpl.resolve(StringBuffer): the body has no
			 * locals for the ParameterRefs, it just throws an error.
			 *
			 * we satisfy the verifier by just increasing the register count, since calling
			 * phantom refs will lead to an error anyway.
			 */
        registerCount = inWords;
    }
    MethodImplementationBuilder builder = new MethodImplementationBuilder(registerCount);
    LabelAssigner labelAssinger = new LabelAssigner(builder);
    List<BuilderInstruction> instructions = stmtV.getRealInsns(labelAssinger);
    fixLongJumps(instructions, labelAssinger, stmtV);
    Map<Local, Integer> seenRegisters = new HashMap<Local, Integer>();
    Map<Instruction, LocalRegisterAssignmentInformation> instructionRegisterMap = stmtV.getInstructionRegisterMap();
    if (Options.v().write_local_annotations()) {
        for (LocalRegisterAssignmentInformation assignment : stmtV.getParameterInstructionsList()) {
            // (at least not if it exists with exactly this name)
            if (assignment.getLocal().getName().equals("this"))
                continue;
            addRegisterAssignmentDebugInfo(assignment, seenRegisters, builder);
        }
    }
    for (BuilderInstruction ins : instructions) {
        Stmt origStmt = stmtV.getStmtForInstruction(ins);
        // If this is a switch payload, we need to place the label
        if (stmtV.getInstructionPayloadMap().containsKey(ins))
            builder.addLabel(labelAssinger.getLabelName(stmtV.getInstructionPayloadMap().get(ins)));
        if (origStmt != null) {
            // Do we need a label here because this a trap handler?
            if (trapReferences.contains(origStmt))
                labelAssinger.getOrCreateLabel(origStmt);
            // Add the label if the statement has one
            String labelName = labelAssinger.getLabelName(origStmt);
            if (labelName != null && !builder.getLabel(labelName).isPlaced())
                builder.addLabel(labelName);
            // Add the tags
            if (stmtV.getStmtForInstruction(ins) != null) {
                List<Tag> tags = origStmt.getTags();
                for (Tag t : tags) {
                    if (t instanceof LineNumberTag) {
                        LineNumberTag lnt = (LineNumberTag) t;
                        builder.addLineNumber(lnt.getLineNumber());
                    } else if (t instanceof SourceFileTag) {
                        SourceFileTag sft = (SourceFileTag) t;
                        builder.addSetSourceFile(new ImmutableStringReference(sft.getSourceFile()));
                    }
                }
            }
        }
        builder.addInstruction(ins);
        LocalRegisterAssignmentInformation registerAssignmentTag = instructionRegisterMap.get(ins);
        if (registerAssignmentTag != null) {
            // Add start local debugging information: Register -> Local
            // assignment
            addRegisterAssignmentDebugInfo(registerAssignmentTag, seenRegisters, builder);
        }
    }
    for (int registersLeft : seenRegisters.values()) builder.addEndLocal(registersLeft);
    toTries(activeBody.getTraps(), stmtV, builder, labelAssinger);
    // Make sure that all labels have been placed by now
    for (Label lbl : labelAssinger.getAllLabels()) if (!lbl.isPlaced())
        throw new RuntimeException("Label not placed: " + lbl);
    return builder.getMethodImplementation();
}
Also used : LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) SourceFileTag(soot.tagkit.SourceFileTag) Label(org.jf.dexlib2.builder.Label) Unit(soot.Unit) 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) LineNumberTag(soot.tagkit.LineNumberTag) Body(soot.Body) MethodImplementationBuilder(org.jf.dexlib2.builder.MethodImplementationBuilder) HashSet(java.util.HashSet) BuilderInstruction(org.jf.dexlib2.builder.BuilderInstruction) Local(soot.Local) Trap(soot.Trap) ImmutableStringReference(org.jf.dexlib2.immutable.reference.ImmutableStringReference) ConstantValueTag(soot.tagkit.ConstantValueTag) SourceFileTag(soot.tagkit.SourceFileTag) AnnotationDefaultTag(soot.tagkit.AnnotationDefaultTag) VisibilityAnnotationTag(soot.tagkit.VisibilityAnnotationTag) InnerClassTag(soot.tagkit.InnerClassTag) FloatConstantValueTag(soot.tagkit.FloatConstantValueTag) AnnotationTag(soot.tagkit.AnnotationTag) IntegerConstantValueTag(soot.tagkit.IntegerConstantValueTag) EnclosingMethodTag(soot.tagkit.EnclosingMethodTag) VisibilityParameterAnnotationTag(soot.tagkit.VisibilityParameterAnnotationTag) Tag(soot.tagkit.Tag) LineNumberTag(soot.tagkit.LineNumberTag) ParamNamesTag(soot.tagkit.ParamNamesTag) DoubleConstantValueTag(soot.tagkit.DoubleConstantValueTag) LongConstantValueTag(soot.tagkit.LongConstantValueTag) SignatureTag(soot.tagkit.SignatureTag) StringConstantValueTag(soot.tagkit.StringConstantValueTag)

Example 3 with MethodImplementationBuilder

use of org.jf.dexlib2.builder.MethodImplementationBuilder in project smali by JesusFreke.

the class PayloadAlignmentTest method testSparseSwitchAlignment.

@Test
public void testSparseSwitchAlignment() {
    MethodImplementationBuilder implBuilder = new MethodImplementationBuilder(10);
    implBuilder.addLabel("switch_target_1");
    implBuilder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, implBuilder.getLabel("goto_target")));
    implBuilder.addLabel("switch_payload");
    implBuilder.addInstruction(new BuilderSparseSwitchPayload(Lists.newArrayList(new SwitchLabelElement(0, implBuilder.getLabel("switch_target_1")), new SwitchLabelElement(5, implBuilder.getLabel("switch_target_2")), new SwitchLabelElement(10, implBuilder.getLabel("switch_target_3")))));
    implBuilder.addLabel("goto_target");
    implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    implBuilder.addLabel("switch_target_2");
    implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    implBuilder.addLabel("switch_target_3");
    implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    implBuilder.addInstruction(new BuilderInstruction31t(Opcode.SPARSE_SWITCH, 0, implBuilder.getLabel("switch_payload")));
    List<Instruction> instructions = Lists.newArrayList(implBuilder.getMethodImplementation().getInstructions());
    checkInstructions(instructions, new Opcode[] { Opcode.GOTO, Opcode.NOP, Opcode.SPARSE_SWITCH_PAYLOAD, Opcode.NOP, Opcode.NOP, Opcode.NOP, Opcode.NOP, Opcode.SPARSE_SWITCH });
    OffsetInstruction gotoInstruction = (OffsetInstruction) instructions.get(0);
    Assert.assertEquals(16, gotoInstruction.getCodeOffset());
    SparseSwitchPayload payload = (SparseSwitchPayload) instructions.get(2);
    Assert.assertEquals(3, payload.getSwitchElements().size());
    Assert.assertEquals(-20, payload.getSwitchElements().get(0).getOffset());
    Assert.assertEquals(-2, payload.getSwitchElements().get(1).getOffset());
    Assert.assertEquals(-1, payload.getSwitchElements().get(2).getOffset());
    OffsetInstruction referent = (OffsetInstruction) instructions.get(7);
    Assert.assertEquals(-18, referent.getCodeOffset());
}
Also used : OffsetInstruction(org.jf.dexlib2.iface.instruction.OffsetInstruction) SparseSwitchPayload(org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload) OffsetInstruction(org.jf.dexlib2.iface.instruction.OffsetInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) Test(org.junit.Test)

Example 4 with MethodImplementationBuilder

use of org.jf.dexlib2.builder.MethodImplementationBuilder in project smali by JesusFreke.

the class PayloadAlignmentTest method testPayloadAlignmentAddNopWithReferent.

@Test
public void testPayloadAlignmentAddNopWithReferent() {
    MethodImplementationBuilder implBuilder = new MethodImplementationBuilder(10);
    Label label = implBuilder.getLabel("array_payload");
    implBuilder.addInstruction(new BuilderInstruction31t(Opcode.FILL_ARRAY_DATA, 0, label));
    implBuilder.addInstruction(new BuilderInstruction12x(Opcode.MOVE, 0, 0));
    implBuilder.addInstruction(new BuilderInstruction12x(Opcode.MOVE, 0, 0));
    implBuilder.addInstruction(new BuilderInstruction12x(Opcode.MOVE, 0, 0));
    implBuilder.addInstruction(new BuilderInstruction12x(Opcode.MOVE, 0, 0));
    implBuilder.addLabel("array_payload");
    implBuilder.addInstruction(new BuilderArrayPayload(4, null));
    List<Instruction> instructions = Lists.newArrayList(implBuilder.getMethodImplementation().getInstructions());
    checkInstructions(instructions, new Opcode[] { Opcode.FILL_ARRAY_DATA, Opcode.MOVE, Opcode.MOVE, Opcode.MOVE, Opcode.MOVE, Opcode.NOP, Opcode.ARRAY_PAYLOAD });
    Instruction31t referent = (Instruction31t) instructions.get(0);
    Assert.assertEquals(8, referent.getCodeOffset());
}
Also used : OffsetInstruction(org.jf.dexlib2.iface.instruction.OffsetInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) Instruction31t(org.jf.dexlib2.iface.instruction.formats.Instruction31t) Test(org.junit.Test)

Example 5 with MethodImplementationBuilder

use of org.jf.dexlib2.builder.MethodImplementationBuilder in project smali by JesusFreke.

the class PayloadAlignmentTest method testPackedSwitchAlignment.

@Test
public void testPackedSwitchAlignment() {
    MethodImplementationBuilder implBuilder = new MethodImplementationBuilder(10);
    implBuilder.addLabel("switch_target_1");
    implBuilder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, implBuilder.getLabel("goto_target")));
    implBuilder.addLabel("switch_payload");
    implBuilder.addInstruction(new BuilderPackedSwitchPayload(0, Lists.newArrayList(implBuilder.getLabel("switch_target_1"), implBuilder.getLabel("switch_target_2"), implBuilder.getLabel("switch_target_3"))));
    implBuilder.addLabel("goto_target");
    implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    implBuilder.addLabel("switch_target_2");
    implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    implBuilder.addLabel("switch_target_3");
    implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    implBuilder.addInstruction(new BuilderInstruction31t(Opcode.PACKED_SWITCH, 0, implBuilder.getLabel("switch_payload")));
    List<Instruction> instructions = Lists.newArrayList(implBuilder.getMethodImplementation().getInstructions());
    checkInstructions(instructions, new Opcode[] { Opcode.GOTO, Opcode.NOP, Opcode.PACKED_SWITCH_PAYLOAD, Opcode.NOP, Opcode.NOP, Opcode.NOP, Opcode.NOP, Opcode.PACKED_SWITCH });
    OffsetInstruction gotoInstruction = (OffsetInstruction) instructions.get(0);
    Assert.assertEquals(12, gotoInstruction.getCodeOffset());
    PackedSwitchPayload payload = (PackedSwitchPayload) instructions.get(2);
    Assert.assertEquals(3, payload.getSwitchElements().size());
    Assert.assertEquals(-16, payload.getSwitchElements().get(0).getOffset());
    Assert.assertEquals(-2, payload.getSwitchElements().get(1).getOffset());
    Assert.assertEquals(-1, payload.getSwitchElements().get(2).getOffset());
    OffsetInstruction referent = (OffsetInstruction) instructions.get(7);
    Assert.assertEquals(-14, referent.getCodeOffset());
}
Also used : OffsetInstruction(org.jf.dexlib2.iface.instruction.OffsetInstruction) PackedSwitchPayload(org.jf.dexlib2.iface.instruction.formats.PackedSwitchPayload) OffsetInstruction(org.jf.dexlib2.iface.instruction.OffsetInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) Test(org.junit.Test)

Aggregations

Test (org.junit.Test)22 BuilderInstruction10x (org.jf.dexlib2.builder.instruction.BuilderInstruction10x)15 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)12 MethodImplementationBuilder (org.jf.dexlib2.builder.MethodImplementationBuilder)9 ImmutableTypeReference (org.jf.dexlib2.immutable.reference.ImmutableTypeReference)8 DexFile (org.jf.dexlib2.iface.DexFile)7 Instruction (org.jf.dexlib2.iface.instruction.Instruction)7 ImmutableDexFile (org.jf.dexlib2.immutable.ImmutableDexFile)7 BuilderInstruction21t (org.jf.dexlib2.builder.instruction.BuilderInstruction21t)6 BuilderInstruction22c (org.jf.dexlib2.builder.instruction.BuilderInstruction22c)6 ClassDef (org.jf.dexlib2.iface.ClassDef)6 Method (org.jf.dexlib2.iface.Method)6 OffsetInstruction (org.jf.dexlib2.iface.instruction.OffsetInstruction)6 ImmutableClassDef (org.jf.dexlib2.immutable.ImmutableClassDef)6 ImmutableMethod (org.jf.dexlib2.immutable.ImmutableMethod)6 ImmutableMethodParameter (org.jf.dexlib2.immutable.ImmutableMethodParameter)6 BuilderInstruction10t (org.jf.dexlib2.builder.instruction.BuilderInstruction10t)4 BuilderInstruction32x (org.jf.dexlib2.builder.instruction.BuilderInstruction32x)3 LinkedHashMap (java.util.LinkedHashMap)2 BuilderInstruction12x (org.jf.dexlib2.builder.instruction.BuilderInstruction12x)2