• 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.dexbacked.raw;
33 
34 import com.google.common.base.Joiner;
35 import org.jf.dexlib2.AccessFlags;
36 import org.jf.dexlib2.dexbacked.DexReader;
37 import org.jf.dexlib2.dexbacked.raw.util.DexAnnotator;
38 import org.jf.dexlib2.util.AnnotatedBytes;
39 
40 import javax.annotation.Nonnull;
41 import javax.annotation.Nullable;
42 
43 public class ClassDataItem {
44     @Nonnull
makeAnnotator(@onnull DexAnnotator annotator, @Nonnull MapItem mapItem)45     public static SectionAnnotator makeAnnotator(@Nonnull DexAnnotator annotator, @Nonnull MapItem mapItem) {
46         return new SectionAnnotator(annotator, mapItem) {
47             private SectionAnnotator codeItemAnnotator = null;
48 
49             @Override public void annotateSection(@Nonnull AnnotatedBytes out) {
50                 codeItemAnnotator = annotator.getAnnotator(ItemType.CODE_ITEM);
51                 super.annotateSection(out);
52             }
53 
54 
55             @Nonnull @Override public String getItemName() {
56                 return "class_data_item";
57             }
58 
59             @Override
60             protected void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity) {
61                 DexReader reader = dexFile.readerAt(out.getCursor());
62 
63                 int staticFieldsSize = reader.readSmallUleb128();
64                 out.annotateTo(reader.getOffset(), "static_fields_size = %d", staticFieldsSize);
65 
66                 int instanceFieldsSize = reader.readSmallUleb128();
67                 out.annotateTo(reader.getOffset(), "instance_fields_size = %d", instanceFieldsSize);
68 
69                 int directMethodsSize = reader.readSmallUleb128();
70                 out.annotateTo(reader.getOffset(), "direct_methods_size = %d", directMethodsSize);
71 
72                 int virtualMethodsSize = reader.readSmallUleb128();
73                 out.annotateTo(reader.getOffset(), "virtual_methods_size = %d", virtualMethodsSize);
74 
75                 int previousIndex = 0;
76                 if (staticFieldsSize > 0) {
77                     out.annotate(0, "static_fields:");
78                     out.indent();
79                     for (int i=0; i<staticFieldsSize; i++) {
80                         out.annotate(0, "static_field[%d]", i);
81                         out.indent();
82                         previousIndex = annotateEncodedField(out, dexFile, reader, previousIndex);
83                         out.deindent();
84                     }
85                     out.deindent();
86                 }
87 
88                 if (instanceFieldsSize > 0) {
89                     out.annotate(0, "instance_fields:");
90                     out.indent();
91                     previousIndex = 0;
92                     for (int i=0; i<instanceFieldsSize; i++) {
93                         out.annotate(0, "instance_field[%d]", i);
94                         out.indent();
95                         previousIndex = annotateEncodedField(out, dexFile, reader, previousIndex);
96                         out.deindent();
97                     }
98                     out.deindent();
99                 }
100 
101                 if (directMethodsSize > 0) {
102                     out.annotate(0, "direct_methods:");
103                     out.indent();
104                     previousIndex = 0;
105                     for (int i=0; i<directMethodsSize; i++) {
106                         out.annotate(0, "direct_method[%d]", i);
107                         out.indent();
108                         previousIndex = annotateEncodedMethod(out, dexFile, reader, previousIndex);
109                         out.deindent();
110                     }
111                     out.deindent();
112                 }
113 
114                 if (virtualMethodsSize > 0) {
115                     out.annotate(0, "virtual_methods:");
116                     out.indent();
117                     previousIndex = 0;
118                     for (int i=0; i<virtualMethodsSize; i++) {
119                         out.annotate(0, "virtual_method[%d]", i);
120                         out.indent();
121                         previousIndex = annotateEncodedMethod(out, dexFile, reader, previousIndex);
122                         out.deindent();
123                     }
124                     out.deindent();
125                 }
126             }
127 
128             private int annotateEncodedField(@Nonnull AnnotatedBytes out, @Nonnull RawDexFile dexFile,
129                                              @Nonnull DexReader reader, int previousIndex) {
130                 // large values may be used for the index delta, which cause the cumulative index to overflow upon
131                 // addition, effectively allowing out of order entries.
132                 int indexDelta = reader.readLargeUleb128();
133                 int fieldIndex = previousIndex + indexDelta;
134                 out.annotateTo(reader.getOffset(), "field_idx_diff = %d: %s", indexDelta,
135                         FieldIdItem.getReferenceAnnotation(dexFile, fieldIndex));
136 
137                 int accessFlags = reader.readSmallUleb128();
138                 out.annotateTo(reader.getOffset(), "access_flags = 0x%x: %s", accessFlags,
139                         Joiner.on('|').join(AccessFlags.getAccessFlagsForField(accessFlags)));
140 
141                 return fieldIndex;
142             }
143 
144             private int annotateEncodedMethod(@Nonnull AnnotatedBytes out, @Nonnull RawDexFile dexFile,
145                                               @Nonnull DexReader reader, int previousIndex) {
146                 // large values may be used for the index delta, which cause the cumulative index to overflow upon
147                 // addition, effectively allowing out of order entries.
148                 int indexDelta = reader.readLargeUleb128();
149                 int methodIndex = previousIndex + indexDelta;
150                 out.annotateTo(reader.getOffset(), "method_idx_diff = %d: %s", indexDelta,
151                         MethodIdItem.getReferenceAnnotation(dexFile, methodIndex));
152 
153                 int accessFlags = reader.readSmallUleb128();
154                 out.annotateTo(reader.getOffset(), "access_flags = 0x%x: %s", accessFlags,
155                         Joiner.on('|').join(AccessFlags.getAccessFlagsForMethod(accessFlags)));
156 
157                 int codeOffset = reader.readSmallUleb128();
158                 if (codeOffset == 0) {
159                     out.annotateTo(reader.getOffset(), "code_off = code_item[NO_OFFSET]");
160                 } else {
161                     out.annotateTo(reader.getOffset(), "code_off = code_item[0x%x]", codeOffset);
162                     addCodeItemIdentity(codeOffset, MethodIdItem.asString(dexFile, methodIndex));
163                 }
164 
165                 return methodIndex;
166             }
167 
168             private void addCodeItemIdentity(int codeItemOffset, String methodString) {
169                 if (codeItemAnnotator != null) {
170                     codeItemAnnotator.setItemIdentity(codeItemOffset, methodString);
171                 }
172             }
173         };
174     }
175 }
176