1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package dexfuzz.rawdex;
18
19import dexfuzz.Log;
20
21import java.io.IOException;
22
23public class HeaderItem implements RawDexObject {
24  public byte[] magic;
25  public int checksum;
26  public byte[] signature; // Verification doesn't depend on this, so we don't update it.
27  public int fileSize;
28  public int headerSize;
29  public int endianTag;
30  public int linkSize;
31  public Offset linkOff;
32  public Offset mapOff;
33  public int stringIdsSize;
34  public Offset stringIdsOff;
35  public int typeIdsSize;
36  public Offset typeIdsOff;
37  public int protoIdsSize;
38  public Offset protoIdsOff;
39  public int fieldIdsSize;
40  public Offset fieldIdsOff;
41  public int methodIdsSize;
42  public Offset methodIdsOff;
43  public int classDefsSize;
44  public Offset classDefsOff;
45  public int dataSize;
46  public Offset dataOff;
47
48  @Override
49  public void read(DexRandomAccessFile file) throws IOException {
50    file.getOffsetTracker().getNewOffsettable(file, this);
51    magic = new byte[8];
52    for (int i = 0; i < 8; i++) {
53      magic[i] = file.readByte();
54    }
55    checksum = file.readUInt();
56    signature = new byte[20];
57    for (int i = 0; i < 20; i++) {
58      signature[i] = file.readByte();
59    }
60    fileSize = file.readUInt();
61    headerSize = file.readUInt();
62    endianTag = file.readUInt();
63    linkSize = file.readUInt();
64    linkOff = file.getOffsetTracker().getNewOffset(file.readUInt());
65    mapOff = file.getOffsetTracker().getNewOffset(file.readUInt());
66    stringIdsSize = file.readUInt();
67    stringIdsOff = file.getOffsetTracker().getNewOffset(file.readUInt());
68    typeIdsSize = file.readUInt();
69    typeIdsOff = file.getOffsetTracker().getNewOffset(file.readUInt());
70    protoIdsSize = file.readUInt();
71    protoIdsOff = file.getOffsetTracker().getNewOffset(file.readUInt());
72    fieldIdsSize = file.readUInt();
73    fieldIdsOff = file.getOffsetTracker().getNewOffset(file.readUInt());
74    methodIdsSize = file.readUInt();
75    methodIdsOff = file.getOffsetTracker().getNewOffset(file.readUInt());
76    classDefsSize = file.readUInt();
77    classDefsOff = file.getOffsetTracker().getNewOffset(file.readUInt());
78    dataSize = file.readUInt();
79    dataOff = file.getOffsetTracker().getNewOffset(file.readUInt());
80    if (headerSize != 0x70) {
81      Log.errorAndQuit("Invalid header size in header.");
82    }
83    if (file.getFilePointer() != headerSize) {
84      Log.errorAndQuit("Read a different amount than expected in header: "
85          + file.getFilePointer());
86    }
87  }
88
89  @Override
90  public void write(DexRandomAccessFile file) throws IOException {
91    file.getOffsetTracker().updatePositionOfNextOffsettable(file);
92    for (int i = 0; i < 8; i++) {
93      file.writeByte(magic[i]);
94    }
95    // Will be recalculated later!
96    file.writeUInt(checksum);
97    for (int i = 0; i < 20; i++) {
98      file.writeByte(signature[i]);
99    }
100    // Will be recalculated later!
101    file.writeUInt(fileSize);
102    file.writeUInt(headerSize);
103    file.writeUInt(endianTag);
104    file.writeUInt(linkSize);
105    file.getOffsetTracker().tryToWriteOffset(linkOff, file, false /* ULEB128 */);
106    file.getOffsetTracker().tryToWriteOffset(mapOff, file, false /* ULEB128 */);
107    file.writeUInt(stringIdsSize);
108    file.getOffsetTracker().tryToWriteOffset(stringIdsOff, file, false /* ULEB128 */);
109    file.writeUInt(typeIdsSize);
110    file.getOffsetTracker().tryToWriteOffset(typeIdsOff, file, false /* ULEB128 */);
111    file.writeUInt(protoIdsSize);
112    file.getOffsetTracker().tryToWriteOffset(protoIdsOff, file, false /* ULEB128 */);
113    file.writeUInt(fieldIdsSize);
114    file.getOffsetTracker().tryToWriteOffset(fieldIdsOff, file, false /* ULEB128 */);
115    file.writeUInt(methodIdsSize);
116    file.getOffsetTracker().tryToWriteOffset(methodIdsOff, file, false /* ULEB128 */);
117    file.writeUInt(classDefsSize);
118    file.getOffsetTracker().tryToWriteOffset(classDefsOff, file, false /* ULEB128 */);
119    // will be recalculated later
120    file.writeUInt(dataSize);
121    file.getOffsetTracker().tryToWriteOffset(dataOff, file, false /* ULEB128 */);
122  }
123
124  @Override
125  public void incrementIndex(IndexUpdateKind kind, int insertedIdx) {
126    // Do nothing
127  }
128}
129