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