Be defensive in dex2oat when updating the vdex in-place.

Invalidate the vdex header before doing any writing, in case
dex2oat gets killed in the middle.

bug: 38113240
Test: test.py --speed-profile
Test: test.py 629-vdex

Change-Id: I4c04ba36db5f6a7066bb6695885e6ae5082d34fb
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 58f3948..660409f 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1374,6 +1374,26 @@
       oat_filenames_.push_back(oat_location_.c_str());
     }
 
+    // If we're updating in place a vdex file, be defensive and put an invalid vdex magic in case
+    // dex2oat gets killed.
+    // Note: we're only invalidating the magic data in the file, as dex2oat needs the rest of
+    // the information to remain valid.
+    if (update_input_vdex_) {
+      std::unique_ptr<BufferedOutputStream> vdex_out(MakeUnique<BufferedOutputStream>(
+          MakeUnique<FileOutputStream>(vdex_files_.back().get())));
+      if (!vdex_out->WriteFully(&VdexFile::Header::kVdexInvalidMagic,
+                                arraysize(VdexFile::Header::kVdexInvalidMagic))) {
+        PLOG(ERROR) << "Failed to invalidate vdex header. File: " << vdex_out->GetLocation();
+        return false;
+      }
+
+      if (!vdex_out->Flush()) {
+        PLOG(ERROR) << "Failed to flush stream after invalidating header of vdex file."
+                    << " File: " << vdex_out->GetLocation();
+        return false;
+      }
+    }
+
     // Swap file handling
     //
     // If the swap fd is not -1, we assume this is the file descriptor of an open but unlinked file
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index e93f04d..842aa04 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -28,6 +28,7 @@
 
 namespace art {
 
+constexpr uint8_t VdexFile::Header::kVdexInvalidMagic[4];
 constexpr uint8_t VdexFile::Header::kVdexMagic[4];
 constexpr uint8_t VdexFile::Header::kVdexVersion[4];
 
diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h
index 9c0d9db..ece5491 100644
--- a/runtime/vdex_file.h
+++ b/runtime/vdex_file.h
@@ -61,6 +61,8 @@
     uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; }
     uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; }
 
+    static constexpr uint8_t kVdexInvalidMagic[] = { 'w', 'd', 'e', 'x' };
+
    private:
     static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' };
     static constexpr uint8_t kVdexVersion[] = { '0', '0', '5', '\0' };  // access flags