proguard.evaluation.TracedStack Java Examples

The following examples show how to use proguard.evaluation.TracedStack. 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: EvaluationShrinker.java    From bazel with Apache License 2.0 6 votes vote down vote up
/**
 * Marks the stack entries and their producing instructions of the
 * consumer at the given offset.
 * @param clazz          the containing class.
 * @param consumerOffset the offset of the consumer.
 * @param consumer       the consumer of the stack entries.
 */
private void markStackProducers(Clazz       clazz,
                                int         consumerOffset,
                                Instruction consumer)
{
    TracedStack tracedStack =
        partialEvaluator.getStackBefore(consumerOffset);

    int stackSize = tracedStack.size();

    // Mark the producers of the popped values.
    int popCount = consumer.stackPopCount(clazz);
    for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
    {
        markStackEntryProducers(consumerOffset, stackIndex);
    }
}
 
Example #2
Source File: EvaluationShrinker.java    From proguard with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Marks the stack entries and their producing instructions of the
 * consumer at the given offset.
 * @param clazz          the containing class.
 * @param consumerOffset the offset of the consumer.
 * @param consumer       the consumer of the stack entries.
 */
private void markStackProducers(Clazz       clazz,
                                int         consumerOffset,
                                Instruction consumer)
{
    TracedStack tracedStack =
        partialEvaluator.getStackBefore(consumerOffset);

    int stackSize = tracedStack.size();

    // Mark the producers of the popped values.
    int popCount = consumer.stackPopCount(clazz);
    for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++)
    {
        markStackEntryProducers(consumerOffset, stackIndex);
    }
}
 
Example #3
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 6 votes vote down vote up
/**
 * Evaluates the instruction block and the exception handlers covering the
 * given instruction range in the given code.
 */
private void evaluateInstructionBlockAndExceptionHandlers(Clazz           clazz,
                                                          Method          method,
                                                          CodeAttribute codeAttribute,
                                                          TracedVariables variables,
                                                          TracedStack     stack,
                                                          int             startOffset,
                                                          int             endOffset)
{
    evaluateInstructionBlock(clazz,
                             method,
                             codeAttribute,
                             variables,
                             stack,
                             startOffset);

    evaluateExceptionHandlers(clazz,
                              method,
                              codeAttribute,
                              startOffset,
                              endOffset);
}
 
Example #4
Source File: EvaluationShrinker.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Marks the stack entry and the corresponding producing instructions
 * of the consumer at the given offset.
 * @param consumerOffset the offset of the consumer.
 * @param stackIndex     the index of the stack entry to be marked
 *                        (counting from the top).
 */
private void markStackEntryProducers(int consumerOffset,
                                     int stackIndex)
{
    TracedStack tracedStack =
        partialEvaluator.getStackBefore(consumerOffset);

    int stackBottomIndex = tracedStack.size() - 1 - stackIndex;

    if (!isStackSimplifiedBefore(consumerOffset, stackBottomIndex))
    {
        markStackEntryProducers(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(),
                                stackBottomIndex);
    }
}
 
Example #5
Source File: EvaluationShrinker.java    From bazel with Apache License 2.0 5 votes vote down vote up
/**
 * Returns whether the specified stack entry before the given offset is
 * present.
 * @param instructionOffset the offset of the stack entry to be checked.
 * @param stackIndex        the index of the stack entry to be checked
 *                          (counting from the bottom).
 */
private boolean isStackEntryPresentBefore(int instructionOffset,
                                          int stackIndex)
{
    TracedStack tracedStack =
        partialEvaluator.getStackBefore(instructionOffset);

    InstructionOffsetValue producerOffsets =
        tracedStack.getBottomProducerValue(stackIndex).instructionOffsetValue();

    return isAnyStackEntryNecessaryAfter(producerOffsets, stackIndex);
}
 
Example #6
Source File: EvaluationShrinker.java    From bazel with Apache License 2.0 5 votes vote down vote up
/**
 * Marks the stack entry and its initializing instruction
 * ('invokespecial *.<init>') for the given 'new' instruction offset.
 * @param newInstructionOffset the offset of the 'new' instruction.
 */
private void markInitialization(int newInstructionOffset)
{
    int initializationOffset =
        partialEvaluator.initializationOffset(newInstructionOffset);

    TracedStack tracedStack =
        partialEvaluator.getStackAfter(newInstructionOffset);

    markStackEntryAfter(initializationOffset, tracedStack.size() - 1);
    markInstruction(initializationOffset);
}
 
Example #7
Source File: EvaluationShrinker.java    From bazel with Apache License 2.0 5 votes vote down vote up
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
    // Get the total size of the parameters.
    int parameterSize = ParameterUsageMarker.getParameterSize(programMethod);

    // Make the method invocation static, if possible.
    if ((programMethod.getAccessFlags() & ClassConstants.ACC_STATIC) == 0 &&
        !ParameterUsageMarker.isParameterUsed(programMethod, 0))
    {
        replaceByStaticInvocation(programClass,
                                  invocationOffset,
                                  invocationInstruction);
    }

    // Remove unused parameters.
    for (int index = 0; index < parameterSize; index++)
    {
        if (!ParameterUsageMarker.isParameterUsed(programMethod, index))
        {
            TracedStack stack =
                partialEvaluator.getStackBefore(invocationOffset);

            int stackIndex = stack.size() - parameterSize + index;

            if (DEBUG)
            {
                System.out.println("  ["+invocationOffset+"] Ignoring parameter #"+index+" of "+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] (stack entry #"+stackIndex+" ["+stack.getBottom(stackIndex)+"])");
                System.out.println("    Full stack: "+stack);
            }

            markStackSimplificationBefore(invocationOffset, stackIndex);
        }
    }
}
 
Example #8
Source File: EvaluationShrinker.java    From proguard with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns whether the specified stack entry before the given offset is
 * present.
 * @param instructionOffset the offset of the stack entry to be checked.
 * @param stackIndex        the index of the stack entry to be checked
 *                          (counting from the bottom).
 */
private boolean isStackEntryPresentBefore(int instructionOffset,
                                          int stackIndex)
{
    TracedStack tracedStack =
        partialEvaluator.getStackBefore(instructionOffset);

    InstructionOffsetValue producerOffsets =
        tracedStack.getBottomProducerValue(stackIndex).instructionOffsetValue();

    return isAnyStackEntryNecessaryAfter(producerOffsets, stackIndex);
}
 
Example #9
Source File: EvaluationShrinker.java    From proguard with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Marks the stack entry and its initializing instruction
 * ('invokespecial *.<init>') for the given 'new' instruction offset.
 * @param newInstructionOffset the offset of the 'new' instruction.
 */
private void markInitialization(int newInstructionOffset)
{
    int initializationOffset =
        partialEvaluator.initializationOffset(newInstructionOffset);

    TracedStack tracedStack =
        partialEvaluator.getStackAfter(newInstructionOffset);

    markStackEntryAfter(initializationOffset, tracedStack.size() - 1);
    markInstruction(initializationOffset);
}
 
Example #10
Source File: EvaluationShrinker.java    From proguard with GNU General Public License v2.0 5 votes vote down vote up
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
    // Get the total size of the parameters.
    int parameterSize = ParameterUsageMarker.getParameterSize(programMethod);

    // Make the method invocation static, if possible.
    if ((programMethod.getAccessFlags() & ClassConstants.ACC_STATIC) == 0 &&
        !ParameterUsageMarker.isParameterUsed(programMethod, 0))
    {
        replaceByStaticInvocation(programClass,
                                  invocationOffset,
                                  invocationInstruction);
    }

    // Remove unused parameters.
    for (int index = 0; index < parameterSize; index++)
    {
        if (!ParameterUsageMarker.isParameterUsed(programMethod, index))
        {
            TracedStack stack =
                partialEvaluator.getStackBefore(invocationOffset);

            int stackIndex = stack.size() - parameterSize + index;

            if (DEBUG)
            {
                System.out.println("  ["+invocationOffset+"] Ignoring parameter #"+index+" of "+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] (stack entry #"+stackIndex+" ["+stack.getBottom(stackIndex)+"])");
                System.out.println("    Full stack: "+stack);
            }

            markStackSimplificationBefore(invocationOffset, stackIndex);
        }
    }
}
 
Example #11
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
private MyInstructionBlock(TracedVariables variables,
                           TracedStack     stack,
                           int             startOffset)
{
    this.variables   = variables;
    this.stack       = stack;
    this.startOffset = startOffset;
}
 
Example #12
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Evaluates a block of instructions, starting at the given offset and ending
 * at a branch instruction, a return instruction, or a throw instruction.
 */
private void evaluateInstructionBlock(Clazz           clazz,
                                      Method          method,
                                      CodeAttribute codeAttribute,
                                      TracedVariables variables,
                                      TracedStack     stack,
                                      int             startOffset)
{
    // Execute the initial instruction block.
    evaluateSingleInstructionBlock(clazz,
                                   method,
                                   codeAttribute,
                                   variables,
                                   stack,
                                   startOffset);

    // Execute all resulting instruction blocks on the execution stack.
    while (!instructionBlockStack.empty())
    {
        if (DEBUG) System.out.println("Popping alternative branch out of "+instructionBlockStack.size()+" blocks");

        MyInstructionBlock instructionBlock =
            (MyInstructionBlock)instructionBlockStack.pop();

        evaluateSingleInstructionBlock(clazz,
                                       method,
                                       codeAttribute,
                                       instructionBlock.variables,
                                       instructionBlock.stack,
                                       instructionBlock.startOffset);
    }
}
 
Example #13
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Pushes block of instructions to be executed in this partial evaluator.
 */
private void pushInstructionBlock(TracedVariables variables,
                                  TracedStack     stack,
                                  int             startOffset)
{
    instructionBlockStack.push(new MyInstructionBlock(variables,
                                                      stack,
                                                      startOffset));
}
 
Example #14
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Pushes block of instructions to be executed in the calling partial
 * evaluator.
 */
private void pushCallingInstructionBlock(TracedVariables variables,
                                         TracedStack     stack,
                                         int             startOffset)
{
    callingInstructionBlockStack.push(new MyInstructionBlock(variables,
                                                             stack,
                                                             startOffset));
}
 
Example #15
Source File: EvaluationShrinker.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Marks the stack entry and its initializing instruction
 * ('invokespecial *.<init>') for the given 'new' instruction offset.
 * @param newInstructionOffset the offset of the 'new' instruction.
 */
private void markInitialization(int newInstructionOffset)
{
    int initializationOffset =
        partialEvaluator.initializationOffset(newInstructionOffset);

    TracedStack tracedStack =
        partialEvaluator.getStackAfter(newInstructionOffset);

    markStackEntryAfter(initializationOffset, tracedStack.size() - 1);
    markInstruction(initializationOffset);
}
 
Example #16
Source File: EvaluationShrinker.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
    // Get the total size of the parameters.
    int parameterSize = ParameterUsageMarker.getParameterSize(programMethod);

    // Make the method invocation static, if possible.
    if ((programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) == 0 &&
        !ParameterUsageMarker.isParameterUsed(programMethod, 0))
    {
        replaceByStaticInvocation(programClass,
                                  invocationOffset,
                                  invocationInstruction);
    }

    // Remove unused parameters.
    for (int index = 0; index < parameterSize; index++)
    {
        if (!ParameterUsageMarker.isParameterUsed(programMethod, index))
        {
            TracedStack stack =
                partialEvaluator.getStackBefore(invocationOffset);

            int stackIndex = stack.size() - parameterSize + index;

            if (DEBUG)
            {
                System.out.println("  ["+invocationOffset+"] Ignoring parameter #"+index+" of "+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] (stack entry #"+stackIndex+" ["+stack.getBottom(stackIndex)+"])");
                System.out.println("    Full stack: "+stack);
            }

            markStackSimplificationBefore(invocationOffset, stackIndex);
        }
    }
}
 
Example #17
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
    {
        int startPC = exceptionInfo.u2startPC;
        int endPC   = exceptionInfo.u2endPC;

        // Do we have to evaluate this exception catch block?
        if (isTraced(startPC, endPC))
        {
            int handlerPC = exceptionInfo.u2handlerPC;
            int catchType = exceptionInfo.u2catchType;

            if (DEBUG) System.out.println("Evaluating exception ["+startPC +" -> "+endPC +": "+handlerPC+"]:");

            // Reuse the existing variables and stack objects, ensuring the
            // right size.
            TracedVariables variables = new TracedVariables(codeAttribute.u2maxLocals);
            TracedStack     stack     = new TracedStack(codeAttribute.u2maxStack);

            // Initialize the trace values.
            Value storeValue = new InstructionOffsetValue(AT_CATCH_ENTRY);
            variables.setProducerValue(storeValue);
            stack.setProducerValue(storeValue);

            // Initialize the variables by generalizing the variables of the
            // try block. Make sure to include the results of the last
            // instruction for preverification.
            generalizeVariables(startPC,
                                endPC,
                                evaluateAllCode,
                                variables);

            // Initialize the the stack.
            //stack.push(valueFactory.createReference((ClassConstant)((ProgramClass)clazz).getConstant(exceptionInfo.u2catchType), false));
            String catchClassName = catchType != 0 ?
                 clazz.getClassName(catchType) :
                 ClassConstants.INTERNAL_NAME_JAVA_LANG_THROWABLE;

            Clazz catchClass = catchType != 0 ?
                ((ClassConstant)((ProgramClass)clazz).getConstant(catchType)).referencedClass :
                null;

            stack.push(valueFactory.createReferenceValue(catchClassName,
                                                         catchClass,
                                                         false));

            int evaluationCount = evaluationCounts[handlerPC];

            // Evaluate the instructions, starting at the entry point.
            evaluateInstructionBlock(clazz,
                                     method,
                                     codeAttribute,
                                     variables,
                                     stack,
                                     handlerPC);

            // Remember to evaluate all exception handlers once more.
            if (!evaluateExceptions)
            {
                evaluateExceptions = evaluationCount < evaluationCounts[handlerPC];
            }
        }
//        else if (evaluateAllCode)
//        {
//            if (DEBUG) System.out.println("No information for partial evaluation of exception ["+startPC +" -> "+endPC +": "+exceptionInfo.u2handlerPC+"] yet");
//
//            // We don't have any information on the try block yet, but we do
//            // have to evaluate the exception handler.
//            // Remember to evaluate all exception handlers once more.
//            evaluateExceptions = true;
//        }
        else
        {
            if (DEBUG) System.out.println("No information for partial evaluation of exception ["+startPC +" -> "+endPC +": "+exceptionInfo.u2handlerPC+"]");
        }
    }
 
Example #18
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Initializes the data structures for the variables, stack, etc.
 */
private void initializeArrays(CodeAttribute codeAttribute)
{
    int codeLength = codeAttribute.u4codeLength;

    // Create new arrays for storing information at each instruction offset.
    if (variablesAfter.length < codeLength)
    {
        // Create new arrays.
        branchOriginValues  = new InstructionOffsetValue[codeLength];
        branchTargetValues  = new InstructionOffsetValue[codeLength];
        variablesBefore     = new TracedVariables[codeLength];
        stacksBefore        = new TracedStack[codeLength];
        variablesAfter      = new TracedVariables[codeLength];
        stacksAfter         = new TracedStack[codeLength];
        generalizedContexts = new boolean[codeLength];
        evaluationCounts    = new int[codeLength];
    }
    else
    {
        // Reset the arrays.
        for (int index = 0; index < codeLength; index++)
        {
            branchOriginValues[index]   = null;
            branchTargetValues[index]   = null;
            generalizedContexts[index]  = false;
            evaluationCounts[index]     = 0;

            if (variablesBefore[index] != null)
            {
                variablesBefore[index].reset(codeAttribute.u2maxLocals);
            }

            if (stacksBefore[index] != null)
            {
                stacksBefore[index].reset(codeAttribute.u2maxStack);
            }

            if (variablesAfter[index] != null)
            {
                variablesAfter[index].reset(codeAttribute.u2maxLocals);
            }

            if (stacksAfter[index] != null)
            {
                stacksAfter[index].reset(codeAttribute.u2maxStack);
            }
        }
    }
}
 
Example #19
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Evaluates a subroutine and its exception handlers, starting at the given
 * offset and ending at a subroutine return instruction.
 */
private void evaluateSubroutine(Clazz           clazz,
                                Method          method,
                                CodeAttribute codeAttribute,
                                TracedVariables variables,
                                TracedStack     stack,
                                int             subroutineStart,
                                java.util.Stack instructionBlockStack)
{
    int subroutineEnd = branchTargetFinder.subroutineEnd(subroutineStart);

    if (DEBUG) System.out.println("Evaluating subroutine from "+subroutineStart+" to "+subroutineEnd);

    PartialEvaluator subroutinePartialEvaluator = this;

    // Create a temporary partial evaluator if necessary.
    if (evaluationCounts[subroutineStart] > 0)
    {
        if (DEBUG) System.out.println("Creating new partial evaluator for subroutine");

        subroutinePartialEvaluator = new PartialEvaluator(this);

        subroutinePartialEvaluator.initializeArrays(codeAttribute);
    }

    // Evaluate the subroutine.
    subroutinePartialEvaluator.evaluateInstructionBlockAndExceptionHandlers(clazz,
                                                                            method,
                                                                            codeAttribute,
                                                                            variables,
                                                                            stack,
                                                                            subroutineStart,
                                                                            subroutineEnd);

    // Merge back the temporary partial evaluator if necessary.
    if (subroutinePartialEvaluator != this)
    {
        generalize(subroutinePartialEvaluator, 0, codeAttribute.u4codeLength);
    }

    if (DEBUG) System.out.println("Ending subroutine from "+subroutineStart+" to "+subroutineEnd);
}
 
Example #20
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the stack after execution of the instruction at the given
 * offset.
 */
public TracedStack getStackAfter(int instructionOffset)
{
    return stacksAfter[instructionOffset];
}
 
Example #21
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the stack before execution of the instruction at the given
 * offset.
 */
public TracedStack getStackBefore(int instructionOffset)
{
    return stacksBefore[instructionOffset];
}
 
Example #22
Source File: PartialEvaluator.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)
{
    // Evaluate the instructions, starting at the entry point.
    if (DEBUG)
    {
        System.out.println();
        System.out.println("Partial evaluation: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
        System.out.println("  Max locals = "+codeAttribute.u2maxLocals);
        System.out.println("  Max stack  = "+codeAttribute.u2maxStack);
    }

    // Reuse the existing variables and stack objects, ensuring the right size.
    TracedVariables variables = new TracedVariables(codeAttribute.u2maxLocals);
    TracedStack     stack     = new TracedStack(codeAttribute.u2maxStack);

    // Initialize the reusable arrays and variables.
    initializeArrays(codeAttribute);
    initializeParameters(clazz, method, codeAttribute, variables);

    // Find all instruction offsets,...
    codeAttribute.accept(clazz, method, branchTargetFinder);

    // Start executing the first instruction block.
    evaluateInstructionBlockAndExceptionHandlers(clazz,
                                                 method,
                                                 codeAttribute,
                                                 variables,
                                                 stack,
                                                 0,
                                                 codeAttribute.u4codeLength);

    if (DEBUG_RESULTS)
    {
        System.out.println("Evaluation results:");

        int offset = 0;
        do
        {
            if (isBranchOrExceptionTarget(offset))
            {
                System.out.println("Branch target from ["+branchOriginValues[offset]+"]:");
                if (isTraced(offset))
                {
                    System.out.println("  Vars:  "+variablesBefore[offset]);
                    System.out.println("  Stack: "+stacksBefore[offset]);
                }
            }

            Instruction instruction = InstructionFactory.create(codeAttribute.code,
                                                                offset);
            System.out.println(instruction.toString(offset));

            if (isTraced(offset))
            {
                int initializationOffset = branchTargetFinder.initializationOffset(offset);
                if (initializationOffset != NONE)
                {
                    System.out.println("     is to be initialized at ["+initializationOffset+"]");
                }

                InstructionOffsetValue branchTargets = branchTargets(offset);
                if (branchTargets != null)
                {
                    System.out.println("     has overall been branching to "+branchTargets);
                }

                System.out.println("  Vars:  "+variablesAfter[offset]);
                System.out.println("  Stack: "+stacksAfter[offset]);
            }

            offset += instruction.length(offset);
        }
        while (offset < codeAttribute.u4codeLength);
    }
}