• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2009 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.obfuscate;
22 
23 import proguard.classfile.*;
24 import proguard.classfile.attribute.*;
25 import proguard.classfile.attribute.annotation.*;
26 import proguard.classfile.attribute.annotation.visitor.*;
27 import proguard.classfile.attribute.preverification.*;
28 import proguard.classfile.attribute.visitor.*;
29 import proguard.classfile.constant.*;
30 import proguard.classfile.constant.visitor.ConstantVisitor;
31 import proguard.classfile.util.SimplifiedVisitor;
32 import proguard.classfile.visitor.*;
33 
34 /**
35  * This ClassVisitor marks all UTF-8 constant pool entries that are
36  * being used in the program classes it visits.
37  *
38  * @see Utf8Shrinker
39  *
40  * @author Eric Lafortune
41  */
42 public class Utf8UsageMarker
43 extends      SimplifiedVisitor
44 implements   ClassVisitor,
45              MemberVisitor,
46              ConstantVisitor,
47              AttributeVisitor,
48              InnerClassesInfoVisitor,
49              LocalVariableInfoVisitor,
50              LocalVariableTypeInfoVisitor,
51              AnnotationVisitor,
52              ElementValueVisitor
53 {
54     // A visitor info flag to indicate the UTF-8 constant pool entry is being used.
55     private static final Object USED = new Object();
56 
57 
58     // Implementations for ClassVisitor.
59 
visitProgramClass(ProgramClass programClass)60     public void visitProgramClass(ProgramClass programClass)
61     {
62         // Mark the UTF-8 entries referenced by the other constant pool entries.
63         programClass.constantPoolEntriesAccept(this);
64 
65         // Mark the UTF-8 entries referenced by the fields and methods.
66         programClass.fieldsAccept(this);
67         programClass.methodsAccept(this);
68 
69         // Mark the UTF-8 entries referenced by the attributes.
70         programClass.attributesAccept(this);
71     }
72 
73 
74     // Implementations for MemberVisitor.
75 
visitProgramMember(ProgramClass programClass, ProgramMember programMember)76     public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
77     {
78         // Mark the name and descriptor UTF-8 entries.
79         markCpUtf8Entry(programClass, programMember.u2nameIndex);
80         markCpUtf8Entry(programClass, programMember.u2descriptorIndex);
81 
82         // Mark the UTF-8 entries referenced by the attributes.
83         programMember.attributesAccept(programClass, this);
84     }
85 
86 
87     // Implementations for ConstantVisitor.
88 
visitAnyConstant(Clazz clazz, Constant constant)89     public void visitAnyConstant(Clazz clazz, Constant constant) {}
90 
91 
visitStringConstant(Clazz clazz, StringConstant stringConstant)92     public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
93     {
94         markCpUtf8Entry(clazz, stringConstant.u2stringIndex);
95     }
96 
97 
visitClassConstant(Clazz clazz, ClassConstant classConstant)98     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
99     {
100         markCpUtf8Entry(clazz, classConstant.u2nameIndex);
101     }
102 
103 
visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)104     public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
105     {
106         markCpUtf8Entry(clazz, nameAndTypeConstant.u2nameIndex);
107         markCpUtf8Entry(clazz, nameAndTypeConstant.u2descriptorIndex);
108     }
109 
110 
111     // Implementations for AttributeVisitor.
112 
visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)113     public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
114     {
115         // This is the best we can do for unknown attributes.
116         markCpUtf8Entry(clazz, unknownAttribute.u2attributeNameIndex);
117     }
118 
119 
visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)120     public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
121     {
122         markCpUtf8Entry(clazz, sourceFileAttribute.u2attributeNameIndex);
123 
124         markCpUtf8Entry(clazz, sourceFileAttribute.u2sourceFileIndex);
125     }
126 
127 
visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)128     public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
129     {
130         markCpUtf8Entry(clazz, sourceDirAttribute.u2attributeNameIndex);
131 
132         markCpUtf8Entry(clazz, sourceDirAttribute.u2sourceDirIndex);
133     }
134 
135 
visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)136     public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
137     {
138         markCpUtf8Entry(clazz, innerClassesAttribute.u2attributeNameIndex);
139 
140         // Mark the UTF-8 entries referenced by the inner classes.
141         innerClassesAttribute.innerClassEntriesAccept(clazz, this);
142     }
143 
144 
visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)145     public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
146     {
147         markCpUtf8Entry(clazz, enclosingMethodAttribute.u2attributeNameIndex);
148 
149         // These entries have already been marked in the constant pool.
150         //clazz.constantPoolEntryAccept(this, enclosingMethodAttribute.u2classIndex);
151         //clazz.constantPoolEntryAccept(this, enclosingMethodAttribute.u2nameAndTypeIndex);
152     }
153 
154 
visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)155     public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
156     {
157         markCpUtf8Entry(clazz, deprecatedAttribute.u2attributeNameIndex);
158     }
159 
160 
visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)161     public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
162     {
163         markCpUtf8Entry(clazz, syntheticAttribute.u2attributeNameIndex);
164     }
165 
166 
visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)167     public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
168     {
169         markCpUtf8Entry(clazz, signatureAttribute.u2attributeNameIndex);
170 
171         markCpUtf8Entry(clazz, signatureAttribute.u2signatureIndex);
172     }
173 
174 
visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)175     public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
176     {
177         markCpUtf8Entry(clazz, constantValueAttribute.u2attributeNameIndex);
178     }
179 
180 
visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)181     public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
182     {
183         markCpUtf8Entry(clazz, exceptionsAttribute.u2attributeNameIndex);
184     }
185 
186 
visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)187     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
188     {
189         markCpUtf8Entry(clazz, codeAttribute.u2attributeNameIndex);
190 
191         // Mark the UTF-8 entries referenced by the attributes.
192         codeAttribute.attributesAccept(clazz, method, this);
193     }
194 
195 
visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)196     public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
197     {
198         markCpUtf8Entry(clazz, stackMapAttribute.u2attributeNameIndex);
199     }
200 
201 
visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)202     public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
203     {
204         markCpUtf8Entry(clazz, stackMapTableAttribute.u2attributeNameIndex);
205     }
206 
207 
visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)208     public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
209     {
210         markCpUtf8Entry(clazz, lineNumberTableAttribute.u2attributeNameIndex);
211     }
212 
213 
visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)214     public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
215     {
216         markCpUtf8Entry(clazz, localVariableTableAttribute.u2attributeNameIndex);
217 
218         // Mark the UTF-8 entries referenced by the local variables.
219         localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
220     }
221 
222 
visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)223     public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
224     {
225         markCpUtf8Entry(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
226 
227         // Mark the UTF-8 entries referenced by the local variable types.
228         localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
229     }
230 
231 
visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)232     public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
233     {
234         markCpUtf8Entry(clazz, annotationsAttribute.u2attributeNameIndex);
235 
236         // Mark the UTF-8 entries referenced by the annotations.
237         annotationsAttribute.annotationsAccept(clazz, this);
238     }
239 
240 
visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)241     public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
242     {
243         markCpUtf8Entry(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
244 
245         // Mark the UTF-8 entries referenced by the annotations.
246         parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
247     }
248 
249 
visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)250     public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
251     {
252         markCpUtf8Entry(clazz, annotationDefaultAttribute.u2attributeNameIndex);
253 
254         // Mark the UTF-8 entries referenced by the element value.
255         annotationDefaultAttribute.defaultValueAccept(clazz, this);
256     }
257 
258 
259     // Implementations for InnerClassesInfoVisitor.
260 
visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)261     public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
262     {
263         if (innerClassesInfo.u2innerNameIndex != 0)
264         {
265             markCpUtf8Entry(clazz, innerClassesInfo.u2innerNameIndex);
266         }
267     }
268 
269 
270     // Implementations for LocalVariableInfoVisitor.
271 
visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)272     public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
273     {
274         markCpUtf8Entry(clazz, localVariableInfo.u2nameIndex);
275         markCpUtf8Entry(clazz, localVariableInfo.u2descriptorIndex);
276     }
277 
278 
279     // Implementations for LocalVariableTypeInfoVisitor.
280 
visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)281     public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
282     {
283         markCpUtf8Entry(clazz, localVariableTypeInfo.u2nameIndex);
284         markCpUtf8Entry(clazz, localVariableTypeInfo.u2signatureIndex);
285     }
286 
287 
288     // Implementations for AnnotationVisitor.
289 
visitAnnotation(Clazz clazz, Annotation annotation)290     public void visitAnnotation(Clazz clazz, Annotation annotation)
291     {
292         markCpUtf8Entry(clazz, annotation.u2typeIndex);
293 
294         // Mark the UTF-8 entries referenced by the element values.
295         annotation.elementValuesAccept(clazz, this);
296     }
297 
298 
299     // Implementations for ElementValueVisitor.
300 
visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)301     public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
302     {
303         if (constantElementValue.u2elementNameIndex != 0)
304         {
305             markCpUtf8Entry(clazz, constantElementValue.u2elementNameIndex);
306         }
307 
308         // Only the string constant element value refers to a UTF-8 entry.
309         if (constantElementValue.u1tag == ClassConstants.ELEMENT_VALUE_STRING_CONSTANT)
310         {
311             markCpUtf8Entry(clazz, constantElementValue.u2constantValueIndex);
312         }
313     }
314 
315 
visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)316     public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
317     {
318         if (enumConstantElementValue.u2elementNameIndex != 0)
319         {
320             markCpUtf8Entry(clazz, enumConstantElementValue.u2elementNameIndex);
321         }
322 
323         markCpUtf8Entry(clazz, enumConstantElementValue.u2typeNameIndex);
324         markCpUtf8Entry(clazz, enumConstantElementValue.u2constantNameIndex);
325     }
326 
327 
visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)328     public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
329     {
330         if (classElementValue.u2elementNameIndex != 0)
331         {
332             markCpUtf8Entry(clazz, classElementValue.u2elementNameIndex);
333         }
334 
335         markCpUtf8Entry(clazz, classElementValue.u2classInfoIndex);
336     }
337 
338 
visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)339     public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
340     {
341         if (annotationElementValue.u2elementNameIndex != 0)
342         {
343             markCpUtf8Entry(clazz, annotationElementValue.u2elementNameIndex);
344         }
345 
346         // Mark the UTF-8 entries referenced by the annotation.
347         annotationElementValue.annotationAccept(clazz, this);
348     }
349 
350 
visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)351     public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
352     {
353         if (arrayElementValue.u2elementNameIndex != 0)
354         {
355             markCpUtf8Entry(clazz, arrayElementValue.u2elementNameIndex);
356         }
357 
358         // Mark the UTF-8 entries referenced by the element values.
359         arrayElementValue.elementValuesAccept(clazz, annotation, this);
360     }
361 
362 
363     // Small utility methods.
364 
365     /**
366      * Marks the given UTF-8 constant pool entry of the given class.
367      */
markCpUtf8Entry(Clazz clazz, int index)368     private void markCpUtf8Entry(Clazz clazz, int index)
369     {
370          markAsUsed((Utf8Constant)((ProgramClass)clazz).getConstant(index));
371     }
372 
373 
374     /**
375      * Marks the given VisitorAccepter as being used.
376      * In this context, the VisitorAccepter will be a Utf8Constant object.
377      */
markAsUsed(VisitorAccepter visitorAccepter)378     private static void markAsUsed(VisitorAccepter visitorAccepter)
379     {
380         visitorAccepter.setVisitorInfo(USED);
381     }
382 
383 
384     /**
385      * Returns whether the given VisitorAccepter has been marked as being used.
386      * In this context, the VisitorAccepter will be a Utf8Constant object.
387      */
isUsed(VisitorAccepter visitorAccepter)388     static boolean isUsed(VisitorAccepter visitorAccepter)
389     {
390         return visitorAccepter.getVisitorInfo() == USED;
391     }
392 }
393