Search in sources :

Example 11 with Label

use of org.jf.dexlib2.builder.Label 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 12 with Label

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

the class LabelAssigner method getOrCreateLabel.

public Label getOrCreateLabel(AbstractPayload payload) {
    if (payload == null)
        throw new RuntimeException("Cannot create label for NULL payload");
    Label lbl = payloadToLabel.get(payload);
    if (lbl == null) {
        String labelName = "l" + lastLabelId++;
        lbl = builder.getLabel(labelName);
        payloadToLabel.put(payload, lbl);
        payloadToLabelName.put(payload, labelName);
    }
    return lbl;
}
Also used : Label(org.jf.dexlib2.builder.Label)

Example 13 with Label

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

the class MutableMethodImplementationTest method testTryEndAtEndOfMethod.

@Test
public void testTryEndAtEndOfMethod() {
    MethodImplementationBuilder builder = new MethodImplementationBuilder(10);
    Label startLabel = builder.addLabel("start");
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction32x(Opcode.MOVE_16, 0, 0));
    Label endLabel = builder.addLabel("end");
    builder.addCatch(startLabel, endLabel, startLabel);
    MethodImplementation methodImplementation = builder.getMethodImplementation();
    Assert.assertEquals(0, methodImplementation.getTryBlocks().get(0).getStartCodeAddress());
    Assert.assertEquals(8, methodImplementation.getTryBlocks().get(0).getCodeUnitCount());
    methodImplementation = new MutableMethodImplementation(methodImplementation);
    Assert.assertEquals(0, methodImplementation.getTryBlocks().get(0).getStartCodeAddress());
    Assert.assertEquals(8, methodImplementation.getTryBlocks().get(0).getCodeUnitCount());
}
Also used : MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) BuilderInstruction10x(org.jf.dexlib2.builder.instruction.BuilderInstruction10x) BuilderInstruction32x(org.jf.dexlib2.builder.instruction.BuilderInstruction32x) Test(org.junit.Test)

Example 14 with Label

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

the class PayloadAlignmentTest method testPayloadAlignmentRemoveNopWithReferent.

@Test
public void testPayloadAlignmentRemoveNopWithReferent() {
    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 BuilderInstruction10x(Opcode.NOP));
    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.ARRAY_PAYLOAD });
    Instruction31t referent = (Instruction31t) instructions.get(0);
    Assert.assertEquals(6, 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 15 with Label

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

the class LabelAssigner method getOrCreateLabel.

public Label getOrCreateLabel(Stmt stmt) {
    if (stmt == null)
        throw new RuntimeException("Cannot create label for NULL statement");
    Label lbl = stmtToLabel.get(stmt);
    if (lbl == null) {
        String labelName = "l" + lastLabelId++;
        lbl = builder.getLabel(labelName);
        stmtToLabel.put(stmt, lbl);
        stmtToLabelName.put(stmt, labelName);
    }
    return lbl;
}
Also used : Label(org.jf.dexlib2.builder.Label)

Aggregations

Test (org.junit.Test)8 BuilderInstruction10x (org.jf.dexlib2.builder.instruction.BuilderInstruction10x)6 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)6 Label (org.jf.dexlib2.builder.Label)4 BuilderInstruction10t (org.jf.dexlib2.builder.instruction.BuilderInstruction10t)4 Instruction (org.jf.dexlib2.iface.instruction.Instruction)4 Nonnull (javax.annotation.Nonnull)3 BuilderInstruction (org.jf.dexlib2.builder.BuilderInstruction)3 SwitchElement (org.jf.dexlib2.iface.instruction.SwitchElement)3 IdentityStmt (soot.jimple.IdentityStmt)3 MonitorStmt (soot.jimple.MonitorStmt)3 NopStmt (soot.jimple.NopStmt)3 Stmt (soot.jimple.Stmt)3 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 BuilderOffsetInstruction (org.jf.dexlib2.builder.BuilderOffsetInstruction)2 BuilderInstruction20t (org.jf.dexlib2.builder.instruction.BuilderInstruction20t)2 ExceptionHandler (org.jf.dexlib2.iface.ExceptionHandler)2 OffsetInstruction (org.jf.dexlib2.iface.instruction.OffsetInstruction)2 Instruction31t (org.jf.dexlib2.iface.instruction.formats.Instruction31t)2