summaryrefslogtreecommitdiff
path: root/src/proguard/classfile/util/InstructionSequenceMatcher.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/classfile/util/InstructionSequenceMatcher.java')
-rw-r--r--src/proguard/classfile/util/InstructionSequenceMatcher.java754
1 files changed, 0 insertions, 754 deletions
diff --git a/src/proguard/classfile/util/InstructionSequenceMatcher.java b/src/proguard/classfile/util/InstructionSequenceMatcher.java
deleted file mode 100644
index dc021ee..0000000
--- a/src/proguard/classfile/util/InstructionSequenceMatcher.java
+++ /dev/null
@@ -1,754 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-package proguard.classfile.util;
-
-import proguard.classfile.*;
-import proguard.classfile.attribute.CodeAttribute;
-import proguard.classfile.constant.*;
-import proguard.classfile.constant.visitor.ConstantVisitor;
-import proguard.classfile.instruction.*;
-import proguard.classfile.instruction.visitor.InstructionVisitor;
-
-import java.util.Arrays;
-
-/**
- * This InstructionVisitor checks whether a given pattern instruction sequence
- * occurs in the instructions that are visited. The arguments of the
- * instruction sequence can be wildcards that are matched.
- *
- * @author Eric Lafortune
- */
-public class InstructionSequenceMatcher
-extends SimplifiedVisitor
-implements InstructionVisitor,
- ConstantVisitor
-{
- //*
- private static final boolean DEBUG = false;
- private static final boolean DEBUG_MORE = false;
- /*/
- public static boolean DEBUG = true;
- public static boolean DEBUG_MORE = true;
- //*/
-
- public static final int X = 0x40000000;
- public static final int Y = 0x40000001;
- public static final int Z = 0x40000002;
-
- public static final int A = 0x40000003;
- public static final int B = 0x40000004;
- public static final int C = 0x40000005;
- public static final int D = 0x40000006;
-
-
- private final Constant[] patternConstants;
- private final Instruction[] patternInstructions;
-
- private boolean matching;
- private int patternInstructionIndex;
- private final int[] matchedInstructionOffsets;
- private int matchedArgumentFlags;
- private final int[] matchedArguments = new int[7];
- private final long[] matchedConstantFlags;
- private final int[] matchedConstantIndices;
- private int constantFlags;
- private int previousConstantFlags;
-
- // Fields acting as a parameter and a return value for visitor methods.
- private Constant patternConstant;
- private boolean matchingConstant;
-
-
- /**
- * Creates a new InstructionSequenceMatcher.
- * @param patternConstants any constants referenced by the pattern
- * instruction.
- * @param patternInstructions the pattern instruction sequence.
- */
- public InstructionSequenceMatcher(Constant[] patternConstants,
- Instruction[] patternInstructions)
- {
- this.patternConstants = patternConstants;
- this.patternInstructions = patternInstructions;
-
- matchedInstructionOffsets = new int[patternInstructions.length];
- matchedConstantFlags = new long[(patternConstants.length + 63) / 64];
- matchedConstantIndices = new int[patternConstants.length];
- }
-
-
- /**
- * Starts matching from the first instruction again next time.
- */
- public void reset()
- {
- patternInstructionIndex = 0;
- matchedArgumentFlags = 0;
-
- Arrays.fill(matchedConstantFlags, 0L);
-
- previousConstantFlags = constantFlags;
- constantFlags = 0;
- }
-
-
- /**
- * Returns whether the complete pattern sequence has been matched.
- */
- public boolean isMatching()
- {
- return matching;
- }
-
-
- /**
- * Returns the number of instructions in the pattern sequence.
- */
- public int instructionCount()
- {
- return patternInstructions.length;
- }
-
-
- /**
- * Returns the matched instruction offset of the specified pattern
- * instruction.
- */
- public int matchedInstructionOffset(int index)
- {
- return matchedInstructionOffsets[index];
- }
-
-
- /**
- * Returns whether the specified wildcard argument was a constant from
- * the constant pool in the most recent match.
- */
- public boolean wasConstant(int argument)
- {
- return (previousConstantFlags & (1 << (argument - X))) != 0;
- }
-
-
- /**
- * Returns the value of the specified matched argument (wildcard or not).
- */
- public int matchedArgument(int argument)
- {
- int argumentIndex = argument - X;
- return argumentIndex < 0 ?
- argument :
- matchedArguments[argumentIndex];
- }
-
-
- /**
- * Returns the values of the specified matched arguments (wildcard or not).
- */
- 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;
- }
-
-
- /**
- * Returns the index of the specified matched constant (wildcard or not).
- */
- public int matchedConstantIndex(int constantIndex)
- {
- int argumentIndex = constantIndex - X;
- return argumentIndex < 0 ?
- matchedConstantIndices[constantIndex] :
- matchedArguments[argumentIndex];
- }
-
-
- /**
- * Returns the value of the specified matched branch offset (wildcard or
- * not).
- */
- public int matchedBranchOffset(int offset, int branchOffset)
- {
- int argumentIndex = branchOffset - X;
- return argumentIndex < 0 ?
- branchOffset :
- matchedArguments[argumentIndex] - offset;
- }
-
-
- /**
- * Returns the values of the specified matched jump offsets (wildcard or
- * not).
- */
- 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;
- }
-
-
- // Implementations for InstructionVisitor.
-
- 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);
- }
-
-
- public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
- {
- Instruction patternInstruction = patternInstructions[patternInstructionIndex];
-
- // Check if the instruction matches the next instruction in the sequence.
- boolean condition =
- matchingOpcodes(variableInstruction, patternInstruction) &&
- matchingArguments(variableInstruction.variableIndex,
- ((VariableInstruction)patternInstruction).variableIndex) &&
- matchingArguments(variableInstruction.constant,
- ((VariableInstruction)patternInstruction).constant);
-
- // Check if the instruction sequence is matching now.
- checkMatch(condition,
- clazz,
- method,
- codeAttribute,
- offset,
- variableInstruction);
- }
-
-
- 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);
- }
-
-
- 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 visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
- {
- Instruction patternInstruction = patternInstructions[patternInstructionIndex];
-
- // Check if the instruction matches the next instruction in the sequence.
- boolean condition =
- matchingOpcodes(tableSwitchInstruction, patternInstruction) &&
- matchingBranchOffsets(offset,
- tableSwitchInstruction.defaultOffset,
- ((TableSwitchInstruction)patternInstruction).defaultOffset) &&
- matchingArguments(tableSwitchInstruction.lowCase,
- ((TableSwitchInstruction)patternInstruction).lowCase) &&
- matchingArguments(tableSwitchInstruction.highCase,
- ((TableSwitchInstruction)patternInstruction).highCase) &&
- matchingJumpOffsets(offset,
- tableSwitchInstruction.jumpOffsets,
- ((TableSwitchInstruction)patternInstruction).jumpOffsets);
-
- // Check if the instruction sequence is matching now.
- checkMatch(condition,
- clazz,
- method,
- codeAttribute,
- offset,
- tableSwitchInstruction);
- }
-
-
- 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);
- }
-
-
- // Implementations for ConstantVisitor.
-
- public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
- {
- IntegerConstant integerPatternConstant = (IntegerConstant)patternConstant;
-
- // Compare the integer values.
- matchingConstant = integerConstant.getValue() ==
- integerPatternConstant.getValue();
- }
-
-
- public void visitLongConstant(Clazz clazz, LongConstant longConstant)
- {
- LongConstant longPatternConstant = (LongConstant)patternConstant;
-
- // Compare the long values.
- matchingConstant = longConstant.getValue() ==
- longPatternConstant.getValue();
- }
-
-
- public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
- {
- FloatConstant floatPatternConstant = (FloatConstant)patternConstant;
-
- // Compare the float values.
- matchingConstant = floatConstant.getValue() ==
- floatPatternConstant.getValue();
- }
-
-
- public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
- {
- DoubleConstant doublePatternConstant = (DoubleConstant)patternConstant;
-
- // Compare the double values.
- matchingConstant = doubleConstant.getValue() ==
- doublePatternConstant.getValue();
- }
-
-
- public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
- {
- StringConstant stringPatternConstant = (StringConstant)patternConstant;
-
- // Check the UTF-8 constant.
- matchingConstant =
- matchingConstantIndices(clazz,
- stringConstant.u2stringIndex,
- stringPatternConstant.u2stringIndex);
- }
-
-
- public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
- {
- Utf8Constant utf8PatternConstant = (Utf8Constant)patternConstant;
-
- // Compare the actual strings.
- matchingConstant = utf8Constant.getString().equals(
- utf8PatternConstant.getString());
- }
-
-
- public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
- {
- InvokeDynamicConstant invokeDynamicPatternConstant = (InvokeDynamicConstant)patternConstant;
-
- // Check the bootstrap method and the name and type.
- matchingConstant =
- matchingConstantIndices(clazz,
- invokeDynamicConstant.getBootstrapMethodAttributeIndex(),
- invokeDynamicPatternConstant.getBootstrapMethodAttributeIndex()) &&
- matchingConstantIndices(clazz,
- invokeDynamicConstant.getNameAndTypeIndex(),
- invokeDynamicPatternConstant.getNameAndTypeIndex());
- }
-
-
- public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
- {
- MethodHandleConstant methodHandlePatternConstant = (MethodHandleConstant)patternConstant;
-
- // Check the handle type and the name and type.
- matchingConstant =
- matchingArguments(methodHandleConstant.getReferenceKind(),
- methodHandlePatternConstant.getReferenceKind()) &&
- matchingConstantIndices(clazz,
- methodHandleConstant.getReferenceIndex(),
- methodHandlePatternConstant.getReferenceIndex());
- }
-
-
- public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
- {
- RefConstant refPatternConstant = (RefConstant)patternConstant;
-
- // Check the class and the name and type.
- matchingConstant =
- matchingConstantIndices(clazz,
- refConstant.getClassIndex(),
- refPatternConstant.getClassIndex()) &&
- matchingConstantIndices(clazz,
- refConstant.getNameAndTypeIndex(),
- refPatternConstant.getNameAndTypeIndex());
- }
-
-
- public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
- {
- ClassConstant classPatternConstant = (ClassConstant)patternConstant;
-
- // Check the class name.
- matchingConstant =
- matchingConstantIndices(clazz,
- classConstant.u2nameIndex,
- classPatternConstant.u2nameIndex);
- }
-
-
- public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
- {
- MethodTypeConstant typePatternConstant = (MethodTypeConstant)patternConstant;
-
- // Check the descriptor.
- matchingConstant =
- matchingConstantIndices(clazz,
- methodTypeConstant.u2descriptorIndex,
- typePatternConstant.u2descriptorIndex);
- }
-
-
- public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
- {
- NameAndTypeConstant typePatternConstant = (NameAndTypeConstant)patternConstant;
-
- // Check the name and the descriptor.
- matchingConstant =
- matchingConstantIndices(clazz,
- nameAndTypeConstant.u2nameIndex,
- typePatternConstant.u2nameIndex) &&
- matchingConstantIndices(clazz,
- nameAndTypeConstant.u2descriptorIndex,
- typePatternConstant.u2descriptorIndex);
- }
-
-
- // Small utility methods.
-
- private boolean matchingOpcodes(Instruction instruction1,
- Instruction instruction2)
- {
- // Check the opcode.
- return instruction1.opcode == instruction2.opcode ||
- instruction1.canonicalOpcode() == instruction2.opcode;
- }
-
-
- private boolean matchingArguments(int argument1,
- int argument2)
- {
- int argumentIndex = argument2 - X;
- if (argumentIndex < 0)
- {
- // Check the literal argument.
- return argument1 == argument2;
- }
- else if (!isMatchingArgumentIndex(argumentIndex))
- {
- // Store the wildcard argument.
- setMatchingArgument(argumentIndex, argument1);
-
- return true;
- }
- else
- {
- // Check the previously stored wildcard argument.
- return matchedArguments[argumentIndex] == argument1;
- }
- }
-
-
- /**
- * Marks the specified argument (by index) as matching the specified
- * argument value.
- */
- private void setMatchingArgument(int argumentIndex,
- int argument)
- {
- matchedArguments[argumentIndex] = argument;
- matchedArgumentFlags |= 1 << argumentIndex;
- }
-
-
- /**
- * Returns whether the specified wildcard argument (by index) has been
- * matched.
- */
- private boolean isMatchingArgumentIndex(int argumentIndex)
- {
- return (matchedArgumentFlags & (1 << argumentIndex)) != 0;
- }
-
-
- private boolean matchingArguments(int[] arguments1,
- int[] arguments2)
- {
- if (arguments1.length != arguments2.length)
- {
- return false;
- }
-
- for (int index = 0; index < arguments1.length; index++)
- {
- if (!matchingArguments(arguments1[index], arguments2[index]))
- {
- return false;
- }
- }
-
- return true;
- }
-
-
- private boolean matchingConstantIndices(Clazz clazz,
- int constantIndex1,
- int constantIndex2)
- {
- if (constantIndex2 >= X)
- {
- // Remember that we are trying to match a constant.
- constantFlags |= 1 << (constantIndex2 - X);
-
- // Check the constant index.
- return matchingArguments(constantIndex1, constantIndex2);
- }
- else if (!isMatchingConstantIndex(constantIndex2))
- {
- // Check the actual constant.
- matchingConstant = false;
- patternConstant = patternConstants[constantIndex2];
-
- if (clazz.getTag(constantIndex1) == patternConstant.getTag())
- {
- clazz.constantPoolEntryAccept(constantIndex1, this);
-
- if (matchingConstant)
- {
- // Store the constant index.
- setMatchingConstant(constantIndex2, constantIndex1);
- }
- }
-
- return matchingConstant;
- }
- else
- {
- // Check a previously stored constant index.
- return matchedConstantIndices[constantIndex2] == constantIndex1;
- }
- }
-
-
- /**
- * Marks the specified constant (by index) as matching the specified
- * constant index value.
- */
- private void setMatchingConstant(int constantIndex,
- int constantIndex1)
- {
- matchedConstantIndices[constantIndex] = constantIndex1;
- matchedConstantFlags[constantIndex / 64] |= 1L << constantIndex;
- }
-
-
- /**
- * Returns whether the specified wildcard constant has been matched.
- */
- private boolean isMatchingConstantIndex(int constantIndex)
- {
- return (matchedConstantFlags[constantIndex / 64] & (1L << constantIndex)) != 0;
- }
-
-
- private boolean matchingBranchOffsets(int offset,
- int branchOffset1,
- int branchOffset2)
- {
- int argumentIndex = branchOffset2 - X;
- if (argumentIndex < 0)
- {
- // Check the literal argument.
- return branchOffset1 == branchOffset2;
- }
- else if (!isMatchingArgumentIndex(argumentIndex))
- {
- // Store a wildcard argument.
- setMatchingArgument(argumentIndex, offset + branchOffset1);
-
- return true;
- }
- else
- {
- // Check the previously stored wildcard argument.
- return matchedArguments[argumentIndex] == offset + branchOffset1;
- }
- }
-
-
- private boolean matchingJumpOffsets(int offset,
- int[] jumpOffsets1,
- int[] jumpOffsets2)
- {
- if (jumpOffsets1.length != jumpOffsets2.length)
- {
- return false;
- }
-
- for (int index = 0; index < jumpOffsets1.length; index++)
- {
- if (!matchingBranchOffsets(offset,
- jumpOffsets1[index],
- jumpOffsets2[index]))
- {
- return false;
- }
- }
-
- return true;
- }
-
-
- 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;
-
- 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);
- }
- }
- }
-}