/** * Creates a new InstructionSequenceReplacer. * @param patternConstants any constants referenced by the pattern * instruction. * @param branchTargetFinder a branch target finder that has been * initialized to indicate branch targets * in the visited code. * @param codeAttributeEditor a code editor that can be used for * accumulating changes to the code. * @param extraInstructionVisitor an optional extra visitor for all deleted * load instructions. */ public InstructionSequenceReplacer(Constant[] patternConstants, Instruction[] patternInstructions, Instruction[] replacementInstructions, BranchTargetFinder branchTargetFinder, CodeAttributeEditor codeAttributeEditor, InstructionVisitor extraInstructionVisitor) { this.instructionSequenceMatcher = new InstructionSequenceMatcher(patternConstants, patternInstructions); this.replacementInstructions = replacementInstructions; this.branchTargetFinder = branchTargetFinder; this.codeAttributeEditor = codeAttributeEditor; this.extraInstructionVisitor = extraInstructionVisitor; }
public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) { Instruction patternInstruction = patternInstructions[patternInstructionIndex]; // Check if the instruction matches the next instruction in the sequence. boolean condition = matchingOpcodes(simpleInstruction, patternInstruction) && matchingArguments(simpleInstruction.constant, ((SimpleInstruction)patternInstruction).constant); // Check if the instruction sequence is matching now. checkMatch(condition, clazz, method, codeAttribute, offset, simpleInstruction); }
/** * Returns whether the matched pattern instructions haven't been modified * before. */ private boolean matchedInstructionsUnmodified() { for (int index = 0; index < instructionSequenceMatcher.instructionCount(); index++) { if (codeAttributeEditor.isModified(instructionSequenceMatcher.matchedInstructionOffset(index))) { return false; } } return true; }
public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) { Instruction patternInstruction = patternInstructions[patternInstructionIndex]; // Check if the instruction matches the next instruction in the from // sequence. boolean condition = matchingOpcodes(branchInstruction, patternInstruction) && matchingBranchOffsets(offset, branchInstruction.branchOffset, ((BranchInstruction)patternInstruction).branchOffset); // Check if the instruction sequence is matching now. checkMatch(condition, clazz, method, codeAttribute, offset, branchInstruction); }
public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) { Instruction patternInstruction = patternInstructions[patternInstructionIndex]; // Check if the instruction matches the next instruction in the sequence. boolean condition = matchingOpcodes(constantInstruction, patternInstruction) && matchingConstantIndices(clazz, constantInstruction.constantIndex, ((ConstantInstruction)patternInstruction).constantIndex) && matchingArguments(constantInstruction.constant, ((ConstantInstruction)patternInstruction).constant); // Check if the instruction sequence is matching now. checkMatch(condition, clazz, method, codeAttribute, offset, constantInstruction); }
int startOffset) final int instructionCount = arrayPreStoreMatcher.instructionCount(); arrayPreStoreMatcher.reset(); for (int count = 0, offset = startOffset; count < instructionCount && offset < codeAttribute.u4codeLength; if (arrayPreStoreMatcher.isMatching()) return arrayPreStoreMatcher.matchedInstructionOffset(instructionCount - 1);
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { // Is the initializer initializing the field? if (codeAttribute.u4codeLength == 10) { INITIALIZER_MATCHER.reset(); codeAttribute.instructionsAccept(clazz, method, INITIALIZER_MATCHER); if (INITIALIZER_MATCHER.isMatching()) { String initializerClassName = clazz.getName(); String fieldClassName = clazz.getClassName(INITIALIZER_MATCHER.matchedConstantIndex(InstructionSequenceMatcher.A)); if (fieldClassName.equals(initializerClassName)) { wrapCounter++; } else { wrapCounter = Integer.MIN_VALUE; } } else { wrapCounter = Integer.MIN_VALUE; } } else { wrapCounter = Integer.MIN_VALUE; } }
public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) { Instruction patternInstruction = patternInstructions[patternInstructionIndex]; // Check if the instruction matches the next instruction in the sequence. boolean condition = matchingOpcodes(lookUpSwitchInstruction, patternInstruction) && matchingBranchOffsets(offset, lookUpSwitchInstruction.defaultOffset, ((LookUpSwitchInstruction)patternInstruction).defaultOffset) && matchingArguments(lookUpSwitchInstruction.cases, ((LookUpSwitchInstruction)patternInstruction).cases) && matchingJumpOffsets(offset, lookUpSwitchInstruction.jumpOffsets, ((LookUpSwitchInstruction)patternInstruction).jumpOffsets); // Check if the instruction sequence is matching now. checkMatch(condition, clazz, method, codeAttribute, offset, lookUpSwitchInstruction); }
public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction) { replacementInstruction = new TableSwitchInstruction(tableSwitchInstruction.opcode, instructionSequenceMatcher.matchedBranchOffset(offset, tableSwitchInstruction.defaultOffset), instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.lowCase), instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.highCase), instructionSequenceMatcher.matchedJumpOffsets(offset, tableSwitchInstruction.jumpOffsets)); }
public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) { replacementInstruction = new LookUpSwitchInstruction(lookUpSwitchInstruction.opcode, instructionSequenceMatcher.matchedBranchOffset(offset, lookUpSwitchInstruction.defaultOffset), instructionSequenceMatcher.matchedArguments(lookUpSwitchInstruction.cases), instructionSequenceMatcher.matchedJumpOffsets(offset, lookUpSwitchInstruction.jumpOffsets)); } }
/** * Returns whether the first whether the first instructions of the * given code attribute match with the given instruction matcher. */ private boolean isDotClassMethodCode(Clazz clazz, Method method, CodeAttribute codeAttribute, InstructionSequenceMatcher codeMatcher, int codeLength) { // Check the minimum code length. if (codeAttribute.u4codeLength < codeLength) { return false; } // Check the actual instructions. codeMatcher.reset(); codeAttribute.instructionsAccept(clazz, method, 0, codeLength, codeMatcher); return codeMatcher.isMatching(); }
public int[] matchedArguments(int[] arguments) { int[] matchedArguments = new int[arguments.length]; for (int index = 0; index < arguments.length; index++) { matchedArguments[index] = matchedArgument(arguments[index]); } return matchedArguments; }
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) { instruction.accept(clazz, method, codeAttribute, offset, invokeMatcher); if (invokeMatcher.isMatching()) { MethodrefConstant methodrefConstant = (MethodrefConstant)((ProgramClass)clazz).getConstant(invokeMatcher.matchedArgument(FIELD_INDEX)); if (ClassConstants.METHOD_NAME_INIT.equals(methodrefConstant.getName(clazz))) { isSuperConstructorCalled |= methodrefConstant.getClassName(clazz).equals(clazz.getSuperName()); } } }
protected Constant matchedConstant(ProgramClass programClass, int argument) { return programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)); }
public int[] matchedJumpOffsets(int offset, int[] jumpOffsets) { int[] matchedJumpOffsets = new int[jumpOffsets.length]; for (int index = 0; index < jumpOffsets.length; index++) { matchedJumpOffsets[index] = matchedBranchOffset(offset, jumpOffsets[index]); } return matchedJumpOffsets; }
public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) { replacementInstruction = new ConstantInstruction(constantInstruction.opcode, instructionSequenceMatcher.matchedConstantIndex(constantInstruction.constantIndex), instructionSequenceMatcher.matchedArgument(constantInstruction.constant)); }
/** * Makes the given label identifier or offset unique for the current * matching instruction sequence. */ private int uniqueLabel(int labelIdentifier) { return labelIdentifier | (instructionSequenceMatcher.matchedInstructionOffset(0) << 8); }
public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) { replacementInstruction = new LookUpSwitchInstruction(lookUpSwitchInstruction.opcode, matchedBranchOffset(offset, lookUpSwitchInstruction.defaultOffset), instructionSequenceMatcher.matchedArguments(lookUpSwitchInstruction.cases), matchedJumpOffsets(offset, lookUpSwitchInstruction.jumpOffsets)); }
/** * Returns the values of the specified matched jump offsets. */ protected int[] matchedJumpOffsets(int offset, int[] jumpOffsets) { // Special cases: are there any labels? for (int index = 0; index < jumpOffsets.length; index++) { if (isLabel(jumpOffsets[index])) { // Then make sure we reference a unique label, because // there may be other matching sequences. jumpOffsets[index] = uniqueLabel(jumpOffsets[index]); } } // Match any other jump offsets. return instructionSequenceMatcher.matchedJumpOffsets(offset, jumpOffsets); }
int startOffset) final int instructionCount = arrayPreStoreMatcher.instructionCount(); arrayPreStoreMatcher.reset(); for (int count = 0, offset = startOffset; count < instructionCount && offset < codeAttribute.u4codeLength; if (arrayPreStoreMatcher.isMatching()) return arrayPreStoreMatcher.matchedInstructionOffset(instructionCount - 1);