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 
17 package dexfuzz.rawdex;
18 
19 import dexfuzz.Log;
20 
21 import java.io.IOException;
22 
23 public 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
read(DexRandomAccessFile file)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
write(DexRandomAccessFile file)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
incrementIndex(IndexUpdateKind kind, int insertedIdx)125   public void incrementIndex(IndexUpdateKind kind, int insertedIdx) {
126     // Do nothing
127   }
128 }
129