23
23
import proguard.classfile.*;
24
24
import proguard.classfile.attribute.CodeAttribute;
25
import proguard.classfile.constant.Constant;
25
import proguard.classfile.constant.*;
26
26
import proguard.classfile.constant.visitor.ConstantVisitor;
27
import proguard.classfile.editor.CodeAttributeEditor;
27
import proguard.classfile.editor.*;
28
28
import proguard.classfile.instruction.*;
29
29
import proguard.classfile.instruction.visitor.InstructionVisitor;
30
30
import proguard.classfile.util.*;
42
42
implements InstructionVisitor,
46
public static boolean DEBUG = true;
45
48
private static final boolean DEBUG = false;
51
public static final int X = InstructionSequenceMatcher.X;
52
public static final int Y = InstructionSequenceMatcher.Y;
53
public static final int Z = InstructionSequenceMatcher.Z;
55
public static final int A = InstructionSequenceMatcher.A;
56
public static final int B = InstructionSequenceMatcher.B;
57
public static final int C = InstructionSequenceMatcher.C;
58
public static final int D = InstructionSequenceMatcher.D;
60
private static final int BOOLEAN_STRING = 0x1;
61
private static final int CHAR_STRING = 0x2;
62
private static final int INT_STRING = 0x3;
63
private static final int LONG_STRING = 0x4;
64
private static final int FLOAT_STRING = 0x5;
65
private static final int DOUBLE_STRING = 0x6;
66
private static final int STRING_STRING = 0x7;
68
public static final int STRING_A_LENGTH = 0x20000000;
69
public static final int BOOLEAN_A_STRING = 0x20000001;
70
public static final int CHAR_A_STRING = 0x20000002;
71
public static final int INT_A_STRING = 0x20000003;
72
public static final int LONG_A_STRING = 0x20000004;
73
public static final int FLOAT_A_STRING = 0x20000005;
74
public static final int DOUBLE_A_STRING = 0x20000006;
75
public static final int STRING_A_STRING = 0x20000007;
76
public static final int BOOLEAN_B_STRING = 0x20000010;
77
public static final int CHAR_B_STRING = 0x20000020;
78
public static final int INT_B_STRING = 0x20000030;
79
public static final int LONG_B_STRING = 0x20000040;
80
public static final int FLOAT_B_STRING = 0x20000050;
81
public static final int DOUBLE_B_STRING = 0x20000060;
82
public static final int STRING_B_STRING = 0x20000070;
48
85
private final InstructionSequenceMatcher instructionSequenceMatcher;
86
private final Constant[] patternConstants;
49
87
private final Instruction[] replacementInstructions;
50
88
private final BranchTargetFinder branchTargetFinder;
51
89
private final CodeAttributeEditor codeAttributeEditor;
204
243
* Creates the replacement instruction for the given index in the
205
244
* instruction sequence.
207
public Instruction create(int index)
246
public Instruction create(Clazz clazz, int index)
209
248
// Create the instruction.
210
replacementInstructions[index].accept(null,
249
replacementInstructions[index].accept(clazz,
213
252
instructionSequenceMatcher.matchedInstructionOffset(index),
261
302
instructionSequenceMatcher.matchedBranchOffset(offset, tableSwitchInstruction.defaultOffset),
262
303
instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.lowCase),
263
304
instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.highCase),
264
instructionSequenceMatcher.matchedJumpOffsets(offset, tableSwitchInstruction.jumpOffsets));
305
instructionSequenceMatcher.matchedJumpOffsets(offset,
306
tableSwitchInstruction.jumpOffsets));
274
316
instructionSequenceMatcher.matchedArguments(lookUpSwitchInstruction.cases),
275
317
instructionSequenceMatcher.matchedJumpOffsets(offset, lookUpSwitchInstruction.jumpOffsets));
322
* Returns the matched argument for the given pattern argument.
324
private int matchedArgument(Clazz clazz, int argument)
326
// Special case: do we have to compute the string length?
327
if (argument == STRING_A_LENGTH)
329
// Return the string length.
330
return clazz.getStringString(instructionSequenceMatcher.matchedArgument(A)).length();
333
// Otherwise, just return the matched argument.
334
return instructionSequenceMatcher.matchedArgument(argument);
339
* Returns the matched or newly created constant index for the given
340
* pattern constant index.
342
private int matchedConstantIndex(ProgramClass programClass, int constantIndex)
344
// Special case: do we have to create a concatenated string?
345
if (constantIndex >= BOOLEAN_A_STRING &&
346
constantIndex <= (STRING_A_STRING | STRING_B_STRING))
348
// Create a new string constant and return its index.
349
return new ConstantPoolEditor(programClass).addStringConstant(
350
argumentAsString(programClass, constantIndex & 0xf, A) +
351
argumentAsString(programClass, (constantIndex >>> 4) & 0xf, B),
356
int matchedConstantIndex =
357
instructionSequenceMatcher.matchedConstantIndex(constantIndex);
359
// Do we have a matched constant index?
360
if (matchedConstantIndex > 0)
363
return matchedConstantIndex;
366
// Otherwise, we still have to create a new constant.
367
// This currently only works for constants without any wildcards.
368
ProgramClass dummyClass = new ProgramClass();
369
dummyClass.constantPool = patternConstants;
371
return new ConstantAdder(programClass).addConstant(dummyClass, constantIndex);
375
private String argumentAsString(ProgramClass programClass,
382
return Boolean.toString((instructionSequenceMatcher.wasConstant(argument) ?
383
((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
384
instructionSequenceMatcher.matchedArgument(argument)) != 0);
387
return Character.toString((char)(instructionSequenceMatcher.wasConstant(argument) ?
388
((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
389
instructionSequenceMatcher.matchedArgument(argument)));
392
return Integer.toString(instructionSequenceMatcher.wasConstant(argument) ?
393
((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
394
instructionSequenceMatcher.matchedArgument(argument));
397
return Long.toString(instructionSequenceMatcher.wasConstant(argument) ?
398
((LongConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
399
instructionSequenceMatcher.matchedArgument(argument));
402
return Float.toString(instructionSequenceMatcher.wasConstant(argument) ?
403
((FloatConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
404
instructionSequenceMatcher.matchedArgument(argument));
407
return Double.toString(instructionSequenceMatcher.wasConstant(argument) ?
408
((DoubleConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
409
instructionSequenceMatcher.matchedArgument(argument));
413
programClass.getStringString(instructionSequenceMatcher.matchedConstantIndex(argument));