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