Remove ExtractCodeAndPrelink and switch Portable to MCLinker

Change-Id: Ia2459c7da6b79e0a1c0f1148c6e28ad9cbbe27a2
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 1a269e9..e299a27 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -93,7 +93,7 @@
   for (size_t i = 0; i != dex_files_->size(); ++i) {
     const DexFile* dex_file = (*dex_files_)[i];
     CHECK(dex_file != NULL);
-    OatDexFile* oat_dex_file = new OatDexFile(*dex_file);
+    OatDexFile* oat_dex_file = new OatDexFile(offset, *dex_file);
     oat_dex_files_.push_back(oat_dex_file);
     offset += oat_dex_file->SizeOf();
   }
@@ -145,7 +145,7 @@
         status = mirror::Class::kStatusNotReady;
       }
 
-      OatClass* oat_class = new OatClass(status, num_methods);
+      OatClass* oat_class = new OatClass(offset, status, num_methods);
       oat_classes_.push_back(oat_class);
       offset += oat_class->SizeOf();
     }
@@ -232,7 +232,7 @@
                                     size_t __attribute__((unused)) class_def_index,
                                     size_t class_def_method_index,
                                     bool __attribute__((unused)) is_native,
-                                    InvokeType type,
+                                    InvokeType invoke_type,
                                     uint32_t method_idx, const DexFile* dex_file) {
   // derived from CompiledMethod if available
   uint32_t code_offset = 0;
@@ -248,12 +248,22 @@
   uint32_t proxy_stub_offset = 0;
 #endif
 
+  OatClass* oat_class = oat_classes_[oat_class_index];
+#if defined(ART_USE_PORTABLE_COMPILER)
+  size_t oat_method_offsets_offset =
+      oat_class->GetOatMethodOffsetsOffsetFromOatHeader(class_def_method_index);
+#endif
+
   CompiledMethod* compiled_method =
       compiler_driver_->GetCompiledMethod(CompilerDriver::MethodReference(dex_file, method_idx));
   if (compiled_method != NULL) {
+#if defined(ART_USE_PORTABLE_COMPILER)
+    compiled_method->AddOatdataOffsetToCompliledCodeOffset(
+        oat_method_offsets_offset + OFFSETOF_MEMBER(OatMethodOffsets, code_offset_));
+#else
+    const std::vector<uint8_t>& code = compiled_method->GetCode();
     offset = compiled_method->AlignCode(offset);
     DCHECK_ALIGNED(offset, kArmAlignment);
-    const std::vector<uint8_t>& code = compiled_method->GetCode();
     uint32_t code_size = code.size() * sizeof(code[0]);
     CHECK_NE(code_size, 0U);
     uint32_t thumb_offset = compiled_method->CodeDelta();
@@ -269,6 +279,7 @@
       offset += code_size;
       oat_header_->UpdateChecksum(&code[0], code_size);
     }
+#endif
     frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
     core_spill_mask = compiled_method->GetCoreSpillMask();
     fp_spill_mask = compiled_method->GetFpSpillMask();
@@ -335,12 +346,16 @@
   }
 
   const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx));
-  const CompiledInvokeStub* compiled_invoke_stub = compiler_driver_->FindInvokeStub(type == kStatic,
-                                                                             shorty);
+  CompiledInvokeStub* compiled_invoke_stub = compiler_driver_->FindInvokeStub(invoke_type == kStatic,
+                                                                              shorty);
   if (compiled_invoke_stub != NULL) {
+#if defined(ART_USE_PORTABLE_COMPILER)
+    compiled_invoke_stub->AddOatdataOffsetToCompliledCodeOffset(
+        oat_method_offsets_offset + OFFSETOF_MEMBER(OatMethodOffsets, invoke_stub_offset_));
+#else
+    const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
     offset = CompiledMethod::AlignCode(offset, compiler_driver_->GetInstructionSet());
     DCHECK_ALIGNED(offset, kArmAlignment);
-    const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
     uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
     CHECK_NE(invoke_stub_size, 0U);
     uint32_t thumb_offset = compiled_invoke_stub->CodeDelta();
@@ -356,35 +371,20 @@
       offset += invoke_stub_size;
       oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size);
     }
+#endif
   }
 
 #if defined(ART_USE_PORTABLE_COMPILER)
-  if (type != kStatic) {
-    const CompiledInvokeStub* compiled_proxy_stub = compiler_driver_->FindProxyStub(shorty);
+  if (invoke_type != kStatic) {
+    CompiledInvokeStub* compiled_proxy_stub = compiler_driver_->FindProxyStub(shorty);
     if (compiled_proxy_stub != NULL) {
-      offset = CompiledMethod::AlignCode(offset, compiler_driver_->GetInstructionSet());
-      DCHECK_ALIGNED(offset, kArmAlignment);
-      const std::vector<uint8_t>& proxy_stub = compiled_proxy_stub->GetCode();
-      uint32_t proxy_stub_size = proxy_stub.size() * sizeof(proxy_stub[0]);
-      CHECK_NE(proxy_stub_size, 0U);
-      uint32_t thumb_offset = compiled_proxy_stub->CodeDelta();
-      proxy_stub_offset = offset + sizeof(proxy_stub_size) + thumb_offset;
-
-      // Deduplicate proxy stubs
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&proxy_stub);
-      if (stub_iter != code_offsets_.end()) {
-        proxy_stub_offset = stub_iter->second;
-      } else {
-        code_offsets_.Put(&proxy_stub, proxy_stub_offset);
-        offset += sizeof(proxy_stub_size);  // proxy stub size is prepended before code
-        offset += proxy_stub_size;
-        oat_header_->UpdateChecksum(&proxy_stub[0], proxy_stub_size);
-      }
+      compiled_proxy_stub->AddOatdataOffsetToCompliledCodeOffset(
+          oat_method_offsets_offset + OFFSETOF_MEMBER(OatMethodOffsets, proxy_stub_offset_));
     }
   }
 #endif
 
-  oat_classes_[oat_class_index]->method_offsets_[class_def_method_index]
+  oat_class->method_offsets_[class_def_method_index]
       = OatMethodOffsets(code_offset,
                          frame_size_in_bytes,
                          core_spill_mask,
@@ -404,7 +404,7 @@
     // Unchecked as we hold mutator_lock_ on entry.
     ScopedObjectAccessUnchecked soa(Thread::Current());
     mirror::AbstractMethod* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache,
-                                                           NULL, NULL, type);
+                                                           NULL, NULL, invoke_type);
     CHECK(method != NULL);
     method->SetFrameSizeInBytes(frame_size_in_bytes);
     method->SetCoreSpillMask(core_spill_mask);
@@ -425,8 +425,11 @@
   return offset;
 }
 
-#define DCHECK_CODE_OFFSET() \
-  DCHECK_EQ(static_cast<off_t>(code_offset), out.Seek(0, kSeekCurrent))
+#define DCHECK_OFFSET() \
+  DCHECK_EQ(static_cast<off_t>(offset), out.Seek(0, kSeekCurrent))
+
+#define DCHECK_OFFSET_() \
+  DCHECK_EQ(static_cast<off_t>(offset_), out.Seek(0, kSeekCurrent))
 
 bool OatWriter::Write(OutputStream& out) {
   if (!out.WriteFully(oat_header_, sizeof(*oat_header_))) {
@@ -491,15 +494,15 @@
 }
 
 size_t OatWriter::WriteCode(OutputStream& out) {
-  uint32_t code_offset = oat_header_->GetExecutableOffset();
+  uint32_t offset = oat_header_->GetExecutableOffset();
   off_t new_offset = out.Seek(executable_offset_padding_length_, kSeekCurrent);
-  if (static_cast<uint32_t>(new_offset) != code_offset) {
+  if (static_cast<uint32_t>(new_offset) != offset) {
     PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset
-                << " Expected: " << code_offset << " File: " << out.GetLocation();
+                << " Expected: " << offset << " File: " << out.GetLocation();
     return 0;
   }
-  DCHECK_CODE_OFFSET();
-  return code_offset;
+  DCHECK_OFFSET();
+  return offset;
 }
 
 size_t OatWriter::WriteCodeDexFiles(OutputStream& out, size_t code_offset) {
@@ -575,7 +578,7 @@
   return code_offset;
 }
 
-size_t OatWriter::WriteCodeMethod(OutputStream& out, size_t code_offset, size_t oat_class_index,
+size_t OatWriter::WriteCodeMethod(OutputStream& out, size_t offset, size_t oat_class_index,
                                   size_t class_def_method_index, bool is_static,
                                   uint32_t method_idx, const DexFile& dex_file) {
   const CompiledMethod* compiled_method =
@@ -586,43 +589,46 @@
 
 
   if (compiled_method != NULL) {  // ie. not an abstract method
-    uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset);
-    uint32_t aligned_code_delta = aligned_code_offset - code_offset;
+#if !defined(ART_USE_PORTABLE_COMPILER)
+    uint32_t aligned_offset = compiled_method->AlignCode(offset);
+    uint32_t aligned_code_delta = aligned_offset - offset;
     if (aligned_code_delta != 0) {
       off_t new_offset = out.Seek(aligned_code_delta, kSeekCurrent);
-      if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
+      if (static_cast<uint32_t>(new_offset) != aligned_offset) {
         PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset
-                    << " Expected: " << aligned_code_offset << " File: " << out.GetLocation();
+                    << " Expected: " << aligned_offset << " File: " << out.GetLocation();
         return 0;
       }
-      code_offset += aligned_code_delta;
-      DCHECK_CODE_OFFSET();
+      offset += aligned_code_delta;
+      DCHECK_OFFSET();
     }
-    DCHECK_ALIGNED(code_offset, kArmAlignment);
+    DCHECK_ALIGNED(offset, kArmAlignment);
     const std::vector<uint8_t>& code = compiled_method->GetCode();
     uint32_t code_size = code.size() * sizeof(code[0]);
     CHECK_NE(code_size, 0U);
 
     // Deduplicate code arrays
-    size_t offset = code_offset + sizeof(code_size) + compiled_method->CodeDelta();
+    size_t code_offset = offset + sizeof(code_size) + compiled_method->CodeDelta();
     SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
-    if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) {
-      DCHECK(code_iter->second == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
+    if (code_iter != code_offsets_.end() && code_offset != method_offsets.code_offset_) {
+      DCHECK(code_iter->second == method_offsets.code_offset_)
+          << PrettyMethod(method_idx, dex_file);
     } else {
-      DCHECK(offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
+      DCHECK(code_offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
       if (!out.WriteFully(&code_size, sizeof(code_size))) {
         ReportWriteFailure("method code size", method_idx, dex_file, out);
         return 0;
       }
-      code_offset += sizeof(code_size);
-      DCHECK_CODE_OFFSET();
+      offset += sizeof(code_size);
+      DCHECK_OFFSET();
       if (!out.WriteFully(&code[0], code_size)) {
         ReportWriteFailure("method code", method_idx, dex_file, out);
         return 0;
       }
-      code_offset += code_size;
+      offset += code_size;
     }
-    DCHECK_CODE_OFFSET();
+    DCHECK_OFFSET();
+#endif
 
     const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
     size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
@@ -631,21 +637,21 @@
     SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter =
         mapping_table_offsets_.find(&mapping_table);
     if (mapping_iter != mapping_table_offsets_.end() &&
-        code_offset != method_offsets.mapping_table_offset_) {
+        offset != method_offsets.mapping_table_offset_) {
       DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
           || mapping_iter->second == method_offsets.mapping_table_offset_)
           << PrettyMethod(method_idx, dex_file);
     } else {
       DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
-          || code_offset == method_offsets.mapping_table_offset_)
+          || offset == method_offsets.mapping_table_offset_)
           << PrettyMethod(method_idx, dex_file);
       if (!out.WriteFully(&mapping_table[0], mapping_table_size)) {
         ReportWriteFailure("mapping table", method_idx, dex_file, out);
         return 0;
       }
-      code_offset += mapping_table_size;
+      offset += mapping_table_size;
     }
-    DCHECK_CODE_OFFSET();
+    DCHECK_OFFSET();
 
     const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
     size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
@@ -654,21 +660,21 @@
     SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter =
         vmap_table_offsets_.find(&vmap_table);
     if (vmap_iter != vmap_table_offsets_.end() &&
-        code_offset != method_offsets.vmap_table_offset_) {
+        offset != method_offsets.vmap_table_offset_) {
       DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
           || vmap_iter->second == method_offsets.vmap_table_offset_)
           << PrettyMethod(method_idx, dex_file);
     } else {
       DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
-          || code_offset == method_offsets.vmap_table_offset_)
+          || offset == method_offsets.vmap_table_offset_)
           << PrettyMethod(method_idx, dex_file);
       if (!out.WriteFully(&vmap_table[0], vmap_table_size)) {
         ReportWriteFailure("vmap table", method_idx, dex_file, out);
         return 0;
       }
-      code_offset += vmap_table_size;
+      offset += vmap_table_size;
     }
-    DCHECK_CODE_OFFSET();
+    DCHECK_OFFSET();
 
     const std::vector<uint8_t>& gc_map = compiled_method->GetNativeGcMap();
     size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
@@ -677,119 +683,76 @@
     SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter =
         gc_map_offsets_.find(&gc_map);
     if (gc_map_iter != gc_map_offsets_.end() &&
-        code_offset != method_offsets.gc_map_offset_) {
+        offset != method_offsets.gc_map_offset_) {
       DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
           || gc_map_iter->second == method_offsets.gc_map_offset_)
           << PrettyMethod(method_idx, dex_file);
     } else {
       DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
-          || code_offset == method_offsets.gc_map_offset_)
+          || offset == method_offsets.gc_map_offset_)
           << PrettyMethod(method_idx, dex_file);
       if (!out.WriteFully(&gc_map[0], gc_map_size)) {
         ReportWriteFailure("GC map", method_idx, dex_file, out);
         return 0;
       }
-      code_offset += gc_map_size;
+      offset += gc_map_size;
     }
-    DCHECK_CODE_OFFSET();
+    DCHECK_OFFSET();
   }
+
+#if !defined(ART_USE_PORTABLE_COMPILER)
   const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
   const CompiledInvokeStub* compiled_invoke_stub = compiler_driver_->FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub != NULL) {
-    uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
-                                                             compiler_driver_->GetInstructionSet());
-    uint32_t aligned_code_delta = aligned_code_offset - code_offset;
+    uint32_t aligned_offset = CompiledMethod::AlignCode(offset,
+                                                        compiler_driver_->GetInstructionSet());
+    uint32_t aligned_code_delta = aligned_offset - offset;
     if (aligned_code_delta != 0) {
       off_t new_offset = out.Seek(aligned_code_delta, kSeekCurrent);
-      if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
+      if (static_cast<uint32_t>(new_offset) != aligned_offset) {
         PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset
-                    << " Expected: " << aligned_code_offset;
+                    << " Expected: " << aligned_offset;
         return 0;
       }
-      code_offset += aligned_code_delta;
-      DCHECK_CODE_OFFSET();
+      offset += aligned_code_delta;
+      DCHECK_OFFSET();
     }
-    DCHECK_ALIGNED(code_offset, kArmAlignment);
+    DCHECK_ALIGNED(offset, kArmAlignment);
     const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
     uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
     CHECK_NE(invoke_stub_size, 0U);
 
     // Deduplicate invoke stubs
-    size_t offset = code_offset + sizeof(invoke_stub_size) + compiled_invoke_stub->CodeDelta();
+    size_t invoke_stub_offset = offset + sizeof(invoke_stub_size) + compiled_invoke_stub->CodeDelta();
     SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
         code_offsets_.find(&invoke_stub);
-    if (stub_iter != code_offsets_.end() && offset != method_offsets.invoke_stub_offset_) {
-      DCHECK(stub_iter->second == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
+    if (stub_iter != code_offsets_.end()
+        && invoke_stub_offset != method_offsets.invoke_stub_offset_) {
+      DCHECK(stub_iter->second == method_offsets.invoke_stub_offset_)
+          << PrettyMethod(method_idx, dex_file);
     } else {
-      DCHECK(offset == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
+      DCHECK(invoke_stub_offset == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
       if (!out.WriteFully(&invoke_stub_size, sizeof(invoke_stub_size))) {
         ReportWriteFailure("invoke stub code size", method_idx, dex_file, out);
         return 0;
       }
-      code_offset += sizeof(invoke_stub_size);
-      DCHECK_CODE_OFFSET();
+      offset += sizeof(invoke_stub_size);
+      DCHECK_OFFSET();
       if (!out.WriteFully(&invoke_stub[0], invoke_stub_size)) {
         ReportWriteFailure("invoke stub code", method_idx, dex_file, out);
         return 0;
       }
-      code_offset += invoke_stub_size;
-      DCHECK_CODE_OFFSET();
-    }
-  }
-
-#if defined(ART_USE_PORTABLE_COMPILER)
-  if (!is_static) {
-    const CompiledInvokeStub* compiled_proxy_stub = compiler_driver_->FindProxyStub(shorty);
-    if (compiled_proxy_stub != NULL) {
-      uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
-                                                               compiler_driver_->GetInstructionSet());
-      uint32_t aligned_code_delta = aligned_code_offset - code_offset;
-      CHECK(aligned_code_delta < 48u);
-      if (aligned_code_delta != 0) {
-        off_t new_offset = out.Seek(aligned_code_delta, kSeekCurrent);
-        if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
-          PLOG(ERROR) << "Failed to seek to align proxy stub code. Actual: " << new_offset
-                      << " Expected: " << aligned_code_offset;
-          return 0;
-        }
-        code_offset += aligned_code_delta;
-        DCHECK_CODE_OFFSET();
-      }
-      DCHECK_ALIGNED(code_offset, kArmAlignment);
-      const std::vector<uint8_t>& proxy_stub = compiled_proxy_stub->GetCode();
-      uint32_t proxy_stub_size = proxy_stub.size() * sizeof(proxy_stub[0]);
-      CHECK_NE(proxy_stub_size, 0U);
-
-      // Deduplicate proxy stubs
-      size_t offset = code_offset + sizeof(proxy_stub_size) + compiled_proxy_stub->CodeDelta();
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
-          code_offsets_.find(&proxy_stub);
-      if (stub_iter != code_offsets_.end() && offset != method_offsets.proxy_stub_offset_) {
-        DCHECK(stub_iter->second == method_offsets.proxy_stub_offset_) << PrettyMethod(method_idx, dex_file);
-      } else {
-        DCHECK(offset == method_offsets.proxy_stub_offset_) << PrettyMethod(method_idx, dex_file);
-        if (!out.WriteFully(&proxy_stub_size, sizeof(proxy_stub_size))) {
-          ReportWriteFailure("proxy stub code size", method_idx, dex_file, out);
-          return 0;
-        }
-        code_offset += sizeof(proxy_stub_size);
-        DCHECK_CODE_OFFSET();
-        if (!out.WriteFully(&proxy_stub[0], proxy_stub_size)) {
-          ReportWriteFailure("proxy stub code", method_idx, dex_file, out);
-          return 0;
-        }
-        code_offset += proxy_stub_size;
-        DCHECK_CODE_OFFSET();
-      }
-      DCHECK_CODE_OFFSET();
+      offset += invoke_stub_size;
+      DCHECK_OFFSET();
     }
   }
 #endif
 
-  return code_offset;
+  return offset;
 }
 
-OatWriter::OatDexFile::OatDexFile(const DexFile& dex_file) {
+OatWriter::OatDexFile::OatDexFile(size_t offset, const DexFile& dex_file) {
+  offset_ = offset;
   const std::string& location(dex_file.GetLocation());
   dex_file_location_size_ = location.size();
   dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data());
@@ -816,6 +779,7 @@
 }
 
 bool OatWriter::OatDexFile::Write(OutputStream& out) const {
+  DCHECK_OFFSET_();
   if (!out.WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) {
     PLOG(ERROR) << "Failed to write dex file location length to " << out.GetLocation();
     return false;
@@ -840,14 +804,25 @@
   return true;
 }
 
-OatWriter::OatClass::OatClass(mirror::Class::Status status, uint32_t methods_count) {
+OatWriter::OatClass::OatClass(size_t offset, mirror::Class::Status status, uint32_t methods_count) {
+  offset_ = offset;
   status_ = status;
   method_offsets_.resize(methods_count);
 }
 
-size_t OatWriter::OatClass::SizeOf() const {
+size_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatHeader(
+    size_t class_def_method_index_) const {
+  return offset_ + GetOatMethodOffsetsOffsetFromOatClass(class_def_method_index_);
+}
+
+size_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatClass(
+    size_t class_def_method_index_) const {
   return sizeof(status_)
-          + (sizeof(method_offsets_[0]) * method_offsets_.size());
+          + (sizeof(method_offsets_[0]) * class_def_method_index_);
+}
+
+size_t OatWriter::OatClass::SizeOf() const {
+  return GetOatMethodOffsetsOffsetFromOatClass(method_offsets_.size());
 }
 
 void OatWriter::OatClass::UpdateChecksum(OatHeader& oat_header) const {
@@ -857,15 +832,20 @@
 }
 
 bool OatWriter::OatClass::Write(OutputStream& out) const {
+  DCHECK_OFFSET_();
   if (!out.WriteFully(&status_, sizeof(status_))) {
     PLOG(ERROR) << "Failed to write class status to " << out.GetLocation();
     return false;
   }
+  DCHECK_EQ(static_cast<off_t>(GetOatMethodOffsetsOffsetFromOatHeader(0)),
+            out.Seek(0, kSeekCurrent));
   if (!out.WriteFully(&method_offsets_[0],
                       sizeof(method_offsets_[0]) * method_offsets_.size())) {
     PLOG(ERROR) << "Failed to write method offsets to " << out.GetLocation();
     return false;
   }
+  DCHECK_EQ(static_cast<off_t>(GetOatMethodOffsetsOffsetFromOatHeader(method_offsets_.size())),
+            out.Seek(0, kSeekCurrent));
   return true;
 }