Search in sources :

Example 6 with LineNumberTag

use of soot.tagkit.LineNumberTag 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 7 with LineNumberTag

use of soot.tagkit.LineNumberTag in project soot by Sable.

the class OutFlow method jimplify.

/**
 * Main.v() entry point for converting list of Instructions to Jimple statements;
 * performs flow analysis, constructs Jimple statements, and fixes jumps.
 * @param constant_pool constant pool of ClassFile.
 * @param this_class constant pool index of the CONSTANT_Class_info object for
 * this' class.
 * @param clearStacks if <i>true</i> semantic stacks will be deleted after
 * the process is complete.
 * @return <i>true</i> if all ok, <i>false</i> if there was an error.
 * @see CFG#jimplify(cp_info[], int)
 * @see Stmt
 */
void jimplify(cp_info[] constant_pool, int this_class) {
    Code_attribute codeAttribute = method.locate_code_attribute();
    Set<Instruction> handlerInstructions = new ArraySet<Instruction>();
    Map<Instruction, SootClass> handlerInstructionToException = new HashMap<Instruction, SootClass>();
    Map<Instruction, TypeStack> instructionToTypeStack;
    Map<Instruction, TypeStack> instructionToPostTypeStack;
    {
        // build graph in
        buildInsnCFGfromBBCFG();
        // Put in successors due to exception handlers
        {
            for (int i = 0; i < codeAttribute.exception_table_length; i++) {
                Instruction startIns = codeAttribute.exception_table[i].start_inst;
                Instruction endIns = codeAttribute.exception_table[i].end_inst;
                Instruction handlerIns = codeAttribute.exception_table[i].handler_inst;
                handlerInstructions.add(handlerIns);
                // Determine exception to catch
                {
                    int catchType = codeAttribute.exception_table[i].catch_type;
                    SootClass exception;
                    if (catchType != 0) {
                        CONSTANT_Class_info classinfo = (CONSTANT_Class_info) constant_pool[catchType];
                        String name = ((CONSTANT_Utf8_info) (constant_pool[classinfo.name_index])).convert();
                        name = name.replace('/', '.');
                        exception = cm.getSootClass(name);
                    } else
                        exception = cm.getSootClass("java.lang.Throwable");
                    handlerInstructionToException.put(handlerIns, exception);
                }
                if (startIns == endIns)
                    throw new RuntimeException("Empty catch range for exception handler");
                Instruction ins = startIns;
                for (; ; ) {
                    Instruction[] succs = ins.succs;
                    Instruction[] newsuccs = new Instruction[succs.length + 1];
                    System.arraycopy(succs, 0, newsuccs, 0, succs.length);
                    newsuccs[succs.length] = handlerIns;
                    ins.succs = newsuccs;
                    ins = ins.next;
                    if (ins == endIns || ins == null)
                        break;
                }
            }
        }
    }
    Set<Instruction> reachableInstructions = new HashSet<Instruction>();
    // Mark all the reachable instructions
    {
        LinkedList<Instruction> instructionsToVisit = new LinkedList<Instruction>();
        reachableInstructions.add(firstInstruction);
        instructionsToVisit.addLast(firstInstruction);
        while (!instructionsToVisit.isEmpty()) {
            Instruction ins = instructionsToVisit.removeFirst();
            Instruction[] succs = ins.succs;
            for (Instruction succ : succs) {
                if (!reachableInstructions.contains(succ)) {
                    reachableInstructions.add(succ);
                    instructionsToVisit.addLast(succ);
                }
            }
        }
    }
    /*
        // Check to see if any instruction is unmarked.
        {
            BasicBlock b = cfg;

             while(b != null)
            {
                Instruction ins = b.head;

                 while(ins != null)
                {
                    if(!reachableInstructions.contains(ins))
                        throw new RuntimeException("Method to jimplify contains unreachable code!  (not handled for now)");

                     ins = ins.next;
                }

                 b = b.next;
            }
        }
        */
    // Perform the flow analysis, and build up instructionToTypeStack and instructionToLocalArray
    {
        instructionToTypeStack = new HashMap<Instruction, TypeStack>();
        instructionToPostTypeStack = new HashMap<Instruction, TypeStack>();
        Set<Instruction> visitedInstructions = new HashSet<Instruction>();
        List<Instruction> changedInstructions = new ArrayList<Instruction>();
        TypeStack initialTypeStack;
        // Build up initial type stack and initial local array (for the first instruction)
        {
            initialTypeStack = TypeStack.v();
        // the empty stack with nothing on it.
        }
        // Get the loop cranked up.
        {
            instructionToTypeStack.put(firstInstruction, initialTypeStack);
            visitedInstructions.add(firstInstruction);
            changedInstructions.add(firstInstruction);
        }
        {
            while (!changedInstructions.isEmpty()) {
                Instruction ins = changedInstructions.get(0);
                changedInstructions.remove(0);
                OutFlow ret = processFlow(ins, instructionToTypeStack.get(ins), constant_pool);
                instructionToPostTypeStack.put(ins, ret.typeStack);
                Instruction[] successors = ins.succs;
                for (Instruction s : successors) {
                    if (!visitedInstructions.contains(s)) {
                        if (handlerInstructions.contains(s)) {
                            TypeStack exceptionTypeStack = (TypeStack.v()).push(RefType.v(handlerInstructionToException.get(s).getName()));
                            instructionToTypeStack.put(s, exceptionTypeStack);
                        } else {
                            instructionToTypeStack.put(s, ret.typeStack);
                        }
                        visitedInstructions.add(s);
                        changedInstructions.add(s);
                    // logger.debug("adding successor: " + s);
                    } else {
                        // logger.debug("considering successor: " + s);
                        TypeStack newTypeStack, oldTypeStack = instructionToTypeStack.get(s);
                        if (handlerInstructions.contains(s)) {
                            // The type stack for an instruction handler should always be that of
                            // single object on the stack.
                            TypeStack exceptionTypeStack = (TypeStack.v()).push(RefType.v(handlerInstructionToException.get(s).getName()));
                            newTypeStack = exceptionTypeStack;
                        } else {
                            try {
                                newTypeStack = ret.typeStack.merge(oldTypeStack);
                            } catch (RuntimeException re) {
                                logger.debug("Considering " + s);
                                throw re;
                            }
                        }
                        if (!newTypeStack.equals(oldTypeStack)) {
                            changedInstructions.add(s);
                        // logger.debug("requires a revisit: " + s);
                        }
                        instructionToTypeStack.put(s, newTypeStack);
                    }
                }
            }
        }
    }
    // logger.debug("Producing Jimple code...");
    // Jimplify each statement
    {
        BasicBlock b = cfg;
        while (b != null) {
            Instruction ins = b.head;
            b.statements = new ArrayList<Stmt>();
            List<Stmt> blockStatements = b.statements;
            for (; ; ) {
                List<Stmt> statementsForIns = new ArrayList<Stmt>();
                if (reachableInstructions.contains(ins))
                    generateJimple(ins, instructionToTypeStack.get(ins), instructionToPostTypeStack.get(ins), constant_pool, statementsForIns, b);
                else
                    statementsForIns.add(Jimple.v().newNopStmt());
                if (!statementsForIns.isEmpty()) {
                    for (int i = 0; i < statementsForIns.size(); i++) {
                        units.add(statementsForIns.get(i));
                        blockStatements.add(statementsForIns.get(i));
                    }
                    instructionToFirstStmt.put(ins, statementsForIns.get(0));
                    instructionToLastStmt.put(ins, statementsForIns.get(statementsForIns.size() - 1));
                }
                if (ins == b.tail)
                    break;
                ins = ins.next;
            }
            b = b.next;
        }
    }
    // fix up jump targets
    jimpleTargetFixup();
    /*
        // Print out basic blocks
        {
            BasicBlock b = cfg;

            logger.debug("Basic blocks for: " + jmethod.getName());

            while(b != null)
            {
                Instruction ins = b.head;

                

                while(ins != null)
                {
                    logger.debug(""+ins.toString());
                    ins = ins.next;
                }

                b = b.next;
            }
        }
        */
    // Insert beginCatch/endCatch statements for exception handling
    {
        Map<Stmt, Stmt> targetToHandler = new HashMap<Stmt, Stmt>();
        for (int i = 0; i < codeAttribute.exception_table_length; i++) {
            Instruction startIns = codeAttribute.exception_table[i].start_inst;
            Instruction endIns = codeAttribute.exception_table[i].end_inst;
            Instruction targetIns = codeAttribute.exception_table[i].handler_inst;
            if (!instructionToFirstStmt.containsKey(startIns) || (endIns != null && (!instructionToLastStmt.containsKey(endIns)))) {
                throw new RuntimeException("Exception range does not coincide with jimple instructions");
            }
            if (!instructionToFirstStmt.containsKey(targetIns)) {
                throw new RuntimeException("Exception handler does not coincide with jimple instruction");
            }
            SootClass exception;
            // Determine exception to catch
            {
                int catchType = codeAttribute.exception_table[i].catch_type;
                if (catchType != 0) {
                    CONSTANT_Class_info classinfo = (CONSTANT_Class_info) constant_pool[catchType];
                    String name = ((CONSTANT_Utf8_info) (constant_pool[classinfo.name_index])).convert();
                    name = name.replace('/', '.');
                    exception = cm.getSootClass(name);
                } else
                    exception = cm.getSootClass("java.lang.Throwable");
            }
            Stmt newTarget;
            // Insert assignment of exception
            {
                Stmt firstTargetStmt = instructionToFirstStmt.get(targetIns);
                if (targetToHandler.containsKey(firstTargetStmt))
                    newTarget = targetToHandler.get(firstTargetStmt);
                else {
                    Local local = Util.v().getLocalCreatingIfNecessary(listBody, "$stack0", UnknownType.v());
                    newTarget = Jimple.v().newIdentityStmt(local, Jimple.v().newCaughtExceptionRef());
                    // changed to account for catch blocks which are also part of normal control flow
                    // units.insertBefore(newTarget, firstTargetStmt);
                    ((PatchingChain<Unit>) units).insertBeforeNoRedirect(newTarget, firstTargetStmt);
                    targetToHandler.put(firstTargetStmt, newTarget);
                    if (units.getFirst() != newTarget) {
                        Unit prev = (Unit) units.getPredOf(newTarget);
                        if (prev != null && prev.fallsThrough())
                            units.insertAfter(Jimple.v().newGotoStmt(firstTargetStmt), prev);
                    }
                }
            }
            // Insert trap
            {
                Stmt firstStmt = instructionToFirstStmt.get(startIns);
                Stmt afterEndStmt;
                if (endIns == null) {
                    // A kludge which isn't really correct, but
                    // gets us closer to correctness (until we
                    // clean up the rest of Soot to properly
                    // represent Traps which extend to the end
                    // of a method): if the protected code extends
                    // to the end of the method, use the last Stmt
                    // as the endUnit of the Trap, even though
                    // that will leave the last unit outside
                    // the protected area.
                    afterEndStmt = (Stmt) units.getLast();
                } else {
                    afterEndStmt = instructionToLastStmt.get(endIns);
                    IdentityStmt catchStart = (IdentityStmt) targetToHandler.get(afterEndStmt);
                    // (Cast to IdentityStmt as an assertion check.)
                    if (catchStart != null) {
                        // before the old afterEndStmt.
                        if (catchStart != units.getPredOf(afterEndStmt)) {
                            throw new IllegalStateException("Assertion failure: catchStart != pred of afterEndStmt");
                        }
                        afterEndStmt = catchStart;
                    }
                }
                Trap trap = Jimple.v().newTrap(exception, firstStmt, afterEndStmt, newTarget);
                listBody.getTraps().add(trap);
            }
        }
    }
    /* convert line number table to tags attached to statements */
    if (Options.v().keep_line_number()) {
        HashMap<Stmt, Tag> stmtstags = new HashMap<Stmt, Tag>();
        LinkedList<Stmt> startstmts = new LinkedList<Stmt>();
        attribute_info[] attrs = codeAttribute.attributes;
        for (attribute_info element : attrs) {
            if (element instanceof LineNumberTable_attribute) {
                LineNumberTable_attribute lntattr = (LineNumberTable_attribute) element;
                for (line_number_table_entry element0 : lntattr.line_number_table) {
                    Stmt start_stmt = instructionToFirstStmt.get(element0.start_inst);
                    if (start_stmt != null) {
                        LineNumberTag lntag = new LineNumberTag(element0.line_number);
                        stmtstags.put(start_stmt, lntag);
                        startstmts.add(start_stmt);
                    }
                }
            }
        }
        /* if the predecessor of a statement is a caughtexcetionref,
             * give it the tag of its successor */
        for (Iterator<Stmt> stmtIt = new ArrayList<Stmt>(stmtstags.keySet()).iterator(); stmtIt.hasNext(); ) {
            final Stmt stmt = stmtIt.next();
            Stmt pred = stmt;
            Tag tag = stmtstags.get(stmt);
            while (true) {
                pred = (Stmt) units.getPredOf(pred);
                if (pred == null)
                    break;
                if (!(pred instanceof IdentityStmt))
                    break;
                stmtstags.put(pred, tag);
                pred.addTag(tag);
            }
        }
        /* attach line number tag to each statement. */
        for (int i = 0; i < startstmts.size(); i++) {
            Stmt stmt = startstmts.get(i);
            Tag tag = stmtstags.get(stmt);
            stmt.addTag(tag);
            stmt = (Stmt) units.getSuccOf(stmt);
            while (stmt != null && !stmtstags.containsKey(stmt)) {
                stmt.addTag(tag);
                stmt = (Stmt) units.getSuccOf(stmt);
            }
        }
    }
}
Also used : ArraySet(soot.util.ArraySet) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Unit(soot.Unit) GotoStmt(soot.jimple.GotoStmt) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) TableSwitchStmt(soot.jimple.TableSwitchStmt) LookupSwitchStmt(soot.jimple.LookupSwitchStmt) Stmt(soot.jimple.Stmt) LineNumberTag(soot.tagkit.LineNumberTag) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) IdentityStmt(soot.jimple.IdentityStmt) HashSet(java.util.HashSet) ArraySet(soot.util.ArraySet) PatchingChain(soot.PatchingChain) Local(soot.Local) Trap(soot.Trap) SootClass(soot.SootClass) LinkedList(java.util.LinkedList) Tag(soot.tagkit.Tag) LineNumberTag(soot.tagkit.LineNumberTag) BytecodeOffsetTag(soot.tagkit.BytecodeOffsetTag) Map(java.util.Map) HashMap(java.util.HashMap)

Example 8 with LineNumberTag

use of soot.tagkit.LineNumberTag in project soot by Sable.

the class BafASMBackend method generateMethodBody.

/*
	 * (non-Javadoc)
	 * 
	 * @see soot.AbstractASMBackend#generateMethodBody(org.objectweb.asm.
	 * MethodVisitor, soot.SootMethod)
	 */
@Override
protected void generateMethodBody(MethodVisitor mv, SootMethod method) {
    BafBody body = getBafBody(method);
    Chain<Unit> instructions = body.getUnits();
    /*
		 * Create a label for each instruction that is the target of some branch
		 */
    for (UnitBox box : body.getUnitBoxes(true)) {
        Unit u = box.getUnit();
        if (!branchTargetLabels.containsKey(u)) {
            branchTargetLabels.put(u, new Label());
        }
    }
    Label startLabel = null;
    if (Options.v().write_local_annotations()) {
        startLabel = new Label();
        mv.visitLabel(startLabel);
    }
    /*
		 * Handle all TRY-CATCH-blocks
		 */
    for (Trap trap : body.getTraps()) {
        // Check if the try-block contains any statement
        if (trap.getBeginUnit() != trap.getEndUnit()) {
            Label start = branchTargetLabels.get(trap.getBeginUnit());
            Label end = branchTargetLabels.get(trap.getEndUnit());
            Label handler = branchTargetLabels.get(trap.getHandlerUnit());
            String type = slashify(trap.getException().getName());
            mv.visitTryCatchBlock(start, end, handler, type);
        }
    }
    /*
		 * Handle local variable slots for the "this"-local and the parameters
		 */
    int localCount = 0;
    int[] paramSlots = new int[method.getParameterCount()];
    Set<Local> assignedLocals = new HashSet<Local>();
    /*
		 * For non-static methods the first parameters and zero-slot is the
		 * "this"-local
		 */
    if (!method.isStatic()) {
        ++localCount;
    }
    for (int i = 0; i < method.getParameterCount(); ++i) {
        paramSlots[i] = localCount;
        localCount += sizeOfType(method.getParameterType(i));
    }
    for (Unit u : instructions) {
        if (u instanceof IdentityInst && ((IdentityInst) u).getLeftOp() instanceof Local) {
            Local l = (Local) ((IdentityInst) u).getLeftOp();
            IdentityRef identity = (IdentityRef) ((IdentityInst) u).getRightOp();
            int slot = 0;
            if (identity instanceof ThisRef) {
                if (method.isStatic())
                    throw new RuntimeException("Attempting to use 'this' in static method");
            } else if (identity instanceof ParameterRef)
                slot = paramSlots[((ParameterRef) identity).getIndex()];
            else {
                // Exception ref. Skip over this
                continue;
            }
            localToSlot.put(l, slot);
            assignedLocals.add(l);
        }
    }
    for (Local local : body.getLocals()) {
        if (assignedLocals.add(local)) {
            localToSlot.put(local, localCount);
            localCount += sizeOfType(local.getType());
        }
    }
    // Generate the code
    for (Unit u : instructions) {
        if (branchTargetLabels.containsKey(u)) {
            mv.visitLabel(branchTargetLabels.get(u));
        }
        if (u.hasTag("LineNumberTag")) {
            LineNumberTag lnt = (LineNumberTag) u.getTag("LineNumberTag");
            Label l;
            if (branchTargetLabels.containsKey(u)) {
                l = branchTargetLabels.get(u);
            } else {
                l = new Label();
                mv.visitLabel(l);
            }
            mv.visitLineNumber(lnt.getLineNumber(), l);
        }
        generateInstruction(mv, (Inst) u);
    }
    // Generate the local annotations
    if (Options.v().write_local_annotations()) {
        Label endLabel = new Label();
        mv.visitLabel(endLabel);
        for (Local local : body.getLocals()) {
            Integer slot = localToSlot.get(local);
            if (slot != null) {
                BafLocal l = (BafLocal) local;
                if (l.getOriginalLocal() != null) {
                    Local jimpleLocal = l.getOriginalLocal();
                    if (jimpleLocal != null)
                        mv.visitLocalVariable(jimpleLocal.getName(), toTypeDesc(jimpleLocal.getType()), null, startLabel, endLabel, slot);
                }
            }
        }
    }
}
Also used : UnitBox(soot.UnitBox) Label(org.objectweb.asm.Label) BafLocal(soot.baf.internal.BafLocal) Local(soot.Local) Trap(soot.Trap) Unit(soot.Unit) ParameterRef(soot.jimple.ParameterRef) ThisRef(soot.jimple.ThisRef) LineNumberTag(soot.tagkit.LineNumberTag) IdentityRef(soot.jimple.IdentityRef) HashSet(java.util.HashSet) BafLocal(soot.baf.internal.BafLocal)

Example 9 with LineNumberTag

use of soot.tagkit.LineNumberTag in project soot by Sable.

the class DexBody method jimplify.

/**
 * Return the jimple equivalent of this body.
 *
 * @param m
 *            the SootMethod that contains this body
 */
public Body jimplify(Body b, SootMethod m) {
    final Jimple jimple = Jimple.v();
    final UnknownType unknownType = UnknownType.v();
    final NullConstant nullConstant = NullConstant.v();
    final Options options = Options.v();
    /*
		 * Timer t_whole_jimplification = new Timer(); Timer t_num = new
		 * Timer(); Timer t_null = new Timer();
		 * 
		 * t_whole_jimplification.start();
		 */
    jBody = (JimpleBody) b;
    deferredInstructions = new ArrayList<DeferableInstruction>();
    instructionsToRetype = new HashSet<RetypeableInstruction>();
    if (IDalvikTyper.ENABLE_DVKTYPER) {
        DalvikTyper.v().clear();
    }
    // process method parameters and generate Jimple locals from Dalvik
    // registers
    List<Local> paramLocals = new LinkedList<Local>();
    if (!isStatic) {
        int thisRegister = numRegisters - numParameterRegisters - 1;
        // generateLocal(UnknownType.v());
        Local thisLocal = jimple.newLocal("$u" + thisRegister, unknownType);
        jBody.getLocals().add(thisLocal);
        registerLocals[thisRegister] = thisLocal;
        JIdentityStmt idStmt = (JIdentityStmt) jimple.newIdentityStmt(thisLocal, jimple.newThisRef(declaringClassType));
        add(idStmt);
        paramLocals.add(thisLocal);
        if (IDalvikTyper.ENABLE_DVKTYPER) {
            DalvikTyper.v().setType(idStmt.leftBox, jBody.getMethod().getDeclaringClass().getType(), false);
        }
    }
    {
        // index of parameter type
        int i = 0;
        // index
        int parameterRegister = numRegisters - numParameterRegisters;
        // register
        for (Type t : parameterTypes) {
            // may
            Local gen = jimple.newLocal("$u" + parameterRegister, unknownType);
            // only
            // use
            // UnknownType
            // here
            // because
            // the
            // local
            // may
            // be
            // reused
            // with
            // a
            // different
            // type
            // later
            // (before
            // splitting)
            jBody.getLocals().add(gen);
            registerLocals[parameterRegister] = gen;
            JIdentityStmt idStmt = (JIdentityStmt) jimple.newIdentityStmt(gen, jimple.newParameterRef(t, i++));
            add(idStmt);
            paramLocals.add(gen);
            if (IDalvikTyper.ENABLE_DVKTYPER) {
                DalvikTyper.v().setType(idStmt.leftBox, t, false);
            }
            // used later in the Dalvik bytecode
            if (t instanceof LongType || t instanceof DoubleType) {
                parameterRegister++;
                // may
                Local g = jimple.newLocal("$u" + parameterRegister, unknownType);
                // only
                // use
                // UnknownType
                // here
                // because
                // the
                // local
                // may
                // be
                // reused
                // with
                // a
                // different
                // type
                // later
                // (before
                // splitting)
                jBody.getLocals().add(g);
                registerLocals[parameterRegister] = g;
            }
            parameterRegister++;
        }
    }
    for (int i = 0; i < (numRegisters - numParameterRegisters - (isStatic ? 0 : 1)); i++) {
        registerLocals[i] = jimple.newLocal("$u" + i, unknownType);
        jBody.getLocals().add(registerLocals[i]);
    }
    // add local to store intermediate results
    storeResultLocal = jimple.newLocal("$u-1", unknownType);
    jBody.getLocals().add(storeResultLocal);
    // process bytecode instructions
    final boolean isOdex = dexFile instanceof DexBackedDexFile ? ((DexBackedDexFile) dexFile).isOdexFile() : false;
    ClassPath cp = null;
    if (isOdex) {
        String[] sootClasspath = options.soot_classpath().split(File.pathSeparator);
        List<String> classpathList = new ArrayList<String>();
        for (String str : sootClasspath) classpathList.add(str);
        try {
            ClassPathResolver resolver = new ClassPathResolver(classpathList, classpathList, classpathList, dexFile);
            cp = new ClassPath(resolver.getResolvedClassProviders().toArray(new ClassProvider[0]));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    int prevLineNumber = -1;
    for (DexlibAbstractInstruction instruction : instructions) {
        if (isOdex && instruction instanceof OdexInstruction)
            ((OdexInstruction) instruction).deOdex(dexFile, method, cp);
        if (dangling != null) {
            dangling.finalize(this, instruction);
            dangling = null;
        }
        instruction.jimplify(this);
        if (instruction.getLineNumber() > 0)
            prevLineNumber = instruction.getLineNumber();
        else {
            instruction.setLineNumber(prevLineNumber);
        }
    }
    for (DeferableInstruction instruction : deferredInstructions) {
        instruction.deferredJimplify(this);
    }
    if (tries != null)
        addTraps();
    int prevLn = -1;
    final boolean keepLineNumber = options.keep_line_number();
    for (DexlibAbstractInstruction instruction : instructions) {
        Unit unit = instruction.getUnit();
        int lineNumber = unit.getJavaSourceStartLineNumber();
        if (keepLineNumber && lineNumber < 0) {
            if (prevLn >= 0) {
                unit.addTag(new LineNumberTag(prevLn));
                unit.addTag(new SourceLineNumberTag(prevLn));
            }
        } else {
            prevLn = lineNumber;
        }
    }
    // At this point Jimple code is generated
    // Cleaning...
    instructions = null;
    // registerLocals = null;
    // storeResultLocal = null;
    instructionAtAddress.clear();
    // localGenerator = null;
    deferredInstructions = null;
    // instructionsToRetype = null;
    dangling = null;
    tries = null;
    /*
		 * We eliminate dead code. Dead code has been shown to occur under the
		 * following circumstances.
		 *
		 * 0006ec: 0d00 |00a2: move-exception v0 ... 0006f2: 0d00 |00a5:
		 * move-exception v0 ... 0x0041 - 0x008a Ljava/lang/Throwable; -> 0x00a5
		 * <any> -> 0x00a2
		 * 
		 * Here there are two traps both over the same region. But the same
		 * always fires, hence rendering the code at a2 unreachable. Dead code
		 * yields problems during local splitting because locals within dead
		 * code will not be split. Hence we remove all dead code here.
		 */
    // Fix traps that do not catch exceptions
    DexTrapStackFixer.v().transform(jBody);
    // Sort out jump chains
    DexJumpChainShortener.v().transform(jBody);
    // Make sure that we don't have any overlapping uses due to returns
    DexReturnInliner.v().transform(jBody);
    // Shortcut: Reduce array initializations
    DexArrayInitReducer.v().transform(jBody);
    // split first to find undefined uses
    getLocalSplitter().transform(jBody);
    // Remove dead code and the corresponding locals before assigning types
    getUnreachableCodeEliminator().transform(jBody);
    DeadAssignmentEliminator.v().transform(jBody);
    UnusedLocalEliminator.v().transform(jBody);
    for (RetypeableInstruction i : instructionsToRetype) i.retype(jBody);
    if (IDalvikTyper.ENABLE_DVKTYPER) {
        DexReturnValuePropagator.v().transform(jBody);
        getCopyPopagator().transform(jBody);
        DexNullThrowTransformer.v().transform(jBody);
        DalvikTyper.v().typeUntypedConstrantInDiv(jBody);
        DeadAssignmentEliminator.v().transform(jBody);
        UnusedLocalEliminator.v().transform(jBody);
        DalvikTyper.v().assignType(jBody);
        // jBody.validate();
        jBody.validateUses();
        jBody.validateValueBoxes();
    // jBody.checkInit();
    // Validate.validateArrays(jBody);
    // jBody.checkTypes();
    // jBody.checkLocals();
    } else {
        // t_num.start();
        DexNumTransformer.v().transform(jBody);
        // t_num.end();
        DexReturnValuePropagator.v().transform(jBody);
        getCopyPopagator().transform(jBody);
        DexNullThrowTransformer.v().transform(jBody);
        // t_null.start();
        DexNullTransformer.v().transform(jBody);
        // t_null.end();
        DexIfTransformer.v().transform(jBody);
        DeadAssignmentEliminator.v().transform(jBody);
        UnusedLocalEliminator.v().transform(jBody);
        // DexRefsChecker.v().transform(jBody);
        DexNullArrayRefTransformer.v().transform(jBody);
    }
    if (IDalvikTyper.ENABLE_DVKTYPER) {
        for (Local l : jBody.getLocals()) {
            l.setType(unknownType);
        }
    }
    // Remove "instanceof" checks on the null constant
    DexNullInstanceofTransformer.v().transform(jBody);
    TypeAssigner.v().transform(jBody);
    final RefType objectType = RefType.v("java.lang.Object");
    if (IDalvikTyper.ENABLE_DVKTYPER) {
        for (Unit u : jBody.getUnits()) {
            if (u instanceof IfStmt) {
                ConditionExpr expr = (ConditionExpr) ((IfStmt) u).getCondition();
                if (((expr instanceof EqExpr) || (expr instanceof NeExpr))) {
                    Value op1 = expr.getOp1();
                    Value op2 = expr.getOp2();
                    if (op1 instanceof Constant && op2 instanceof Local) {
                        Local l = (Local) op2;
                        Type ltype = l.getType();
                        if (ltype instanceof PrimType)
                            continue;
                        if (// by default
                        !(op1 instanceof IntConstant))
                            // in Dalvik
                            continue;
                        IntConstant icst = (IntConstant) op1;
                        int val = icst.value;
                        if (val != 0)
                            continue;
                        expr.setOp1(nullConstant);
                    } else if (op1 instanceof Local && op2 instanceof Constant) {
                        Local l = (Local) op1;
                        Type ltype = l.getType();
                        if (ltype instanceof PrimType)
                            continue;
                        if (// by default
                        !(op2 instanceof IntConstant))
                            // in Dalvik
                            continue;
                        IntConstant icst = (IntConstant) op2;
                        int val = icst.value;
                        if (val != 0)
                            continue;
                        expr.setOp2(nullConstant);
                    } else if (op1 instanceof Local && op2 instanceof Local) {
                    // nothing to do
                    } else if (op1 instanceof Constant && op2 instanceof Constant) {
                        if (op1 instanceof NullConstant && op2 instanceof NumericConstant) {
                            IntConstant nc = (IntConstant) op2;
                            if (nc.value != 0)
                                throw new RuntimeException("expected value 0 for int constant. Got " + expr);
                            expr.setOp2(NullConstant.v());
                        } else if (op2 instanceof NullConstant && op1 instanceof NumericConstant) {
                            IntConstant nc = (IntConstant) op1;
                            if (nc.value != 0)
                                throw new RuntimeException("expected value 0 for int constant. Got " + expr);
                            expr.setOp1(nullConstant);
                        }
                    } else {
                        throw new RuntimeException("error: do not handle if: " + u);
                    }
                }
            }
        }
        // For null_type locals: replace their use by NullConstant()
        List<ValueBox> uses = jBody.getUseBoxes();
        // List<ValueBox> defs = jBody.getDefBoxes();
        List<ValueBox> toNullConstantify = new ArrayList<ValueBox>();
        List<Local> toRemove = new ArrayList<Local>();
        for (Local l : jBody.getLocals()) {
            if (l.getType() instanceof NullType) {
                toRemove.add(l);
                for (ValueBox vb : uses) {
                    Value v = vb.getValue();
                    if (v == l)
                        toNullConstantify.add(vb);
                }
            }
        }
        for (ValueBox vb : toNullConstantify) {
            System.out.println("replace valuebox '" + vb + " with null constant");
            vb.setValue(nullConstant);
        }
        for (Local l : toRemove) {
            System.out.println("removing null_type local " + l);
            l.setType(objectType);
        }
    }
    // We pack locals that are not used in overlapping regions. This may
    // again lead to unused locals which we have to remove.
    LocalPacker.v().transform(jBody);
    UnusedLocalEliminator.v().transform(jBody);
    LocalNameStandardizer.v().transform(jBody);
    // on the fly.
    if (options.wrong_staticness() == Options.wrong_staticness_fix) {
        FieldStaticnessCorrector.v().transform(jBody);
        MethodStaticnessCorrector.v().transform(jBody);
    }
    // Inline PackManager.v().getPack("jb").apply(jBody);
    // Keep only transformations that have not been done
    // at this point.
    TrapTightener.v().transform(jBody);
    TrapMinimizer.v().transform(jBody);
    // LocalSplitter.v().transform(jBody);
    Aggregator.v().transform(jBody);
    // UnusedLocalEliminator.v().transform(jBody);
    // TypeAssigner.v().transform(jBody);
    // LocalPacker.v().transform(jBody);
    // LocalNameStandardizer.v().transform(jBody);
    // Remove if (null == null) goto x else <madness>. We can only do this
    // after we have run the constant propagation as we might not be able
    // to statically decide the conditions earlier.
    ConditionalBranchFolder.v().transform(jBody);
    // Remove unnecessary typecasts
    ConstantCastEliminator.v().transform(jBody);
    IdentityCastEliminator.v().transform(jBody);
    // Remove unnecessary logic operations
    IdentityOperationEliminator.v().transform(jBody);
    // We need to run this transformer since the conditional branch folder
    // might have rendered some code unreachable (well, it was unreachable
    // before as well, but we didn't know).
    UnreachableCodeEliminator.v().transform(jBody);
    // Not sure whether we need this even though we do it earlier on as
    // the earlier pass does not have type information
    // CopyPropagator.v().transform(jBody);
    // we might have gotten new dead assignments and unused locals through
    // copy propagation and unreachable code elimination, so we have to do
    // this again
    DeadAssignmentEliminator.v().transform(jBody);
    UnusedLocalEliminator.v().transform(jBody);
    NopEliminator.v().transform(jBody);
    // Remove unnecessary chains of return statements
    DexReturnPacker.v().transform(jBody);
    for (Unit u : jBody.getUnits()) {
        if (u instanceof AssignStmt) {
            AssignStmt ass = (AssignStmt) u;
            if (ass.getRightOp() instanceof CastExpr) {
                CastExpr c = (CastExpr) ass.getRightOp();
                if (c.getType() instanceof NullType) {
                    ass.setRightOp(nullConstant);
                }
            }
        }
        if (u instanceof DefinitionStmt) {
            DefinitionStmt def = (DefinitionStmt) u;
            // we must manually fix the hierarchy
            if (def.getLeftOp() instanceof Local && def.getRightOp() instanceof CaughtExceptionRef) {
                Type t = def.getLeftOp().getType();
                if (t instanceof RefType) {
                    RefType rt = (RefType) t;
                    if (rt.getSootClass().isPhantom() && !rt.getSootClass().hasSuperclass() && !rt.getSootClass().getName().equals("java.lang.Throwable"))
                        rt.getSootClass().setSuperclass(Scene.v().getSootClass("java.lang.Throwable"));
                }
            }
        }
    }
    // 
    for (Local l : jBody.getLocals()) {
        Type t = l.getType();
        if (t instanceof NullType) {
            l.setType(objectType);
        }
    }
    return jBody;
}
Also used : Options(soot.options.Options) ClassPath(org.jf.dexlib2.analysis.ClassPath) LongType(soot.LongType) CaughtExceptionRef(soot.jimple.CaughtExceptionRef) NullConstant(soot.jimple.NullConstant) Constant(soot.jimple.Constant) IntConstant(soot.jimple.IntConstant) NumericConstant(soot.jimple.NumericConstant) AssignStmt(soot.jimple.AssignStmt) ArrayList(java.util.ArrayList) Unit(soot.Unit) RetypeableInstruction(soot.dexpler.instructions.RetypeableInstruction) RefType(soot.RefType) LineNumberTag(soot.tagkit.LineNumberTag) SourceLineNumberTag(soot.tagkit.SourceLineNumberTag) CastExpr(soot.jimple.CastExpr) PrimType(soot.PrimType) IntConstant(soot.jimple.IntConstant) DeferableInstruction(soot.dexpler.instructions.DeferableInstruction) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) ClassPathResolver(org.jf.dexlib2.analysis.ClassPathResolver) DexlibAbstractInstruction(soot.dexpler.instructions.DexlibAbstractInstruction) NeExpr(soot.jimple.NeExpr) JIdentityStmt(soot.jimple.internal.JIdentityStmt) NullConstant(soot.jimple.NullConstant) Local(soot.Local) IOException(java.io.IOException) LinkedList(java.util.LinkedList) UnknownType(soot.UnknownType) RefType(soot.RefType) Type(soot.Type) UnknownType(soot.UnknownType) DoubleType(soot.DoubleType) LongType(soot.LongType) NullType(soot.NullType) PrimType(soot.PrimType) IfStmt(soot.jimple.IfStmt) OdexInstruction(soot.dexpler.instructions.OdexInstruction) DoubleType(soot.DoubleType) EqExpr(soot.jimple.EqExpr) NumericConstant(soot.jimple.NumericConstant) ValueBox(soot.ValueBox) ConditionExpr(soot.jimple.ConditionExpr) Value(soot.Value) SourceLineNumberTag(soot.tagkit.SourceLineNumberTag) Jimple(soot.jimple.Jimple) NullType(soot.NullType) DefinitionStmt(soot.jimple.DefinitionStmt)

Example 10 with LineNumberTag

use of soot.tagkit.LineNumberTag in project soot by Sable.

the class JasminClass method emitStmt.

void emitStmt(Stmt stmt) {
    LineNumberTag lnTag = (LineNumberTag) stmt.getTag("LineNumberTag");
    if (lnTag != null)
        emit(".line " + lnTag.getLineNumber());
    stmt.apply(new AbstractStmtSwitch() {

        public void caseAssignStmt(AssignStmt s) {
            emitAssignStmt(s);
        }

        public void caseIdentityStmt(IdentityStmt s) {
            if (s.getRightOp() instanceof CaughtExceptionRef && s.getLeftOp() instanceof Local) {
                int slot = localToSlot.get(s.getLeftOp()).intValue();
                // simulate the pushing of the exception onto the
                modifyStackHeight(1);
                if (slot >= 0 && slot <= 3)
                    emit("astore_" + slot, -1);
                else
                    emit("astore " + slot, -1);
            }
        }

        public void caseBreakpointStmt(BreakpointStmt s) {
            emit("breakpoint", 0);
        }

        public void caseInvokeStmt(InvokeStmt s) {
            emitValue(s.getInvokeExpr());
            Type returnType = ((InvokeExpr) s.getInvokeExpr()).getMethodRef().returnType();
            if (!returnType.equals(VoidType.v())) {
                if (sizeOfType(returnType) == 1)
                    emit("pop", -1);
                else
                    emit("pop2", -2);
            }
        }

        public void caseEnterMonitorStmt(EnterMonitorStmt s) {
            emitValue(s.getOp());
            emit("monitorenter", -1);
        }

        public void caseExitMonitorStmt(ExitMonitorStmt s) {
            emitValue(s.getOp());
            emit("monitorexit", -1);
        }

        public void caseGotoStmt(GotoStmt s) {
            if (isNextGotoAJsr) {
                emit("jsr " + unitToLabel.get(s.getTarget()));
                isNextGotoAJsr = false;
                subroutineToReturnAddressSlot.put(s.getTarget(), new Integer(returnAddressSlot));
            } else
                emit("goto " + unitToLabel.get(s.getTarget()));
        }

        public void caseIfStmt(IfStmt s) {
            emitIfStmt(s);
        }

        public void caseLookupSwitchStmt(LookupSwitchStmt s) {
            emitValue(s.getKey());
            emit("lookupswitch", -1);
            List<IntConstant> lookupValues = s.getLookupValues();
            List<Unit> targets = s.getTargets();
            for (int i = 0; i < lookupValues.size(); i++) emit("  " + lookupValues.get(i) + " : " + unitToLabel.get(targets.get(i)));
            emit("  default : " + unitToLabel.get(s.getDefaultTarget()));
        }

        public void caseNopStmt(NopStmt s) {
            emit("nop", 0);
        }

        public void caseRetStmt(RetStmt s) {
            emit("ret " + localToSlot.get(s.getStmtAddress()), 0);
        }

        public void caseReturnStmt(ReturnStmt s) {
            emitValue(s.getOp());
            Value returnValue = s.getOp();
            returnValue.getType().apply(new TypeSwitch() {

                public void defaultCase(Type t) {
                    throw new RuntimeException("invalid return type " + t.toString());
                }

                public void caseDoubleType(DoubleType t) {
                    emit("dreturn", -2);
                }

                public void caseFloatType(FloatType t) {
                    emit("freturn", -1);
                }

                public void caseIntType(IntType t) {
                    emit("ireturn", -1);
                }

                public void caseByteType(ByteType t) {
                    emit("ireturn", -1);
                }

                public void caseShortType(ShortType t) {
                    emit("ireturn", -1);
                }

                public void caseCharType(CharType t) {
                    emit("ireturn", -1);
                }

                public void caseBooleanType(BooleanType t) {
                    emit("ireturn", -1);
                }

                public void caseLongType(LongType t) {
                    emit("lreturn", -2);
                }

                public void caseArrayType(ArrayType t) {
                    emit("areturn", -1);
                }

                public void caseRefType(RefType t) {
                    emit("areturn", -1);
                }

                public void caseNullType(NullType t) {
                    emit("areturn", -1);
                }
            });
        }

        public void caseReturnVoidStmt(ReturnVoidStmt s) {
            emit("return", 0);
        }

        public void caseTableSwitchStmt(TableSwitchStmt s) {
            emitValue(s.getKey());
            emit("tableswitch " + s.getLowIndex() + " ; high = " + s.getHighIndex(), -1);
            List<Unit> targets = s.getTargets();
            for (int i = 0; i < targets.size(); i++) emit("  " + unitToLabel.get(targets.get(i)));
            emit("default : " + unitToLabel.get(s.getDefaultTarget()));
        }

        public void caseThrowStmt(ThrowStmt s) {
            emitValue(s.getOp());
            emit("athrow", -1);
        }
    });
}
Also used : LineNumberTag(soot.tagkit.LineNumberTag)

Aggregations

LineNumberTag (soot.tagkit.LineNumberTag)10 Local (soot.Local)5 Unit (soot.Unit)5 HashSet (java.util.HashSet)3 Trap (soot.Trap)3 Tag (soot.tagkit.Tag)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 LinkedList (java.util.LinkedList)2 List (java.util.List)2 DoubleType (soot.DoubleType)2 LongType (soot.LongType)2 NullType (soot.NullType)2 IdentityStmt (soot.jimple.IdentityStmt)2 Stmt (soot.jimple.Stmt)2 BytecodeOffsetTag (soot.tagkit.BytecodeOffsetTag)2 ColorTag (soot.tagkit.ColorTag)2 Host (soot.tagkit.Host)2 JimpleLineNumberTag (soot.tagkit.JimpleLineNumberTag)2 LinkTag (soot.tagkit.LinkTag)2