Separate vdex versioning into two sections: verifier deps and dex code.

The layout is still the same, but this CL allows updating the cdex and
quickening encoding versions without having to update the verifier deps
version.

bug: 63920015
Test: test.py, dex2oat_test, oat_writer_test, oatdump_test
Change-Id: Ifd282b4c1856f7597d8d26577bf58b9ad87da084
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 73afbad..9b6771d 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1398,8 +1398,8 @@
       std::unique_ptr<linker::BufferedOutputStream> vdex_out =
           std::make_unique<linker::BufferedOutputStream>(
               std::make_unique<linker::FileOutputStream>(vdex_files_.back().get()));
-      if (!vdex_out->WriteFully(&VdexFile::Header::kVdexInvalidMagic,
-                                arraysize(VdexFile::Header::kVdexInvalidMagic))) {
+      if (!vdex_out->WriteFully(&VdexFile::VerifierDepsHeader::kVdexInvalidMagic,
+                                arraysize(VdexFile::VerifierDepsHeader::kVdexInvalidMagic))) {
         PLOG(ERROR) << "Failed to invalidate vdex header. File: " << vdex_out->GetLocation();
         return false;
       }
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 96dd319..094dfee 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -1834,7 +1834,7 @@
                                                   /*unquicken*/ false,
                                                   &error_msg));
     ASSERT_TRUE(vdex != nullptr);
-    EXPECT_EQ(vdex->GetHeader().GetDexSize(), 0u) << output_;
+    EXPECT_FALSE(vdex->HasDexSection()) << output_;
   }
   std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
                                                    odex_location.c_str(),
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index c72beea..089aa80 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -555,8 +555,9 @@
                                       const char* location,
                                       CreateTypeLookupTable create_type_lookup_table) {
   DCHECK(write_state_ == WriteState::kAddingDexFileSources);
+  DCHECK(vdex_file.HasDexSection());
   const uint8_t* current_dex_data = nullptr;
-  for (size_t i = 0; i < vdex_file.GetHeader().GetNumberOfDexFiles(); ++i) {
+  for (size_t i = 0; i < vdex_file.GetVerifierDepsHeader().GetNumberOfDexFiles(); ++i) {
     current_dex_data = vdex_file.GetNextDexFileData(current_dex_data);
     if (current_dex_data == nullptr) {
       LOG(ERROR) << "Unexpected number of dex files in vdex " << location;
@@ -659,7 +660,8 @@
   // Initialize VDEX and OAT headers.
 
   // Reserve space for Vdex header and checksums.
-  vdex_size_ = sizeof(VdexFile::Header) + oat_dex_files_.size() * sizeof(VdexFile::VdexChecksum);
+  vdex_size_ = sizeof(VdexFile::VerifierDepsHeader) +
+      oat_dex_files_.size() * sizeof(VdexFile::VdexChecksum);
   oat_size_ = InitOatHeader(instruction_set,
                             instruction_set_features,
                             dchecked_integral_cast<uint32_t>(oat_dex_files_.size()),
@@ -3333,8 +3335,6 @@
                               CopyOption copy_dex_files) {
   TimingLogger::ScopedTiming split("Write Dex files", timings_);
 
-  vdex_dex_files_offset_ = vdex_size_;
-
   // If extraction is enabled, only do it if not all the dex files are aligned and uncompressed.
   if (copy_dex_files == CopyOption::kOnlyIfCompressed) {
     extract_dex_files_into_vdex_ = false;
@@ -3357,6 +3357,9 @@
   }
 
   if (extract_dex_files_into_vdex_) {
+    // Add the dex section header.
+    vdex_size_ += sizeof(VdexFile::DexSectionHeader);
+    vdex_dex_files_offset_ = vdex_size_;
     // Write dex files.
     for (OatDexFile& oat_dex_file : oat_dex_files_) {
       if (!WriteDexFile(out, file, &oat_dex_file, update_input_vdex)) {
@@ -4076,8 +4079,9 @@
 
 bool OatWriter::WriteChecksumsAndVdexHeader(OutputStream* vdex_out) {
   // Write checksums
-  off_t actual_offset = vdex_out->Seek(sizeof(VdexFile::Header), kSeekSet);
-  if (actual_offset != sizeof(VdexFile::Header)) {
+  off_t checksums_offset = sizeof(VdexFile::VerifierDepsHeader);
+  off_t actual_offset = vdex_out->Seek(checksums_offset, kSeekSet);
+  if (actual_offset != checksums_offset) {
     PLOG(ERROR) << "Failed to seek to the checksum location of vdex file. Actual: " << actual_offset
                 << " File: " << vdex_out->GetLocation();
     return false;
@@ -4094,6 +4098,27 @@
     size_vdex_checksums_ += sizeof(VdexFile::VdexChecksum);
   }
 
+  // Maybe write dex section header.
+  DCHECK_NE(vdex_verifier_deps_offset_, 0u);
+  DCHECK_NE(vdex_quickening_info_offset_, 0u);
+
+  bool has_dex_section = extract_dex_files_into_vdex_;
+  if (has_dex_section) {
+    DCHECK_NE(vdex_dex_files_offset_, 0u);
+    size_t dex_section_size = vdex_dex_shared_data_offset_ - vdex_dex_files_offset_;
+    size_t dex_shared_data_size = vdex_verifier_deps_offset_ - vdex_dex_shared_data_offset_;
+    size_t quickening_info_section_size = vdex_size_ - vdex_quickening_info_offset_;
+
+    VdexFile::DexSectionHeader dex_section_header(dex_section_size,
+                                                  dex_shared_data_size,
+                                                  quickening_info_section_size);
+    if (!vdex_out->WriteFully(&dex_section_header, sizeof(VdexFile::DexSectionHeader))) {
+      PLOG(ERROR) << "Failed to write vdex header. File: " << vdex_out->GetLocation();
+      return false;
+    }
+    size_vdex_header_ += sizeof(VdexFile::DexSectionHeader);
+  }
+
   // Write header.
   actual_offset = vdex_out->Seek(0, kSeekSet);
   if (actual_offset != 0) {
@@ -4102,25 +4127,15 @@
     return false;
   }
 
-  DCHECK_NE(vdex_dex_files_offset_, 0u);
-  DCHECK_NE(vdex_verifier_deps_offset_, 0u);
-  DCHECK_NE(vdex_quickening_info_offset_, 0u);
-
-  size_t dex_section_size = vdex_dex_shared_data_offset_ - vdex_dex_files_offset_;
-  size_t dex_shared_data_size = vdex_verifier_deps_offset_ - vdex_dex_shared_data_offset_;
   size_t verifier_deps_section_size = vdex_quickening_info_offset_ - vdex_verifier_deps_offset_;
-  size_t quickening_info_section_size = vdex_size_ - vdex_quickening_info_offset_;
 
-  VdexFile::Header vdex_header(oat_dex_files_.size(),
-                               dex_section_size,
-                               dex_shared_data_size,
-                               verifier_deps_section_size,
-                               quickening_info_section_size);
-  if (!vdex_out->WriteFully(&vdex_header, sizeof(VdexFile::Header))) {
+  VdexFile::VerifierDepsHeader deps_header(
+      oat_dex_files_.size(), verifier_deps_section_size, has_dex_section);
+  if (!vdex_out->WriteFully(&deps_header, sizeof(VdexFile::VerifierDepsHeader))) {
     PLOG(ERROR) << "Failed to write vdex header. File: " << vdex_out->GetLocation();
     return false;
   }
-  size_vdex_header_ = sizeof(VdexFile::Header);
+  size_vdex_header_ += sizeof(VdexFile::VerifierDepsHeader);
 
   if (!vdex_out->Flush()) {
     PLOG(ERROR) << "Failed to flush stream after writing to vdex file."
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index 00b9abe..0148a57 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -663,7 +663,8 @@
                       dex_file2_data->GetHeader().file_size_));
   ASSERT_EQ(dex_file2_data->GetLocation(), opened_dex_file2->GetLocation());
 
-  const VdexFile::Header &vdex_header = opened_oat_file->GetVdexFile()->GetHeader();
+  const VdexFile::DexSectionHeader &vdex_header =
+      opened_oat_file->GetVdexFile()->GetDexSectionHeader();
   if (!compiler_driver_->GetCompilerOptions().IsQuickeningCompilationEnabled()) {
     // If quickening is enabled we will always write the table since there is no special logic that
     // checks for all methods not being quickened (not worth the complexity).
@@ -672,7 +673,7 @@
 
   int64_t actual_vdex_size = vdex_file.GetFile()->GetLength();
   ASSERT_GE(actual_vdex_size, 0);
-  ASSERT_EQ((uint64_t) actual_vdex_size, vdex_header.GetComputedFileSize());
+  ASSERT_EQ((uint64_t) actual_vdex_size, opened_oat_file->GetVdexFile()->GetComputedFileSize());
 }
 
 TEST_F(OatTest, DexFileInputCheckOutput) {