Java Code Examples for proguard.classfile.instruction.Instruction#accept()

The following examples show how to use proguard.classfile.instruction.Instruction#accept() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: CodeAttributeEditor.java    From java-n-IDE-for-Android with Apache License 2.0 6 votes vote down vote up
public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
{
    if (instructionVisitor != CodeAttributeEditor.this)
    {
        throw new UnsupportedOperationException("Unexpected visitor ["+instructionVisitor+"]");
    }

    for (int index = 0; index < instructions.length; index++)
    {
        Instruction instruction = instructions[index];

        instruction.accept(clazz, method, codeAttribute, offset, CodeAttributeEditor.this);

        offset += instruction.length(offset);
    }
}
 
Example 2
Source File: UnreachableCodeRemover.java    From java-n-IDE-for-Android with Apache License 2.0 6 votes vote down vote up
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
    if (DEBUG)
    {
        System.out.println("  "+(reachableCodeMarker.isReachable(offset) ? "+" : "-")+" "+instruction.toString(offset));
    }

    // Is this instruction unreachable?
    if (!reachableCodeMarker.isReachable(offset))
    {
        // Then delete it.
        codeAttributeEditor.deleteInstruction(offset);

        // Visit the instruction, if required.
        if (extraInstructionVisitor != null)
        {
            instruction.accept(clazz, method, codeAttribute, offset, extraInstructionVisitor);
        }
    }
}
 
Example 3
Source File: EvaluationSimplifier.java    From java-n-IDE-for-Android with Apache License 2.0 6 votes vote down vote up
/**
 * Replaces the instruction at a given offset by a given push instruction.
 */
private void replaceInstruction(Clazz       clazz,
                                int         offset,
                                Instruction instruction,
                                Instruction replacementInstruction)
{
    // Pop unneeded stack entries if necessary.
    int popCount =
        instruction.stackPopCount(clazz) -
        replacementInstruction.stackPopCount(clazz);

    insertPopInstructions(offset, popCount);

    if (DEBUG) System.out.println("  Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstruction.toString()+(popCount == 0 ? "" : " ("+popCount+" pops)"));

    codeAttributeEditor.replaceInstruction(offset, replacementInstruction);

    // Visit the instruction, if required.
    if (extraInstructionVisitor != null)
    {
        // Note: we're not passing the right arguments for now, knowing that
        // they aren't used anyway.
        instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
    }
}
 
Example 4
Source File: EvaluationSimplifier.java    From java-n-IDE-for-Android with Apache License 2.0 6 votes vote down vote up
/**
 * Replaces the given instruction by an infinite loop.
 */
private void replaceByInfiniteLoop(Clazz       clazz,
                                   int         offset,
                                   Instruction instruction)
{
    // Replace the instruction by an infinite loop.
    Instruction replacementInstruction =
        new BranchInstruction(InstructionConstants.OP_GOTO, 0);

    if (DEBUG) System.out.println("  Replacing unreachable instruction by infinite loop "+replacementInstruction.toString(offset));

    codeAttributeEditor.replaceInstruction(offset, replacementInstruction);

    // Visit the instruction, if required.
    if (extraInstructionVisitor != null)
    {
        // Note: we're not passing the right arguments for now, knowing that
        // they aren't used anyway.
        instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
    }
}
 
Example 5
Source File: UnreachableCodeRemover.java    From proguard with GNU General Public License v2.0 6 votes vote down vote up
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
    if (DEBUG)
    {
        System.out.println("  "+(reachableCodeMarker.isReachable(offset) ? "+" : "-")+" "+instruction.toString(offset));
    }

    // Is this instruction unreachable?
    if (!reachableCodeMarker.isReachable(offset))
    {
        // Then delete it.
        codeAttributeEditor.deleteInstruction(offset);

        // Visit the instruction, if required.
        if (extraInstructionVisitor != null)
        {
            instruction.accept(clazz, method, codeAttribute, offset, extraInstructionVisitor);
        }
    }
}
 
Example 6
Source File: UnreachableCodeRemover.java    From bazel with Apache License 2.0 6 votes vote down vote up
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
    if (DEBUG)
    {
        System.out.println("  "+(reachableCodeMarker.isReachable(offset) ? "+" : "-")+" "+instruction.toString(offset));
    }

    // Is this instruction unreachable?
    if (!reachableCodeMarker.isReachable(offset))
    {
        // Then delete it.
        codeAttributeEditor.deleteInstruction(offset);

        // Visit the instruction, if required.
        if (extraInstructionVisitor != null)
        {
            instruction.accept(clazz, method, codeAttribute, offset, extraInstructionVisitor);
        }
    }
}
 
Example 7
Source File: UnreachableCodeRemover.java    From proguard with GNU General Public License v2.0 6 votes vote down vote up
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
    if (DEBUG)
    {
        System.out.println("  "+(reachableCodeMarker.isReachable(offset) ? "+" : "-")+" "+instruction.toString(offset));
    }

    // Is this instruction unreachable?
    if (!reachableCodeMarker.isReachable(offset))
    {
        // Then delete it.
        codeAttributeEditor.deleteInstruction(offset);

        // Visit the instruction, if required.
        if (extraInstructionVisitor != null)
        {
            instruction.accept(clazz, method, codeAttribute, offset, extraInstructionVisitor);
        }
    }
}
 
Example 8
Source File: SideEffectInstructionChecker.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
public boolean hasSideEffects(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
    hasSideEffects = false;

    instruction.accept(clazz, method, codeAttribute, offset, this);

    return hasSideEffects;
}
 
Example 9
Source File: ExceptionInstructionChecker.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Returns whether the given instruction may throw exceptions.
 */
public boolean mayThrowExceptions(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
    mayThrowExceptions = false;

    instruction.accept(clazz, method,  codeAttribute, offset, this);

    return mayThrowExceptions;
}
 
Example 10
Source File: EvaluationShrinker.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Pushes a specified type of stack entry before or at the given offset.
 * The instruction is marked as necessary.
 */
private void insertPushInstructions(int     offset,
                                    boolean replace,
                                    int     computationalType)
{
    // Mark this instruction.
    markInstruction(offset);

    // Create a simple push instrucion.
    Instruction replacementInstruction =
        new SimpleInstruction(pushOpcode(computationalType));

    if (DEBUG) System.out.println(": "+replacementInstruction.toString(offset));

    // Replace or insert the push instruction.
    if (replace)
    {
        // Replace the push instruction.
        codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
    }
    else
    {
        // Insert the push instruction.
        codeAttributeEditor.insertBeforeInstruction(offset, replacementInstruction);

        if (extraAddedInstructionVisitor != null)
        {
            replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
        }
    }
}
 
Example 11
Source File: EvaluationSimplifier.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
    if (DEBUG)
    {
        System.out.println();
        System.out.println("Class "+ClassUtil.externalClassName(clazz.getName()));
        System.out.println("Method "+ClassUtil.externalFullMethodDescription(clazz.getName(),
                                                                             0,
                                                                             method.getName(clazz),
                                                                             method.getDescriptor(clazz)));
    }

    // Evaluate the method.
    partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);

    int codeLength = codeAttribute.u4codeLength;

    // Reset the code changes.
    codeAttributeEditor.reset(codeLength);

    // Replace any instructions that can be simplified.
    for (int offset = 0; offset < codeLength; offset++)
    {
        if (partialEvaluator.isTraced(offset))
        {
            Instruction instruction = InstructionFactory.create(codeAttribute.code,
                                                                offset);

            instruction.accept(clazz, method, codeAttribute, offset, this);
        }
    }

    // Apply all accumulated changes to the code.
    codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
}
 
Example 12
Source File: DuplicateInitializerInvocationFixer.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
{
    if (constantInstruction.opcode == InstructionConstants.OP_INVOKESPECIAL)
    {
        hasBeenFixed = false;
        clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);

        if (hasBeenFixed)
        {
            Instruction extraInstruction =
                new SimpleInstruction(InstructionConstants.OP_ICONST_0);

            codeAttributeEditor.insertBeforeInstruction(offset,
                                                        extraInstruction);

            if (DEBUG)
            {
                System.out.println("  ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] Inserting "+extraInstruction.toString()+" before "+constantInstruction.toString(offset));
            }

            if (extraAddedInstructionVisitor != null)
            {
                extraInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor);
            }
        }
    }
}
 
Example 13
Source File: ReachableCodeMarker.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Marks the code starting at the given offset.
 */
private void markCode(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset)
{
    boolean oldNext = next;

    byte[] code = codeAttribute.code;

    // Continue with the current instruction as long as we haven't marked it
    // yet.
    while (!isReachable[offset])
    {
        // Get the current instruction.
        Instruction instruction = InstructionFactory.create(code, offset);

        // Mark it as reachable.
        isReachable[offset] = true;

        // By default, we'll assume we can continue with the next
        // instruction in a moment.
        next = true;

        // Mark the branch targets, if any.
        instruction.accept(clazz, method, codeAttribute, offset, this);

        // Can we really continue with the next instruction?
        if (!next)
        {
            break;
        }

        // Go to the next instruction.
        offset += instruction.length(offset);
    }

    next = oldNext;
}
 
Example 14
Source File: DynamicMemberReferenceInitializer.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Tries to match the next instruction and fills out the string constant
 * or prints out a note accordingly.
 */
private void matchGetMember(Clazz clazz,
                            Method                     method,
                            CodeAttribute codeAttribute,
                            int                        offset,
                            Instruction instruction,
                            InstructionSequenceMatcher constantSequenceMatcher,
                            InstructionSequenceMatcher variableSequenceMatcher,
                            boolean                    isField,
                            boolean                    isDeclared,
                            String                     defaultName,
                            String                     defaultDescriptor)
{
    if (constantSequenceMatcher != null)
    {
        // Try to match the next instruction in the constant sequence.
        instruction.accept(clazz, method, codeAttribute, offset,
                           constantSequenceMatcher);

        // Did we find a match to fill out the string constant?
        if (constantSequenceMatcher.isMatching())
        {
            initializeStringReference(clazz,
                                      constantSequenceMatcher,
                                      isField,
                                      isDeclared,
                                      defaultDescriptor);

            // Don't look for the dynamic construct.
            variableSequenceMatcher.reset();
        }
    }

    // Try to match the next instruction in the variable sequence.
    instruction.accept(clazz, method, codeAttribute, offset,
                       variableSequenceMatcher);

    // Did we find a match to print out a note?
    if (variableSequenceMatcher.isMatching())
    {
        // Print out a note about the dynamic invocation.
        printDynamicInvocationNote(clazz,
                                   variableSequenceMatcher,
                                   isField,
                                   isDeclared,
                                   defaultName,
                                   defaultDescriptor);
    }
}
 
Example 15
Source File: InstructionSequenceMatcher.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
private void checkMatch(boolean       condition,
                        Clazz         clazz,
                        Method        method,
                        CodeAttribute codeAttribute,
                        int           offset,
                        Instruction   instruction)
{
    if (DEBUG_MORE)
    {
        System.out.println("InstructionSequenceMatcher: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]: "+patternInstructions[patternInstructionIndex].toString(patternInstructionIndex)+(condition?"\t== ":"\t   ")+instruction.toString(offset));
    }

    // Did the instruction match?
    if (condition)
    {
        // Remember the offset of the matching instruction.
        matchedInstructionOffsets[patternInstructionIndex] = offset;

        // Try to match the next instruction next time.
        patternInstructionIndex++;

        // Did we match all instructions in the sequence?
        matching = patternInstructionIndex == patternInstructions.length;

        // Did we match any wildcards along the way?
        matchingAnyWildCards = matchedArgumentFlags != 0;

        if (matching)
        {
            if (DEBUG)
            {
                System.out.println("InstructionSequenceMatcher: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]");
                for (int index = 0; index < patternInstructionIndex; index++)
                {
                    System.out.println("    "+ InstructionFactory.create(codeAttribute.code, matchedInstructionOffsets[index]).toString(matchedInstructionOffsets[index]));
                }
            }

            // Start matching from the first instruction again next time.
            reset();
        }
    }
    else
    {
        // The instruction didn't match.
        matching = false;

        // Is this a failed second instruction?
        boolean retry = patternInstructionIndex == 1;

        // Start matching from the first instruction next time.
        reset();

        // Retry a failed second instruction as a first instruction.
        if (retry)
        {
            instruction.accept(clazz, method, codeAttribute, offset, this);
        }
    }
}
 
Example 16
Source File: CodeAttributeComposer.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
     * Wraps up the current code fragment, continuing with the previous one on
     * the stack.
     */
    public void endCodeFragment()
    {
        if (level < 0)
        {
            throw new IllegalArgumentException("Code fragment not begun ["+level+"]");
        }

        // Remap the instructions of the code fragment.
        int instructionOffset = codeFragmentOffsets[level];
        while (instructionOffset < codeLength)
        {
            // Get the next instruction.
            Instruction instruction = InstructionFactory.create(code, instructionOffset);

            // Does this instruction still have to be remapped?
            if (oldInstructionOffsets[instructionOffset] >= 0)
            {
                // Adapt the instruction for its new offset.
                instruction.accept(null, null, null, instructionOffset, this);

                // Write the instruction back.
//                instruction.accept(null,
//                                   null,
//                                   new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
//                                   instructionOffset,
//                                   instructionWriter);
                instruction.write(code, instructionOffset);

                // Don't remap this instruction again.
                oldInstructionOffsets[instructionOffset] = -1;
            }

            // Continue remapping at the next instruction offset.
            instructionOffset += instruction.length(instructionOffset);
        }

        // Correct the estimated maximum code length, now that we know the
        // actual length of this code fragment.
        maximumCodeLength += codeLength - codeFragmentOffsets[level] -
                             codeFragmentLengths[level];

        // Try to remap the exception handlers that couldn't be remapped before.
        if (allowExternalExceptionHandlers)
        {
            for (int index = 0; index < exceptionTableLength; index++)
            {
                ExceptionInfo exceptionInfo = exceptionTable[index];

                // Unmapped exception handlers are still negated.
                int handlerPC = -exceptionInfo.u2handlerPC;
                if (handlerPC > 0)
                {
                    if (remappableInstructionOffset(handlerPC))
                    {
                        exceptionInfo.u2handlerPC = remapInstructionOffset(handlerPC);
                    }
                    else if (level == 0)
                    {
                        throw new IllegalStateException("Couldn't remap exception handler offset ["+handlerPC+"]");
                    }
                }
            }
        }

        level--;
    }
 
Example 17
Source File: CodeAttributeEditor.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Moves the given instruction to its new offset.
 * @param clazz         the class file of the code to be changed.
 * @param method        the method of the code to be changed.
 * @param codeAttribute the code to be changed.
 * @param oldOffset     the original instruction offset.
 * @param instruction   the original instruction.
 */
private void moveInstruction(Clazz         clazz,
                             Method        method,
                             CodeAttribute codeAttribute,
                             int           oldOffset,
                             Instruction   instruction)
{
    // Remap and insert the pre-inserted instruction, if any.
    Instruction preInstruction = preInsertions[oldOffset];
    if (preInstruction != null)
    {
        if (DEBUG)
        {
            System.out.println("  Pre-inserted  "+preInstruction.toString(newOffset));
        }

        // Remap the instruction.
        preInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
    }

    // Remap and insert the replacement instruction, or the current
    // instruction, if it shouldn't be deleted.
    Instruction replacementInstruction = replacements[oldOffset];
    if (replacementInstruction != null)
    {
        if (DEBUG)
        {
            System.out.println("  Replaced      "+replacementInstruction.toString(newOffset));
        }
        // Remap the instruction.
        replacementInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
    }
    else if (!deleted[oldOffset])
    {
        if (DEBUG)
        {
            System.out.println("  Copied        "+instruction.toString(newOffset));
        }

        // Remap the instruction.
        instruction.accept(clazz, method, codeAttribute, oldOffset, this);
    }

    // Remap and insert the post-inserted instruction, if any.
    Instruction postInstruction = postInsertions[oldOffset];
    if (postInstruction != null)
    {
        if (DEBUG)
        {
            System.out.println("  Post-inserted "+postInstruction.toString(newOffset));
        }

        // Remap the instruction.
        postInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
    }
}
 
Example 18
Source File: GsonDeserializationInvocationFinder.java    From proguard with GNU General Public License v2.0 4 votes vote down vote up
@Override
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
    // Try to match any of the fromJson() constructs.
    FromJsonInvocationMatcher matchingMatcher = null;
    for (FromJsonInvocationMatcher matcher : fromJsonInvocationMatchers)
    {
        instruction.accept(clazz,
                           method,
                           codeAttribute,
                           offset,
                           matcher);
        if(matcher.isMatching())
        {
            matchingMatcher = matcher;
            break;
        }
    }

    if (matchingMatcher != null)
    {
        if (DEBUG)
        {
            System.out.println("GsonDeserializationInvocationFinder: Gson#fromJson: " +
                               clazz.getName() +
                               "." +
                               method.getName(clazz) +
                               method.getDescriptor(clazz) +
                               " " +
                               instruction.toString(offset));
        }

        // Figure out the type that is being deserialized.
        lazyPartialEvaluator.visitCodeAttribute(clazz,
                                                method,
                                                codeAttribute);

        // Derive types from Class or Type argument.
        int stackElementIndex = matchingMatcher.typeStackElementIndex == -1 ?
            matchingMatcher.classStackElementIndex :
            matchingMatcher.typeStackElementIndex;
        InstructionOffsetValue producer =
            partialEvaluator.getStackBefore(offset)
                            .getTopActualProducerValue(stackElementIndex)
                            .instructionOffsetValue();

        TypeArgumentFinder typeArgumentFinder =
            new TypeArgumentFinder(programClassPool,
                                   libraryClassPool,
                                   partialEvaluator);
        for (int i = 0; i < producer.instructionOffsetCount(); i++)
        {
            codeAttribute.instructionAccept(clazz,
                                            method,
                                            producer.instructionOffset(i),
                                            typeArgumentFinder);
        }

        String[] targetTypes = typeArgumentFinder.typeArgumentClasses;
        if (targetTypes != null)
        {
            for (String targetType : targetTypes)
            {
                if(DEBUG)
                {
                    System.out.println("GsonDeserializationInvocationFinder: deserialized type: " +
                                       targetType);
                }
                programClassPool.classAccept(targetType, domainClassVisitor);
            }
        }
        else if (warningPrinter != null)
        {
            warningPrinter.print(clazz.getName(),
                                 "Warning: can't derive deserialized type from fromJson() invocation in " +
                                 clazz.getName() +
                                 "." +
                                 method.getName(clazz) +
                                 method.getDescriptor(clazz));
        }
    }
}
 
Example 19
Source File: CodeAttribute.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Applies the given instruction visitor to the instruction at the specified
 * offset.
 */
public void instructionAccept(Clazz clazz, Method method, int offset, InstructionVisitor instructionVisitor)
{
    Instruction instruction = InstructionFactory.create(code, offset);
    instruction.accept(clazz, method, this, offset, instructionVisitor);
}
 
Example 20
Source File: CodeSubroutineInliner.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
    branchTargetFinder.visitCodeAttribute(clazz, method, codeAttribute);

    // Don't bother if there aren't any subroutines anyway.
    if (!containsSubroutines(codeAttribute))
    {
        return;
    }

    if (DEBUG)
    {
        System.out.println("SubroutineInliner: processing ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]");
    }

    // Append the body of the code.
    codeAttributeComposer.reset();
    codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);

    // Copy the non-subroutine instructions.
    int offset  = 0;
    while (offset < codeAttribute.u4codeLength)
    {
        Instruction instruction = InstructionFactory.create(codeAttribute.code, offset);
        int instructionLength = instruction.length(offset);

        // Is this returning subroutine?
        if (branchTargetFinder.isSubroutine(offset) &&
            branchTargetFinder.isSubroutineReturning(offset))
        {
            // Skip the subroutine.
            if (DEBUG)
            {
                System.out.println("  Skipping original subroutine instruction "+instruction.toString(offset));
            }

            // Append a label at this offset instead.
            codeAttributeComposer.appendLabel(offset);
        }
        else
        {
            // Copy the instruction, inlining any subroutine call recursively.
            instruction.accept(clazz, method, codeAttribute, offset, this);
        }

        offset += instructionLength;
    }

    // Copy the exceptions. Note that exceptions with empty try blocks
    // are automatically removed.
    codeAttribute.exceptionsAccept(clazz,
                                   method,
                                   subroutineExceptionInliner);

    if (DEBUG)
    {
        System.out.println("  Appending label after code at ["+offset+"]");
    }

    // Append a label just after the code.
    codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);

    // End and update the code attribute.
    codeAttributeComposer.endCodeFragment();
    codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
}