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.java182
1 files changed, 151 insertions, 31 deletions
diff --git a/src/proguard/classfile/util/InstructionSequenceMatcher.java b/src/proguard/classfile/util/InstructionSequenceMatcher.java
index 8a689d5..51eb7bc 100644
--- a/src/proguard/classfile/util/InstructionSequenceMatcher.java
+++ b/src/proguard/classfile/util/InstructionSequenceMatcher.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2011 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
@@ -27,6 +27,8 @@ 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
@@ -40,8 +42,8 @@ implements InstructionVisitor,
ConstantVisitor
{
/*
- private static boolean DEBUG = false;
- public static boolean DEBUG_MORE = false;
+ public static boolean DEBUG = true;
+ public static boolean DEBUG_MORE = true;
/*/
private static final boolean DEBUG = false;
private static final boolean DEBUG_MORE = false;
@@ -60,14 +62,15 @@ implements InstructionVisitor,
private final Constant[] patternConstants;
private final Instruction[] patternInstructions;
- private boolean matching;
- private boolean matchingAnyWildCards;
- private int patternInstructionIndex;
- private final int[] matchedInstructionOffsets;
- private int matchedArgumentFlags;
- private final int[] matchedArguments = new int[7];
- private long matchedConstantFlags;
- private final int[] matchedConstantIndices;
+ 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;
@@ -87,6 +90,7 @@ implements InstructionVisitor,
this.patternInstructions = patternInstructions;
matchedInstructionOffsets = new int[patternInstructions.length];
+ matchedConstantFlags = new long[(patternConstants.length + 63) / 64];
matchedConstantIndices = new int[patternConstants.length];
}
@@ -98,34 +102,55 @@ implements InstructionVisitor,
{
patternInstructionIndex = 0;
matchedArgumentFlags = 0;
- matchedConstantFlags = 0L;
- }
+ Arrays.fill(matchedConstantFlags, 0L);
- public boolean isMatching()
- {
- return matching;
+ previousConstantFlags = constantFlags;
+ constantFlags = 0;
}
- public boolean isMatchingAnyWildcards()
+ /**
+ * Returns whether the complete pattern sequence has been matched.
+ */
+ public boolean isMatching()
{
- return matchingAnyWildCards;
+ 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;
@@ -135,6 +160,9 @@ implements InstructionVisitor,
}
+ /**
+ * Returns the values of the specified matched arguments (wildcard or not).
+ */
public int[] matchedArguments(int[] arguments)
{
int[] matchedArguments = new int[arguments.length];
@@ -148,6 +176,9 @@ implements InstructionVisitor,
}
+ /**
+ * Returns the index of the specified matched constant (wildcard or not).
+ */
public int matchedConstantIndex(int constantIndex)
{
int argumentIndex = constantIndex - X;
@@ -157,6 +188,10 @@ implements InstructionVisitor,
}
+ /**
+ * Returns the value of the specified matched branch offset (wildcard or
+ * not).
+ */
public int matchedBranchOffset(int offset, int branchOffset)
{
int argumentIndex = branchOffset - X;
@@ -166,6 +201,10 @@ implements InstructionVisitor,
}
+ /**
+ * 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];
@@ -387,6 +426,35 @@ implements InstructionVisitor,
}
+ 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;
@@ -414,6 +482,18 @@ implements InstructionVisitor,
}
+ 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;
@@ -449,11 +529,10 @@ implements InstructionVisitor,
// Check the literal argument.
return argument1 == argument2;
}
- else if ((matchedArgumentFlags & (1 << argumentIndex)) == 0)
+ else if (!isMatchingArgumentIndex(argumentIndex))
{
- // Store a wildcard argument.
- matchedArguments[argumentIndex] = argument1;
- matchedArgumentFlags |= 1 << argumentIndex;
+ // Store the wildcard argument.
+ setMatchingArgument(argumentIndex, argument1);
return true;
}
@@ -465,6 +544,28 @@ implements InstructionVisitor,
}
+ /**
+ * 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)
{
@@ -491,10 +592,13 @@ implements InstructionVisitor,
{
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 ((matchedConstantFlags & (1L << constantIndex2)) == 0)
+ else if (!isMatchingConstantIndex(constantIndex2))
{
// Check the actual constant.
matchingConstant = false;
@@ -507,8 +611,7 @@ implements InstructionVisitor,
if (matchingConstant)
{
// Store the constant index.
- matchedConstantIndices[constantIndex2] = constantIndex1;
- matchedConstantFlags |= 1L << constantIndex2;
+ setMatchingConstant(constantIndex2, constantIndex1);
}
}
@@ -522,6 +625,27 @@ implements InstructionVisitor,
}
+ /**
+ * 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)
@@ -532,11 +656,10 @@ implements InstructionVisitor,
// Check the literal argument.
return branchOffset1 == branchOffset2;
}
- else if ((matchedArgumentFlags & (1 << argumentIndex)) == 0)
+ else if (!isMatchingArgumentIndex(argumentIndex))
{
// Store a wildcard argument.
- matchedArguments[argumentIndex] = offset + branchOffset1;
- matchedArgumentFlags |= 1 << argumentIndex;
+ setMatchingArgument(argumentIndex, offset + branchOffset1);
return true;
}
@@ -595,9 +718,6 @@ implements InstructionVisitor,
// Did we match all instructions in the sequence?
matching = patternInstructionIndex == patternInstructions.length;
- // Did we match any wildcards along the way?
- matchingAnyWildCards = matchedArgumentFlags != 0;
-
if (matching)
{
if (DEBUG)