• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013, Google Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 package org.jf.dexlib2.writer.pool;
33 
34 import org.jf.dexlib2.Opcodes;
35 import org.jf.dexlib2.ValueType;
36 import org.jf.dexlib2.iface.Annotation;
37 import org.jf.dexlib2.iface.AnnotationElement;
38 import org.jf.dexlib2.iface.ClassDef;
39 import org.jf.dexlib2.iface.Field;
40 import org.jf.dexlib2.iface.reference.*;
41 import org.jf.dexlib2.iface.value.*;
42 import org.jf.dexlib2.writer.*;
43 import org.jf.dexlib2.writer.io.DexDataStore;
44 import org.jf.dexlib2.writer.io.FileDataStore;
45 import org.jf.util.ExceptionWithContext;
46 
47 import javax.annotation.Nonnull;
48 import java.io.File;
49 import java.io.IOException;
50 import java.util.Collection;
51 import java.util.Set;
52 
53 public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference,
54         MethodProtoReference, FieldReference, MethodReference, PoolClassDef,
55         CallSiteReference, MethodHandleReference, Annotation, Set<? extends Annotation>,
56         TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod,
57         ArrayEncodedValue, EncodedValue, AnnotationElement, StringPool, TypePool, ProtoPool, FieldPool, MethodPool,
58         ClassPool, CallSitePool, MethodHandlePool, TypeListPool, AnnotationPool, AnnotationSetPool, EncodedArrayPool> {
59 
60     private final BasePool<?, ?>[] sections = new BasePool<?, ?>[] {
61             stringSection,
62             typeSection,
63             protoSection,
64             fieldSection,
65             methodSection,
66             classSection,
67             callSiteSection,
68             methodHandleSection,
69 
70             typeListSection,
71             annotationSection,
72             annotationSetSection,
73             encodedArraySection,
74     };
75 
DexPool(Opcodes opcodes)76     public DexPool(Opcodes opcodes) {
77         super(opcodes);
78     }
79 
getSectionProvider()80     @Nonnull @Override protected SectionProvider getSectionProvider() {
81         return new DexPoolSectionProvider();
82     }
83 
writeTo(@onnull DexDataStore dataStore, @Nonnull org.jf.dexlib2.iface.DexFile input)84     public static void writeTo(@Nonnull DexDataStore dataStore, @Nonnull org.jf.dexlib2.iface.DexFile input)
85             throws IOException {
86         DexPool dexPool = new DexPool(input.getOpcodes());
87         for (ClassDef classDef: input.getClasses()) {
88             dexPool.internClass(classDef);
89         }
90         dexPool.writeTo(dataStore);
91     }
92 
writeTo(@onnull String path, @Nonnull org.jf.dexlib2.iface.DexFile input)93     public static void writeTo(@Nonnull String path, @Nonnull org.jf.dexlib2.iface.DexFile input) throws IOException {
94         DexPool dexPool = new DexPool(input.getOpcodes());
95         for (ClassDef classDef: input.getClasses()) {
96             dexPool.internClass(classDef);
97         }
98         dexPool.writeTo(new FileDataStore(new File(path)));
99     }
100 
101     /**
102      * Interns a class into this DexPool
103      * @param classDef The class to intern
104      */
internClass(ClassDef classDef)105     public void internClass(ClassDef classDef) {
106         classSection.intern(classDef);
107     }
108 
109     /**
110      * Creates a marked state that can be returned to by calling reset()
111      *
112      * This is useful to rollback the last added class if it causes a method/field/type overflow
113      */
mark()114     public void mark() {
115         for (Markable section: sections) {
116             section.mark();
117         }
118     }
119 
120     /**
121      * Resets to the last marked state
122      *
123      * This is useful to rollback the last added class if it causes a method/field/type overflow
124      */
reset()125     public void reset() {
126         for (Markable section: sections) {
127             section.reset();
128         }
129     }
130 
writeEncodedValue(@onnull InternalEncodedValueWriter writer, @Nonnull EncodedValue encodedValue)131     @Override protected void writeEncodedValue(@Nonnull InternalEncodedValueWriter writer,
132                                                @Nonnull EncodedValue encodedValue) throws IOException {
133         switch (encodedValue.getValueType()) {
134             case ValueType.ANNOTATION:
135                 AnnotationEncodedValue annotationEncodedValue = (AnnotationEncodedValue)encodedValue;
136                 writer.writeAnnotation(annotationEncodedValue.getType(), annotationEncodedValue.getElements());
137                 break;
138             case ValueType.ARRAY:
139                 ArrayEncodedValue arrayEncodedValue = (ArrayEncodedValue)encodedValue;
140                 writer.writeArray(arrayEncodedValue.getValue());
141                 break;
142             case ValueType.BOOLEAN:
143                 writer.writeBoolean(((BooleanEncodedValue)encodedValue).getValue());
144                 break;
145             case ValueType.BYTE:
146                 writer.writeByte(((ByteEncodedValue)encodedValue).getValue());
147                 break;
148             case ValueType.CHAR:
149                 writer.writeChar(((CharEncodedValue)encodedValue).getValue());
150                 break;
151             case ValueType.DOUBLE:
152                 writer.writeDouble(((DoubleEncodedValue)encodedValue).getValue());
153                 break;
154             case ValueType.ENUM:
155                 writer.writeEnum(((EnumEncodedValue)encodedValue).getValue());
156                 break;
157             case ValueType.FIELD:
158                 writer.writeField(((FieldEncodedValue)encodedValue).getValue());
159                 break;
160             case ValueType.FLOAT:
161                 writer.writeFloat(((FloatEncodedValue)encodedValue).getValue());
162                 break;
163             case ValueType.INT:
164                 writer.writeInt(((IntEncodedValue)encodedValue).getValue());
165                 break;
166             case ValueType.LONG:
167                 writer.writeLong(((LongEncodedValue)encodedValue).getValue());
168                 break;
169             case ValueType.METHOD:
170                 writer.writeMethod(((MethodEncodedValue)encodedValue).getValue());
171                 break;
172             case ValueType.NULL:
173                 writer.writeNull();
174                 break;
175             case ValueType.SHORT:
176                 writer.writeShort(((ShortEncodedValue)encodedValue).getValue());
177                 break;
178             case ValueType.STRING:
179                 writer.writeString(((StringEncodedValue)encodedValue).getValue());
180                 break;
181             case ValueType.TYPE:
182                 writer.writeType(((TypeEncodedValue)encodedValue).getValue());
183                 break;
184             case ValueType.METHOD_TYPE:
185                 writer.writeMethodType(((MethodTypeEncodedValue) encodedValue).getValue());
186                 break;
187             case ValueType.METHOD_HANDLE:
188                 writer.writeMethodHandle(((MethodHandleEncodedValue) encodedValue).getValue());
189                 break;
190             default:
191                 throw new ExceptionWithContext("Unrecognized value type: %d", encodedValue.getValueType());
192         }
193     }
194 
internEncodedValue(@onnull EncodedValue encodedValue)195     void internEncodedValue(@Nonnull EncodedValue encodedValue) {
196         switch (encodedValue.getValueType()) {
197             case ValueType.ANNOTATION:
198                 AnnotationEncodedValue annotationEncodedValue = (AnnotationEncodedValue)encodedValue;
199                 typeSection.intern(annotationEncodedValue.getType());
200                 for (AnnotationElement element: annotationEncodedValue.getElements()) {
201                     stringSection.intern(element.getName());
202                     internEncodedValue(element.getValue());
203                 }
204                 break;
205             case ValueType.ARRAY:
206                 for (EncodedValue element: ((ArrayEncodedValue)encodedValue).getValue()) {
207                     internEncodedValue(element);
208                 }
209                 break;
210             case ValueType.STRING:
211                 stringSection.intern(((StringEncodedValue)encodedValue).getValue());
212                 break;
213             case ValueType.TYPE:
214                 typeSection.intern(((TypeEncodedValue)encodedValue).getValue());
215                 break;
216             case ValueType.ENUM:
217                 fieldSection.intern(((EnumEncodedValue)encodedValue).getValue());
218                 break;
219             case ValueType.FIELD:
220                 fieldSection.intern(((FieldEncodedValue)encodedValue).getValue());
221                 break;
222             case ValueType.METHOD:
223                 methodSection.intern(((MethodEncodedValue)encodedValue).getValue());
224                 break;
225             case ValueType.METHOD_HANDLE:
226                 methodHandleSection.intern(((MethodHandleEncodedValue)encodedValue).getValue());
227                 break;
228             case ValueType.METHOD_TYPE:
229                 protoSection.intern(((MethodTypeEncodedValue)encodedValue).getValue());
230                 break;
231         }
232     }
233 
234     protected class DexPoolSectionProvider extends SectionProvider {
getStringSection()235         @Nonnull @Override public StringPool getStringSection() {
236             return new StringPool(DexPool.this);
237         }
238 
getTypeSection()239         @Nonnull @Override public TypePool getTypeSection() {
240             return new TypePool(DexPool.this);
241         }
242 
getProtoSection()243         @Nonnull @Override public ProtoPool getProtoSection() {
244             return new ProtoPool(DexPool.this);
245         }
246 
getFieldSection()247         @Nonnull @Override public FieldPool getFieldSection() {
248             return new FieldPool(DexPool.this);
249         }
250 
getMethodSection()251         @Nonnull @Override public MethodPool getMethodSection() {
252             return new MethodPool(DexPool.this);
253         }
254 
getClassSection()255         @Nonnull @Override public ClassPool getClassSection() {
256             return new ClassPool(DexPool.this);
257         }
258 
getCallSiteSection()259         @Nonnull @Override public CallSitePool getCallSiteSection() {
260             return new CallSitePool(DexPool.this);
261         }
262 
getMethodHandleSection()263         @Nonnull @Override public MethodHandlePool getMethodHandleSection() {
264             return new MethodHandlePool(DexPool.this);
265         }
266 
getTypeListSection()267         @Nonnull @Override public TypeListPool getTypeListSection() {
268             return new TypeListPool(DexPool.this);
269         }
270 
getAnnotationSection()271         @Nonnull @Override public AnnotationPool getAnnotationSection() {
272             return new AnnotationPool(DexPool.this);
273         }
274 
getAnnotationSetSection()275         @Nonnull @Override public AnnotationSetPool getAnnotationSetSection() {
276             return new AnnotationSetPool(DexPool.this);
277         }
278 
getEncodedArraySection()279         @Nonnull @Override public EncodedArrayPool getEncodedArraySection() {
280             return new EncodedArrayPool(DexPool.this);
281         }
282     }
283 }
284