1/*
2 * Copyright (C) 2007 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 com.android.dx.dex.file;
18
19import com.android.dx.dex.DexFormat;
20import com.android.dx.dex.SizeOf;
21import com.android.dx.rop.cst.CstString;
22import com.android.dx.util.AnnotatedOutput;
23import com.android.dx.util.Hex;
24
25/**
26 * File header section of a {@code .dex} file.
27 */
28public final class HeaderItem extends IndexedItem {
29    /**
30     * Constructs an instance.
31     */
32    public HeaderItem() {
33        // This space intentionally left blank.
34    }
35
36    /** {@inheritDoc} */
37    @Override
38    public ItemType itemType() {
39        return ItemType.TYPE_HEADER_ITEM;
40    }
41
42    /** {@inheritDoc} */
43    @Override
44    public int writeSize() {
45        return SizeOf.HEADER_ITEM;
46    }
47
48    /** {@inheritDoc} */
49    @Override
50    public void addContents(DexFile file) {
51        // Nothing to do here.
52    }
53
54    /** {@inheritDoc} */
55    @Override
56    public void writeTo(DexFile file, AnnotatedOutput out) {
57        int mapOff = file.getMap().getFileOffset();
58        Section firstDataSection = file.getFirstDataSection();
59        Section lastDataSection = file.getLastDataSection();
60        int dataOff = firstDataSection.getFileOffset();
61        int dataSize = lastDataSection.getFileOffset() +
62            lastDataSection.writeSize() - dataOff;
63
64        String magic = file.getDexOptions().getMagic();
65
66        if (out.annotates()) {
67            out.annotate(8, "magic: " + new CstString(magic).toQuoted());
68            out.annotate(4, "checksum");
69            out.annotate(20, "signature");
70            out.annotate(4, "file_size:       " +
71                         Hex.u4(file.getFileSize()));
72            out.annotate(4, "header_size:     " + Hex.u4(SizeOf.HEADER_ITEM));
73            out.annotate(4, "endian_tag:      " + Hex.u4(DexFormat.ENDIAN_TAG));
74            out.annotate(4, "link_size:       0");
75            out.annotate(4, "link_off:        0");
76            out.annotate(4, "map_off:         " + Hex.u4(mapOff));
77        }
78
79        // Write the magic number.
80        for (int i = 0; i < 8; i++) {
81            out.writeByte(magic.charAt(i));
82        }
83
84        // Leave space for the checksum and signature.
85        out.writeZeroes(24);
86
87        out.writeInt(file.getFileSize());
88        out.writeInt(SizeOf.HEADER_ITEM);
89        out.writeInt(DexFormat.ENDIAN_TAG);
90
91        /*
92         * Write zeroes for the link size and data, as the output
93         * isn't a staticly linked file.
94         */
95        out.writeZeroes(8);
96
97        out.writeInt(mapOff);
98
99        // Write out each section's respective header part.
100        file.getStringIds().writeHeaderPart(out);
101        file.getTypeIds().writeHeaderPart(out);
102        file.getProtoIds().writeHeaderPart(out);
103        file.getFieldIds().writeHeaderPart(out);
104        file.getMethodIds().writeHeaderPart(out);
105        file.getClassDefs().writeHeaderPart(out);
106
107        if (out.annotates()) {
108            out.annotate(4, "data_size:       " + Hex.u4(dataSize));
109            out.annotate(4, "data_off:        " + Hex.u4(dataOff));
110        }
111
112        out.writeInt(dataSize);
113        out.writeInt(dataOff);
114    }
115}
116