Update DEX container generation
Include container size in the header of each section.
Bug: b/249922554
Change-Id: Ie34fb729abc04cf7245e4bf544584017f3cc7173
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index eda00f9..b58107d 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -390,7 +390,7 @@
assert tmp.getDexVersion() == DexVersion.V41;
assert dexReader.getUint(offset + Constants.HEADER_SIZE_OFFSET)
== Constants.TYPE_HEADER_ITEM_SIZE_V41;
- assert dexReader.getUint(offset + Constants.HEADER_OFF_OFFSET) == offset;
+ assert dexReader.getUint(offset + Constants.CONTAINER_OFF_OFFSET) == offset;
int dataSize = dexReader.getUint(offset + Constants.DATA_SIZE_OFFSET);
int dataOffset = dexReader.getUint(offset + Constants.DATA_OFF_OFFSET);
int file_size = dexReader.getUint(offset + Constants.FILE_SIZE_OFFSET);
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
index 0a81bd2..853d01e 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
@@ -183,7 +183,11 @@
DexContainerSection lastSection = ListUtils.last(sections);
int stringIdsSize = lastSection.getFileWriter().getMixedSectionOffsets().getStringData().size();
int stringIdsOffset = lastSection.getLayout().stringIdsOffset;
+ int containerSize = lastSection.getLayout().getEndOfFile();
for (DexContainerSection section : sections) {
+ // Update container size in all sections.
+ dexOutputBuffer.moveTo(section.getLayout().headerOffset + Constants.CONTAINER_SIZE_OFFSET);
+ dexOutputBuffer.putInt(containerSize);
if (section != lastSection) {
// Update the string_ids size and offset in the header.
dexOutputBuffer.moveTo(section.getLayout().headerOffset + Constants.STRING_IDS_SIZE_OFFSET);
diff --git a/src/main/java/com/android/tools/r8/dex/Constants.java b/src/main/java/com/android/tools/r8/dex/Constants.java
index 912f4f1..9de8120 100644
--- a/src/main/java/com/android/tools/r8/dex/Constants.java
+++ b/src/main/java/com/android/tools/r8/dex/Constants.java
@@ -45,14 +45,15 @@
public static final int CLASS_DEFS_OFF_OFFSET = CLASS_DEFS_SIZE_OFFSET + 4;
public static final int DATA_SIZE_OFFSET = CLASS_DEFS_OFF_OFFSET + 4;
public static final int DATA_OFF_OFFSET = DATA_SIZE_OFFSET + 4;
- public static final int HEADER_OFF_OFFSET = DATA_OFF_OFFSET + 4;
+ public static final int CONTAINER_SIZE_OFFSET = DATA_OFF_OFFSET + 4;
+ public static final int CONTAINER_OFF_OFFSET = CONTAINER_SIZE_OFFSET + 4;
public static final int ENDIAN_CONSTANT = 0x12345678;
public static final int REVERSE_ENDIAN_CONSTANT = 0x78563412;
public static final int TYPE_HEADER_ITEM = 0x0;
public static final int TYPE_HEADER_ITEM_SIZE = 0x70;
- public static final int TYPE_HEADER_ITEM_SIZE_V41 = 0x74;
+ public static final int TYPE_HEADER_ITEM_SIZE_V41 = 0x78;
public static final int TYPE_STRING_ID_ITEM = 0x0001;
public static final int TYPE_STRING_ID_ITEM_SIZE = 0x04;
public static final int TYPE_TYPE_ID_ITEM = 0x0002;
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index 25d19b0..8c6f33a 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -825,9 +825,11 @@
dest.putInt(numberOfClasses);
dest.putInt(numberOfClasses == 0 ? 0 : layout.classDefsOffset);
if (layout.isContainerSection()) {
- dest.putInt(0);
- dest.putInt(0);
- dest.putInt(layout.headerOffset);
+ // Fields data_size and data_off are zero for all sections in a container DEX.
+ dest.putInt(0); // data_size
+ dest.putInt(0); // data_off
+ dest.putInt(0); // container_size will be updated in final pass.
+ dest.putInt(layout.headerOffset); // container_off
} else {
dest.putInt(layout.getDataSectionSize());
dest.putInt(layout.dataSectionOffset);
diff --git a/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java b/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java
index 25b028a..81d709c9 100644
--- a/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java
+++ b/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java
@@ -4,11 +4,12 @@
package com.android.tools.r8.dex.container;
import static com.android.tools.r8.dex.Constants.CHECKSUM_OFFSET;
+import static com.android.tools.r8.dex.Constants.CONTAINER_OFF_OFFSET;
+import static com.android.tools.r8.dex.Constants.CONTAINER_SIZE_OFFSET;
import static com.android.tools.r8.dex.Constants.DATA_OFF_OFFSET;
import static com.android.tools.r8.dex.Constants.DATA_SIZE_OFFSET;
import static com.android.tools.r8.dex.Constants.DEX_MAGIC_SIZE;
import static com.android.tools.r8.dex.Constants.FILE_SIZE_OFFSET;
-import static com.android.tools.r8.dex.Constants.HEADER_OFF_OFFSET;
import static com.android.tools.r8.dex.Constants.HEADER_SIZE_OFFSET;
import static com.android.tools.r8.dex.Constants.MAP_OFF_OFFSET;
import static com.android.tools.r8.dex.Constants.SIGNATURE_OFFSET;
@@ -260,7 +261,8 @@
assertEquals(0, buffer.getInt(offset + DATA_SIZE_OFFSET));
assertEquals(0, buffer.getInt(offset + DATA_OFF_OFFSET));
// Additional header field from V41.
- assertEquals(offset, buffer.getInt(offset + HEADER_OFF_OFFSET));
+ assertEquals(buffer.capacity(), buffer.getInt(offset + CONTAINER_SIZE_OFFSET));
+ assertEquals(offset, buffer.getInt(offset + CONTAINER_OFF_OFFSET));
}
assertEquals(stringIdsSize, getSizeFromMap(TYPE_STRING_ID_ITEM, buffer, offset));
assertEquals(stringIdsOffset, getOffsetFromMap(TYPE_STRING_ID_ITEM, buffer, offset));