Merge art-cache dex files into oat files

Change-Id: I5a327a4e0b678bd9dabb12de4e21ef05e3fefd0b
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 32ba4b1..3ab2fb9 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -29,6 +29,7 @@
 
   size_t offset = InitOatHeader();
   offset = InitOatDexFiles(offset);
+  offset = InitDexFiles(offset);
   offset = InitOatClasses(offset);
   offset = InitOatMethods(offset);
   offset = InitOatCode(offset);
@@ -64,6 +65,21 @@
   return offset;
 }
 
+size_t OatWriter::InitDexFiles(size_t offset) {
+  // calculate the offsets within OatDexFiles to the DexFiles
+  for (size_t i = 0; i != dex_files_->size(); ++i) {
+    // dex files are required to be 4 byte aligned
+    offset = RoundUp(offset, 4);
+
+    // set offset in OatDexFile to DexFile
+    oat_dex_files_[i]->dex_file_offset_ = offset;
+
+    const DexFile* dex_file = (*dex_files_)[i];
+    offset += dex_file->GetHeader().file_size_;
+  }
+  return offset;
+}
+
 size_t OatWriter::InitOatClasses(size_t offset) {
   // create the OatClasses
   // calculate the offsets within OatDexFiles to OatClasses
@@ -305,7 +321,7 @@
 }
 
 #define DCHECK_CODE_OFFSET() \
-  DCHECK_EQ(static_cast<off_t>(code_offset), lseek(file->Fd(), 0, SEEK_CUR))
+  DCHECK_EQ(static_cast<off64_t>(code_offset), lseek64(file->Fd(), 0, SEEK_CUR))
 
 bool OatWriter::Write(File* file) {
   if (!file->WriteFully(oat_header_, sizeof(*oat_header_))) {
@@ -340,6 +356,21 @@
       return false;
     }
   }
+  for (size_t i = 0; i != oat_dex_files_.size(); ++i) {
+    uint32_t expected_offset = oat_dex_files_[i]->dex_file_offset_;
+    off64_t actual_offset = lseek64(file->Fd(), expected_offset, SEEK_SET);
+    if (static_cast<uint32_t>(actual_offset) != expected_offset) {
+      const DexFile* dex_file = (*dex_files_)[i];
+      PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset
+                  << " Expected: " << expected_offset << " File: " << dex_file->GetLocation();
+      return false;
+    }
+    const DexFile* dex_file = (*dex_files_)[i];
+    if (!file->WriteFully(&dex_file->GetHeader(), dex_file->GetHeader().file_size_)) {
+      PLOG(ERROR) << "Failed to write dex file " << dex_file->GetLocation() << " to " << file->name();
+      return false;
+    }
+  }
   for (size_t i = 0; i != oat_classes_.size(); ++i) {
     if (!oat_classes_[i]->Write(file)) {
       PLOG(ERROR) << "Failed to write oat classes information to " << file->name();
@@ -357,7 +388,7 @@
 
 size_t OatWriter::WriteCode(File* file) {
   uint32_t code_offset = oat_header_->GetExecutableOffset();
-  off_t new_offset = lseek(file->Fd(), executable_offset_padding_length_, SEEK_CUR);
+  off64_t new_offset = lseek64(file->Fd(), executable_offset_padding_length_, SEEK_CUR);
   if (static_cast<uint32_t>(new_offset) != code_offset) {
     PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset
                 << " Expected: " << code_offset << " File: " << file->name();
@@ -458,7 +489,7 @@
     uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset);
     uint32_t aligned_code_delta = aligned_code_offset - code_offset;
     if (aligned_code_delta != 0) {
-      off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
+      off64_t new_offset = lseek64(file->Fd(), aligned_code_delta, SEEK_CUR);
       if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
         PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset
                     << " Expected: " << aligned_code_offset << " File: " << file->name();
@@ -564,7 +595,7 @@
                                                              compiler_->GetInstructionSet());
     uint32_t aligned_code_delta = aligned_code_offset - code_offset;
     if (aligned_code_delta != 0) {
-      off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
+      off64_t new_offset = lseek64(file->Fd(), aligned_code_delta, SEEK_CUR);
       if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
         PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset
                     << " Expected: " << aligned_code_offset;
@@ -605,6 +636,7 @@
   dex_file_location_size_ = location.size();
   dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data());
   dex_file_checksum_ = dex_file.GetHeader().checksum_;
+  dex_file_offset_ = 0;
   classes_offset_ = 0;
 }
 
@@ -612,6 +644,7 @@
   return sizeof(dex_file_location_size_)
           + dex_file_location_size_
           + sizeof(dex_file_checksum_)
+          + sizeof(dex_file_offset_)
           + sizeof(classes_offset_);
 }
 
@@ -619,6 +652,7 @@
   oat_header.UpdateChecksum(&dex_file_location_size_, sizeof(dex_file_location_size_));
   oat_header.UpdateChecksum(dex_file_location_data_, dex_file_location_size_);
   oat_header.UpdateChecksum(&dex_file_checksum_, sizeof(dex_file_checksum_));
+  oat_header.UpdateChecksum(&dex_file_offset_, sizeof(dex_file_offset_));
   oat_header.UpdateChecksum(&classes_offset_, sizeof(classes_offset_));
 }
 
@@ -635,6 +669,10 @@
     PLOG(ERROR) << "Failed to write dex file checksum to " << file->name();
     return false;
   }
+  if (!file->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) {
+    PLOG(ERROR) << "Failed to write dex file offset to " << file->name();
+    return false;
+  }
   if (!file->WriteFully(&classes_offset_, sizeof(classes_offset_))) {
     PLOG(ERROR) << "Failed to write classes offset to " << file->name();
     return false;