HeaderItem.java revision 132eeaedf7d0980397fbdac41e1a7aebff01adbf
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 32package org.jf.dexlib2.dexbacked.raw; 33 34import org.jf.dexlib2.dexbacked.raw.util.DexAnnotator; 35import org.jf.dexlib2.util.AnnotatedBytes; 36import org.jf.util.StringUtils; 37 38import javax.annotation.Nonnull; 39import javax.annotation.Nullable; 40 41public class HeaderItem { 42 public static final int ITEM_SIZE = 0x70; 43 44 public static final byte[][] MAGIC_VALUES= new byte[][] { 45 new byte[]{0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00}, 46 new byte[]{0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x36, 0x00}}; 47 48 public static final int LITTLE_ENDIAN_TAG = 0x12345678; 49 public static final int BIG_ENDIAN_TAG = 0x78563412; 50 51 public static final int CHECKSUM_OFFSET = 8; 52 53 public static final int SIGNATURE_OFFSET = 12; 54 public static final int SIGNATURE_SIZE = 20; 55 56 public static final int HEADER_SIZE_OFFSET = 36; 57 58 public static final int ENDIAN_TAG_OFFSET = 40; 59 60 public static final int MAP_OFFSET = 52; 61 62 public static final int STRING_COUNT_OFFSET = 56; 63 public static final int STRING_START_OFFSET = 60; 64 65 public static final int TYPE_COUNT_OFFSET = 64; 66 public static final int TYPE_START_OFFSET = 68; 67 68 public static final int PROTO_COUNT_OFFSET = 72; 69 public static final int PROTO_START_OFFSET = 76; 70 71 public static final int FIELD_COUNT_OFFSET = 80; 72 public static final int FIELD_START_OFFSET = 84; 73 74 public static final int METHOD_COUNT_OFFSET = 88; 75 public static final int METHOD_START_OFFSET = 92; 76 77 public static final int CLASS_COUNT_OFFSET = 96; 78 public static final int CLASS_START_OFFSET = 100; 79 80 @Nonnull private RawDexFile dexFile; 81 82 public HeaderItem(@Nonnull RawDexFile dexFile) { 83 this.dexFile = dexFile; 84 } 85 86 public int getChecksum() { 87 return dexFile.readSmallUint(CHECKSUM_OFFSET); 88 } 89 90 @Nonnull public byte[] getSignature() { 91 return dexFile.readByteRange(SIGNATURE_OFFSET, SIGNATURE_SIZE); 92 } 93 94 public int getMapOffset() { 95 return dexFile.readSmallUint(MAP_OFFSET); 96 } 97 98 public int getHeaderSize() { 99 return dexFile.readSmallUint(HEADER_SIZE_OFFSET); 100 } 101 102 public int getStringCount() { 103 return dexFile.readSmallUint(STRING_COUNT_OFFSET); 104 } 105 106 public int getStringOffset() { 107 return dexFile.readSmallUint(STRING_START_OFFSET); 108 } 109 110 public int getTypeCount() { 111 return dexFile.readSmallUint(TYPE_COUNT_OFFSET); 112 } 113 114 public int getTypeOffset() { 115 return dexFile.readSmallUint(TYPE_START_OFFSET); 116 } 117 118 public int getProtoCount() { 119 return dexFile.readSmallUint(PROTO_COUNT_OFFSET); 120 } 121 122 public int getProtoOffset() { 123 return dexFile.readSmallUint(PROTO_START_OFFSET); 124 } 125 126 public int getFieldCount() { 127 return dexFile.readSmallUint(FIELD_COUNT_OFFSET); 128 } 129 130 public int getFieldOffset() { 131 return dexFile.readSmallUint(FIELD_START_OFFSET); 132 } 133 134 public int getMethodCount() { 135 return dexFile.readSmallUint(METHOD_COUNT_OFFSET); 136 } 137 138 public int getMethodOffset() { 139 return dexFile.readSmallUint(METHOD_START_OFFSET); 140 } 141 142 public int getClassCount() { 143 return dexFile.readSmallUint(CLASS_COUNT_OFFSET); 144 } 145 146 public int getClassOffset() { 147 return dexFile.readSmallUint(CLASS_START_OFFSET); 148 } 149 150 @Nonnull 151 public static SectionAnnotator makeAnnotator(@Nonnull DexAnnotator annotator, @Nonnull MapItem mapItem) { 152 return new SectionAnnotator(annotator, mapItem) { 153 @Nonnull @Override public String getItemName() { 154 return "header_item"; 155 } 156 157 @Override 158 protected void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity) { 159 int startOffset = out.getCursor(); 160 int headerSize; 161 162 StringBuilder magicBuilder = new StringBuilder(); 163 for (int i=0; i<8; i++) { 164 magicBuilder.append((char)dexFile.readUbyte(startOffset + i)); 165 } 166 167 out.annotate(8, "magic: %s", StringUtils.escapeString(magicBuilder.toString())); 168 out.annotate(4, "checksum"); 169 out.annotate(20, "signature"); 170 out.annotate(4, "file_size: %d", dexFile.readInt(out.getCursor())); 171 172 headerSize = dexFile.readInt(out.getCursor()); 173 out.annotate(4, "header_size: %d", headerSize); 174 175 int endianTag = dexFile.readInt(out.getCursor()); 176 out.annotate(4, "endian_tag: 0x%x (%s)", endianTag, getEndianText(endianTag)); 177 178 out.annotate(4, "link_size: %d", dexFile.readInt(out.getCursor())); 179 out.annotate(4, "link_offset: 0x%x", dexFile.readInt(out.getCursor())); 180 181 out.annotate(4, "map_off: 0x%x", dexFile.readInt(out.getCursor())); 182 183 out.annotate(4, "string_ids_size: %d", dexFile.readInt(out.getCursor())); 184 out.annotate(4, "string_ids_off: 0x%x", dexFile.readInt(out.getCursor())); 185 186 out.annotate(4, "type_ids_size: %d", dexFile.readInt(out.getCursor())); 187 out.annotate(4, "type_ids_off: 0x%x", dexFile.readInt(out.getCursor())); 188 189 out.annotate(4, "proto_ids_size: %d", dexFile.readInt(out.getCursor())); 190 out.annotate(4, "proto_ids_off: 0x%x", dexFile.readInt(out.getCursor())); 191 192 out.annotate(4, "field_ids_size: %d", dexFile.readInt(out.getCursor())); 193 out.annotate(4, "field_ids_off: 0x%x", dexFile.readInt(out.getCursor())); 194 195 out.annotate(4, "method_ids_size: %d", dexFile.readInt(out.getCursor())); 196 out.annotate(4, "method_ids_off: 0x%x", dexFile.readInt(out.getCursor())); 197 198 out.annotate(4, "class_defs_size: %d", dexFile.readInt(out.getCursor())); 199 out.annotate(4, "class_defs_off: 0x%x", dexFile.readInt(out.getCursor())); 200 201 out.annotate(4, "data_size: %d", dexFile.readInt(out.getCursor())); 202 out.annotate(4, "data_off: 0x%x", dexFile.readInt(out.getCursor())); 203 204 if (headerSize > ITEM_SIZE) { 205 out.annotateTo(headerSize, "header padding"); 206 } 207 } 208 }; 209 } 210 211 private static String getEndianText(int endianTag) { 212 if (endianTag == LITTLE_ENDIAN_TAG) { 213 return "Little Endian"; 214 } 215 if (endianTag == BIG_ENDIAN_TAG) { 216 return "Big Endian"; 217 } 218 return "Invalid"; 219 } 220} 221