• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013, Google LLC
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google LLC nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 package com.android.tools.smali.dexlib2.dexbacked.raw;
32 
33 import com.android.tools.smali.dexlib2.AccessFlags;
34 import com.android.tools.smali.dexlib2.dexbacked.DexBuffer;
35 import com.android.tools.smali.dexlib2.dexbacked.raw.util.DexAnnotator;
36 import com.android.tools.smali.dexlib2.util.AnnotatedBytes;
37 import com.android.tools.smali.util.StringUtils;
38 
39 import java.util.Arrays;
40 import java.util.List;
41 
42 import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile;
43 import com.android.tools.smali.dexlib2.dexbacked.DexReader;
44 
45 import javax.annotation.Nonnull;
46 import javax.annotation.Nullable;
47 
48 public class ClassDataItem {
49     @Nonnull
makeAnnotator(@onnull DexAnnotator annotator, @Nonnull MapItem mapItem)50     public static SectionAnnotator makeAnnotator(@Nonnull DexAnnotator annotator, @Nonnull MapItem mapItem) {
51         return new SectionAnnotator(annotator, mapItem) {
52             private SectionAnnotator codeItemAnnotator = null;
53 
54             @Override public void annotateSection(@Nonnull AnnotatedBytes out) {
55                 codeItemAnnotator = annotator.getAnnotator(ItemType.CODE_ITEM);
56                 super.annotateSection(out);
57             }
58 
59             @Nonnull @Override public String getItemName() {
60                 return "class_data_item";
61             }
62 
63             @Override
64             protected void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity) {
65                 DexReader<? extends DexBuffer> reader = dexFile.getBuffer().readerAt(out.getCursor());
66 
67                 int staticFieldsSize = reader.readSmallUleb128();
68                 out.annotateTo(reader.getOffset(), "static_fields_size = %d", staticFieldsSize);
69 
70                 int instanceFieldsSize = reader.readSmallUleb128();
71                 out.annotateTo(reader.getOffset(), "instance_fields_size = %d", instanceFieldsSize);
72 
73                 int directMethodsSize = reader.readSmallUleb128();
74                 out.annotateTo(reader.getOffset(), "direct_methods_size = %d", directMethodsSize);
75 
76                 int virtualMethodsSize = reader.readSmallUleb128();
77                 out.annotateTo(reader.getOffset(), "virtual_methods_size = %d", virtualMethodsSize);
78 
79                 int previousIndex = 0;
80                 if (staticFieldsSize > 0) {
81                     out.annotate(0, "static_fields:");
82                     out.indent();
83                     for (int i=0; i<staticFieldsSize; i++) {
84                         out.annotate(0, "static_field[%d]", i);
85                         out.indent();
86                         previousIndex = annotateEncodedField(out, dexFile, reader, previousIndex);
87                         out.deindent();
88                     }
89                     out.deindent();
90                 }
91 
92                 if (instanceFieldsSize > 0) {
93                     out.annotate(0, "instance_fields:");
94                     out.indent();
95                     previousIndex = 0;
96                     for (int i=0; i<instanceFieldsSize; i++) {
97                         out.annotate(0, "instance_field[%d]", i);
98                         out.indent();
99                         previousIndex = annotateEncodedField(out, dexFile, reader, previousIndex);
100                         out.deindent();
101                     }
102                     out.deindent();
103                 }
104 
105                 if (directMethodsSize > 0) {
106                     out.annotate(0, "direct_methods:");
107                     out.indent();
108                     previousIndex = 0;
109                     for (int i=0; i<directMethodsSize; i++) {
110                         out.annotate(0, "direct_method[%d]", i);
111                         out.indent();
112                         previousIndex = annotateEncodedMethod(out, dexFile, reader, previousIndex);
113                         out.deindent();
114                     }
115                     out.deindent();
116                 }
117 
118                 if (virtualMethodsSize > 0) {
119                     out.annotate(0, "virtual_methods:");
120                     out.indent();
121                     previousIndex = 0;
122                     for (int i=0; i<virtualMethodsSize; i++) {
123                         out.annotate(0, "virtual_method[%d]", i);
124                         out.indent();
125                         previousIndex = annotateEncodedMethod(out, dexFile, reader, previousIndex);
126                         out.deindent();
127                     }
128                     out.deindent();
129                 }
130             }
131 
132             private int annotateEncodedField(@Nonnull AnnotatedBytes out, @Nonnull DexBackedDexFile dexFile,
133                                              @Nonnull DexReader<? extends DexBuffer> reader, int previousIndex) {
134                 // large values may be used for the index delta, which cause the cumulative index to overflow upon
135                 // addition, effectively allowing out of order entries.
136                 int indexDelta = reader.readLargeUleb128();
137                 int fieldIndex = previousIndex + indexDelta;
138                 out.annotateTo(reader.getOffset(), "field_idx_diff = %d: %s", indexDelta,
139                         FieldIdItem.getReferenceAnnotation(dexFile, fieldIndex));
140 
141                 int accessFlags = reader.readSmallUleb128();
142                 out.annotateTo(reader.getOffset(), "access_flags = 0x%x: %s", accessFlags,
143                         StringUtils.join(Arrays.asList(AccessFlags.getAccessFlagsForField(accessFlags)), "|"));
144 
145                 return fieldIndex;
146             }
147 
148             private int annotateEncodedMethod(@Nonnull AnnotatedBytes out, @Nonnull DexBackedDexFile dexFile,
149                                               @Nonnull DexReader<? extends DexBuffer> reader, int previousIndex) {
150                 // large values may be used for the index delta, which cause the cumulative index to overflow upon
151                 // addition, effectively allowing out of order entries.
152                 int indexDelta = reader.readLargeUleb128();
153                 int methodIndex = previousIndex + indexDelta;
154                 out.annotateTo(reader.getOffset(), "method_idx_diff = %d: %s", indexDelta,
155                         MethodIdItem.getReferenceAnnotation(dexFile, methodIndex));
156 
157                 int accessFlags = reader.readSmallUleb128();
158                 out.annotateTo(reader.getOffset(), "access_flags = 0x%x: %s", accessFlags,
159                     StringUtils.join(Arrays.asList(AccessFlags.getAccessFlagsForField(accessFlags)), "|"));
160 
161                 int codeOffset = reader.readSmallUleb128();
162                 if (codeOffset == 0) {
163                     out.annotateTo(reader.getOffset(), "code_off = code_item[NO_OFFSET]");
164                 } else {
165                     out.annotateTo(reader.getOffset(), "code_off = code_item[0x%x]", codeOffset);
166                     addCodeItemIdentity(codeOffset, MethodIdItem.asString(dexFile, methodIndex));
167                 }
168 
169                 return methodIndex;
170             }
171 
172             private void addCodeItemIdentity(int codeItemOffset, String methodString) {
173                 if (codeItemAnnotator != null) {
174                     codeItemAnnotator.setItemIdentity(codeItemOffset, methodString);
175                 }
176             }
177         };
178     }
179 }
180