• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 package proguard.classfile.editor;
22 
23 import proguard.classfile.*;
24 import proguard.classfile.attribute.*;
25 import proguard.classfile.attribute.annotation.*;
26 import proguard.classfile.attribute.annotation.target.*;
27 import proguard.classfile.attribute.annotation.target.visitor.*;
28 import proguard.classfile.attribute.annotation.visitor.TypeAnnotationVisitor;
29 import proguard.classfile.attribute.visitor.*;
30 import proguard.classfile.instruction.*;
31 import proguard.classfile.instruction.visitor.InstructionVisitor;
32 import proguard.classfile.util.SimplifiedVisitor;
33 
34 /**
35  * This AttributeVisitor remaps variable indexes in all attributes that it
36  * visits, based on a given index map.
37  *
38  * @author Eric Lafortune
39  */
40 public class VariableRemapper
41 extends      SimplifiedVisitor
42 implements   AttributeVisitor,
43              InstructionVisitor,
44              LocalVariableInfoVisitor,
45              LocalVariableTypeInfoVisitor,
46              TypeAnnotationVisitor,
47              TargetInfoVisitor,
48              LocalVariableTargetElementVisitor
49 {
50     private static final boolean DEBUG = false;
51 
52 
53     private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
54 
55     private int[] variableMap;
56 
57 
58     /**
59      * Sets the given mapping of old variable indexes to their new indexes.
60      * Variables that should disappear can be mapped to -1.
61      */
setVariableMap(int[] variableMap)62     public void setVariableMap(int[] variableMap)
63     {
64         this.variableMap = variableMap;
65     }
66 
67 
68     // Implementations for AttributeVisitor.
69 
visitAnyAttribute(Clazz clazz, Attribute attribute)70     public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
71 
72 
visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)73     public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
74     {
75         // Reorder the array with parameter information.
76         ParameterInfo[] oldParameters = methodParametersAttribute.parameters;
77         ParameterInfo[] newParameters =
78             new ParameterInfo[methodParametersAttribute.u1parametersCount];
79 
80         for (int index = 0; index < methodParametersAttribute.u1parametersCount; index++)
81         {
82             newParameters[remapVariable(index)] = oldParameters[index];
83         }
84 
85         methodParametersAttribute.parameters = newParameters;
86     }
87 
88 
visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)89     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
90     {
91         if (DEBUG)
92         {
93             System.out.println("VariableRemapper: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
94             for (int index= 0; index < codeAttribute.u2maxLocals; index++)
95             {
96                 System.out.println("  v"+index+" -> "+variableMap[index]);
97             }
98         }
99 
100         // Remap the variables of the attributes, before editing the code and
101         // cleaning up its local variable frame.
102         codeAttribute.attributesAccept(clazz, method, this);
103 
104         // Initially, the code attribute editor doesn't contain any changes.
105         codeAttributeEditor.reset(codeAttribute.u4codeLength);
106 
107         // Remap the variables of the instructions.
108         codeAttribute.instructionsAccept(clazz, method, this);
109 
110         // Apply the code atribute editor.
111         codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
112     }
113 
114 
visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)115     public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
116     {
117         // Remap the variable references of the local variables.
118         localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
119     }
120 
121 
visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)122     public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
123     {
124         // Remap the variable references of the local variables.
125         localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
126     }
127 
128 
visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute)129     public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute)
130     {
131         // Remap the variable references of local variable type annotations.
132         typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this);
133     }
134 
135 
136     // Implementations for LocalVariableInfoVisitor.
137 
visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)138     public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
139     {
140         localVariableInfo.u2index =
141             remapVariable(localVariableInfo.u2index);
142     }
143 
144 
145     // Implementations for LocalVariableTypeInfoVisitor.
146 
visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)147     public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
148     {
149         localVariableTypeInfo.u2index =
150             remapVariable(localVariableTypeInfo.u2index);
151     }
152 
153 
154     // Implementations for TypeAnnotationVisitor.
155 
visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)156     public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)
157     {
158         typeAnnotation.targetInfoAccept(clazz, this);
159     }
160 
161 
162     // Implementations for TargetInfoVisitor.
163 
visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo)164     public void visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo) {}
165 
166 
visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)167     public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)
168     {
169         localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this);
170     }
171 
172 
173     // Implementations for LocalVariableTargetElementVisitor.
174 
visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)175     public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)
176     {
177         localVariableTargetElement.u2index  =
178             remapVariable(localVariableTargetElement.u2index);
179     }
180 
181 
182     // Implementations for InstructionVisitor.
183 
visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)184     public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
185 
186 
visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)187     public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
188     {
189         // Is the new variable index different from the original one?
190         int oldVariableIndex = variableInstruction.variableIndex;
191         int newVariableIndex = remapVariable(oldVariableIndex);
192         if (newVariableIndex != oldVariableIndex)
193         {
194             // Replace the instruction.
195             Instruction replacementInstruction =
196                 new VariableInstruction(variableInstruction.opcode,
197                                         newVariableIndex,
198                                         variableInstruction.constant);
199 
200             codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
201         }
202     }
203 
204 
205     // Small utility methods.
206 
207     /**
208      * Returns the new variable index of the given variable.
209      */
remapVariable(int variableIndex)210     private int remapVariable(int variableIndex)
211     {
212         return variableMap[variableIndex];
213     }
214 }
215