--- /dev/null
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dexgen.dex.file;
+
+import com.android.dexgen.rop.cst.CstUtf8;
+import com.android.dexgen.util.AnnotatedOutput;
+import com.android.dexgen.util.Hex;
+
+/**
+ * File header section of a {@code .dex} file.
+ */
+public final class HeaderItem extends IndexedItem {
+ /**
+ * {@code non-null;} the file format magic number, represented as the
+ * low-order bytes of a string
+ */
+ private static final String MAGIC = "dex\n035\0";
+
+ /** size of this section, in bytes */
+ private static final int HEADER_SIZE = 0x70;
+
+ /** the endianness tag */
+ private static final int ENDIAN_TAG = 0x12345678;
+
+ /**
+ * Constructs an instance.
+ */
+ public HeaderItem() {
+ // This space intentionally left blank.
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ItemType itemType() {
+ return ItemType.TYPE_HEADER_ITEM;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int writeSize() {
+ return HEADER_SIZE;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void addContents(DexFile file) {
+ // Nothing to do here.
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void writeTo(DexFile file, AnnotatedOutput out) {
+ int mapOff = file.getMap().getFileOffset();
+ Section firstDataSection = file.getFirstDataSection();
+ Section lastDataSection = file.getLastDataSection();
+ int dataOff = firstDataSection.getFileOffset();
+ int dataSize = lastDataSection.getFileOffset() +
+ lastDataSection.writeSize() - dataOff;
+
+ if (out.annotates()) {
+ out.annotate(8, "magic: " + new CstUtf8(MAGIC).toQuoted());
+ out.annotate(4, "checksum");
+ out.annotate(20, "signature");
+ out.annotate(4, "file_size: " +
+ Hex.u4(file.getFileSize()));
+ out.annotate(4, "header_size: " + Hex.u4(HEADER_SIZE));
+ out.annotate(4, "endian_tag: " + Hex.u4(ENDIAN_TAG));
+ out.annotate(4, "link_size: 0");
+ out.annotate(4, "link_off: 0");
+ out.annotate(4, "map_off: " + Hex.u4(mapOff));
+ }
+
+ // Write the magic number.
+ for (int i = 0; i < 8; i++) {
+ out.writeByte(MAGIC.charAt(i));
+ }
+
+ // Leave space for the checksum and signature.
+ out.writeZeroes(24);
+
+ out.writeInt(file.getFileSize());
+ out.writeInt(HEADER_SIZE);
+ out.writeInt(ENDIAN_TAG);
+
+ /*
+ * Write zeroes for the link size and data, as the output
+ * isn't a staticly linked file.
+ */
+ out.writeZeroes(8);
+
+ out.writeInt(mapOff);
+
+ // Write out each section's respective header part.
+ file.getStringIds().writeHeaderPart(out);
+ file.getTypeIds().writeHeaderPart(out);
+ file.getProtoIds().writeHeaderPart(out);
+ file.getFieldIds().writeHeaderPart(out);
+ file.getMethodIds().writeHeaderPart(out);
+ file.getClassDefs().writeHeaderPart(out);
+
+ if (out.annotates()) {
+ out.annotate(4, "data_size: " + Hex.u4(dataSize));
+ out.annotate(4, "data_off: " + Hex.u4(dataOff));
+ }
+
+ out.writeInt(dataSize);
+ out.writeInt(dataOff);
+ }
+}