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 + -
显示快捷键?