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