branchtargetfinder.java

来自「proguard 一个java的混淆器」· Java 代码 · 共 689 行 · 第 1/2 页

JAVA
689
字号
        // Initialize the stack of 'new' instruction offsets if this method is        // an instance initializer.        if (method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))        {            recentCreationOffsets[recentCreationOffsetIndex++] = AT_METHOD_ENTRY;        }        // The end of the code is a branch target sentinel.        instructionMarks[codeLength] = BRANCH_TARGET;        // Mark branch targets by going over all instructions.        codeAttribute.instructionsAccept(clazz, method, this);        // Mark branch targets in the exception table.        codeAttribute.exceptionsAccept(clazz, method, this);        // Fill out any gaps in the subroutine starts and the subroutine ends        // and subroutine returning flags, working backward.        // We're not starting in a subroutine.        int     subroutineStart     = NONE;        int     subroutineEnd       = codeLength;        boolean subroutineReturning = false;        for (int index = codeLength - 1; index >= 0; index--)        {            if (isInstruction(index))            {                // Are we inside a previously marked subroutine?                if (subroutineStarts[index] != NONE)                {                    // Update the current subroutine start.                    subroutineStart = subroutineStarts[index];                }                else if (subroutineStart != NONE)                {                    // Mark the subroutine start.                    subroutineStarts[index] = subroutineStart;                }                // Did we reach the start of the subroutine.                if (isSubroutineStart(index))                {                    // Stop marking it.                    subroutineStart = NONE;                }                // Are we inside a subroutine?                if (isSubroutine(index))                {                    // Mark the subroutine end.                    subroutineEnds[index] = subroutineEnd;                    // Update or mark the subroutine returning flag.                    if (isSubroutineReturning(index))                    {                        subroutineReturning = true;                    }                    else if (subroutineReturning)                    {                        instructionMarks[index] |= SUBROUTINE_RETURNING;                    }                }                else                {                    // Update the subroutine end and returning flag.                    subroutineEnd       = index;                    subroutineReturning = false;                }            }        }        if (DEBUG)        {            System.out.println();            System.out.println("Branch targets: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));            for (int index = 0; index < codeLength; index++)            {                if (isInstruction(index))                {                    System.out.println("" +                                       (isBranchOrigin(index)         ? 'B' : '-') +                                       (isBranchTarget(index)         ? 'T' : '-') +                                       (isExceptionStart(index)       ? 'E' : '-') +                                       (isExceptionEnd(index)         ? 'E' : '-') +                                       (isExceptionHandler(index)     ? 'H' : '-') +                                       (isSubroutineInvocation(index) ? 'J' : '-') +                                       (isSubroutineStart(index)      ? 'S' : '-') +                                       (isSubroutineReturning(index)  ? 'r' : '-') +                                       (isSubroutine(index)           ? " ["+subroutineStart(index)+" -> "+subroutineEnd(index)+"] " : " ") +                                       InstructionFactory.create(codeAttribute.code, index).toString(index));                }            }        }    }    // Implementations for InstructionVisitor.    public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)    {        // Mark the instruction.        instructionMarks[offset] |= INSTRUCTION;        // Check if this is the first instruction of a subroutine.        checkSubroutine(offset);        byte opcode = simpleInstruction.opcode;        if (opcode == InstructionConstants.OP_IRETURN ||            opcode == InstructionConstants.OP_LRETURN ||            opcode == InstructionConstants.OP_FRETURN ||            opcode == InstructionConstants.OP_DRETURN ||            opcode == InstructionConstants.OP_ARETURN ||            opcode == InstructionConstants.OP_ATHROW)        {            // Mark the branch origin.            markBranchOrigin(offset);            // Mark the next instruction.            markAfterBranchOrigin(offset + simpleInstruction.length(offset));        }    }    public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)    {        // Mark the instruction.        instructionMarks[offset] |= INSTRUCTION;        // Check if this is the first instruction of a subroutine.        checkSubroutine(offset);        // Check if the instruction is a 'new' instruction.        if (constantInstruction.opcode == InstructionConstants.OP_NEW)        {            // Push the 'new' instruction offset on the stack.            recentCreationOffsets[recentCreationOffsetIndex++] = offset;        }        else        {            // Check if the instruction is an initializer invocation.            isInitializer = false;            clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);            if (isInitializer)            {                // Pop the 'new' instruction offset from the stack.                int recentCreationOffset = recentCreationOffsets[--recentCreationOffsetIndex];                // Fill it out in the creation offsets.                creationOffsets[offset] = recentCreationOffset;                // Fill out the initialization offsets.                if (recentCreationOffset == AT_METHOD_ENTRY)                {                    superInitializationOffset = offset;                }                else                {                    initializationOffsets[recentCreationOffset] = offset;                }            }        }    }    public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)    {        // Mark the instruction.        instructionMarks[offset] |= INSTRUCTION;        // Check if this is the first instruction of a subroutine.        checkSubroutine(offset);        if (variableInstruction.opcode == InstructionConstants.OP_RET)        {            // Mark the branch origin.            markBranchOrigin(offset);            // Mark the regular subroutine return.            instructionMarks[offset] |= SUBROUTINE_RETURNING;            // Mark the next instruction.            markAfterBranchOrigin(offset + variableInstruction.length(offset));        }    }    public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)    {        // Mark the branch origin.        markBranchOrigin(offset);        // Check if this is the first instruction of a subroutine.        checkSubroutine(offset);        // Mark the branch target.        markBranchTarget(offset, branchInstruction.branchOffset);        byte opcode = branchInstruction.opcode;        if (opcode == InstructionConstants.OP_JSR ||            opcode == InstructionConstants.OP_JSR_W)        {            // Mark the subroutine invocation.            instructionMarks[offset] |= SUBROUTINE_INVOCATION;            // Mark the subroutine start.            int targetOffset = offset + branchInstruction.branchOffset;            subroutineStarts[targetOffset] = targetOffset;        }        else if (opcode == InstructionConstants.OP_GOTO ||                 opcode == InstructionConstants.OP_GOTO_W)        {            // Mark the next instruction.            markAfterBranchOrigin(offset + branchInstruction.length(offset));        }    }    public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)    {        // Mark the branch origin.        markBranchOrigin(offset);        // Check if this is the first instruction of a subroutine.        checkSubroutine(offset);        // Mark the branch targets of the default jump offset.        markBranchTarget(offset, switchInstruction.defaultOffset);        // Mark the branch targets of the jump offsets.        markBranchTargets(offset,                          switchInstruction.jumpOffsets);        // Mark the next instruction.        markAfterBranchOrigin(offset + switchInstruction.length(offset));    }    // Implementations for ConstantVisitor.    public void visitAnyConstant(Clazz clazz, Constant constant) {}    public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)    {        isInitializer = methodrefConstant.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT);    }    // Implementations for ExceptionInfoVisitor.    public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)    {        // Mark the exception offsets.        instructionMarks[exceptionInfo.u2startPC]   |= EXCEPTION_START;        instructionMarks[exceptionInfo.u2endPC]     |= EXCEPTION_END;        instructionMarks[exceptionInfo.u2handlerPC] |= EXCEPTION_HANDLER;    }    // Small utility methods.    /**     * Marks the branch targets of the given jump offsets for the instruction     * at the given offset.     */    private void markBranchTargets(int offset, int[] jumpOffsets)    {        for (int index = 0; index < jumpOffsets.length; index++)        {            markBranchTarget(offset, jumpOffsets[index]);        }    }    /**     * Marks the branch origin at the given offset.     */    private void markBranchOrigin(int offset)    {        instructionMarks[offset] |= INSTRUCTION | BRANCH_ORIGIN;    }    /**     * Marks the branch target at the given offset.     */    private void markBranchTarget(int offset, int jumpOffset)    {        int targetOffset = offset + jumpOffset;        instructionMarks[targetOffset] |= BRANCH_TARGET;        // Are we inside a previously marked subroutine?        if (isSubroutine(offset))        {            // Mark the subroutine start of the target.            subroutineStarts[targetOffset] = currentSubroutineStart;            // Update the current subroutine end.            if (currentSubroutineEnd < targetOffset)            {                currentSubroutineEnd = targetOffset;            }        }    }    /**     * Marks the instruction at the given offset, after a branch.     */    private void markAfterBranchOrigin(int nextOffset)    {        instructionMarks[nextOffset] |= AFTER_BRANCH;        // Are we at the end of the current subroutine?        if (currentSubroutineEnd <= nextOffset)        {            // Reset the subroutine start.            currentSubroutineStart = NONE;        }    }    /**     * Checks if the specified instruction is inside a subroutine.     */    private void checkSubroutine(int offset)    {        // Are we inside a previously marked subroutine?        if (isSubroutine(offset))        {            // Update the current subroutine start.            currentSubroutineStart = subroutineStarts[offset];        }        else        {            // Mark the subroutine start (or NONE).            subroutineStarts[offset] = currentSubroutineStart;        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?