/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "oat_writer.h"

#include <zlib.h>

#include "class_linker.h"
#include "class_loader.h"
#include "elf_image.h"
#include "file.h"
#include "os.h"
#include "safe_map.h"
#include "space.h"
#include "stl_util.h"

namespace art {

bool OatWriter::Create(File* file,
                       const ClassLoader* class_loader,
                       const std::vector<const DexFile*>& dex_files,
                       uint32_t image_file_location_checksum,
                       const std::string& image_file_location,
                       const Compiler& compiler) {
  OatWriter oat_writer(dex_files,
                       image_file_location_checksum,
                       image_file_location,
                       class_loader,
                       compiler);
  return oat_writer.Write(file);
}

OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
                     uint32_t image_file_location_checksum,
                     const std::string& image_file_location,
                     const ClassLoader* class_loader,
                     const Compiler& compiler) {
  compiler_ = &compiler;
  class_loader_ = class_loader;
  image_file_location_checksum_ = image_file_location_checksum;
  image_file_location_ = image_file_location;
  dex_files_ = &dex_files;
  elf_images_ = compiler_->GetElfImages();
  oat_header_ = NULL;
  executable_offset_padding_length_ = 0;

  size_t offset = InitOatHeader();
  offset = InitOatDexFiles(offset);
  offset = InitDexFiles(offset);
  offset = InitOatElfImages(offset);
  offset = InitElfImages(offset);
  offset = InitOatClasses(offset);
  offset = InitOatCode(offset);
  offset = InitOatCodeDexFiles(offset);

  CHECK_EQ(dex_files_->size(), oat_dex_files_.size());
}

OatWriter::~OatWriter() {
  delete oat_header_;
  STLDeleteElements(&oat_dex_files_);
  STLDeleteElements(&oat_elf_images_);
  STLDeleteElements(&oat_classes_);
}

size_t OatWriter::InitOatHeader() {
  // create the OatHeader
  oat_header_ = new OatHeader(compiler_->GetInstructionSet(),
                              dex_files_,
                              elf_images_.size(),
                              image_file_location_checksum_,
                              image_file_location_);
  size_t offset = sizeof(*oat_header_);
  offset += image_file_location_.size();
  return offset;
}

size_t OatWriter::InitOatDexFiles(size_t offset) {
  // create the OatDexFiles
  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);
    oat_dex_files_.push_back(oat_dex_file);
    offset += oat_dex_file->SizeOf();
  }
  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::InitOatElfImages(size_t offset) {
  size_t n = elf_images_.size();
  if (n != 0) {
    // Offset to ELF image table should be rounded up to 4-byte aligned, so that
    // we can read the uint32_t directly.
    offset = RoundUp(offset, 4);
    oat_header_->SetElfImageTableOffset(offset);
  } else {
    oat_header_->SetElfImageTableOffset(0);
  }

  for (size_t i = 0; i < n; ++i) {
    OatElfImage* oat_elf_image = new OatElfImage(elf_images_[i]);
    oat_elf_images_.push_back(oat_elf_image);
    offset += oat_elf_image->SizeOf();
  }
  return offset;
}

size_t OatWriter::InitElfImages(size_t offset) {
  for (size_t i = 0; i < oat_elf_images_.size(); ++i) {
    offset = RoundUp(offset, 4);
    oat_elf_images_[i]->SetElfOffset(offset);
    offset += oat_elf_images_[i]->GetElfSize();
  }
  return offset;
}

size_t OatWriter::InitOatClasses(size_t offset) {
  // create the OatClasses
  // calculate the offsets within OatDexFiles to OatClasses
  for (size_t i = 0; i != dex_files_->size(); ++i) {
    const DexFile* dex_file = (*dex_files_)[i];
    for (size_t class_def_index = 0;
         class_def_index < dex_file->NumClassDefs();
         class_def_index++) {
      oat_dex_files_[i]->methods_offsets_[class_def_index] = offset;
      const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
      const byte* class_data = dex_file->GetClassData(class_def);
      uint32_t num_methods = 0;
      if (class_data != NULL) {  // ie not an empty class, such as a marker interface
        ClassDataItemIterator it(*dex_file, class_data);
        size_t num_direct_methods = it.NumDirectMethods();
        size_t num_virtual_methods = it.NumVirtualMethods();
        num_methods = num_direct_methods + num_virtual_methods;
      }

      CompiledClass* compiled_class =
          compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index));
      Class::Status status =
          (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady;

      OatClass* oat_class = new OatClass(status, num_methods);
      oat_classes_.push_back(oat_class);
      offset += oat_class->SizeOf();
    }
    oat_dex_files_[i]->UpdateChecksum(*oat_header_);
  }
  return offset;
}

size_t OatWriter::InitOatCode(size_t offset) {
  // calculate the offsets within OatHeader to executable code
  size_t old_offset = offset;
  // required to be on a new page boundary
  offset = RoundUp(offset, kPageSize);
  oat_header_->SetExecutableOffset(offset);
  executable_offset_padding_length_ = offset - old_offset;
  return offset;
}

size_t OatWriter::InitOatCodeDexFiles(size_t offset) {
  size_t oat_class_index = 0;
  for (size_t i = 0; i != dex_files_->size(); ++i) {
    const DexFile* dex_file = (*dex_files_)[i];
    CHECK(dex_file != NULL);
    offset = InitOatCodeDexFile(offset, oat_class_index, *dex_file);
  }
  return offset;
}

size_t OatWriter::InitOatCodeDexFile(size_t offset,
                                     size_t& oat_class_index,
                                     const DexFile& dex_file) {
  for (size_t class_def_index = 0;
       class_def_index < dex_file.NumClassDefs();
       class_def_index++, oat_class_index++) {
    const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
    offset = InitOatCodeClassDef(offset, oat_class_index, class_def_index, dex_file, class_def);
    oat_classes_[oat_class_index]->UpdateChecksum(*oat_header_);
  }
  return offset;
}

size_t OatWriter::InitOatCodeClassDef(size_t offset,
                                      size_t oat_class_index, size_t class_def_index,
                                      const DexFile& dex_file,
                                      const DexFile::ClassDef& class_def) {
  const byte* class_data = dex_file.GetClassData(class_def);
  if (class_data == NULL) {
    // empty class, such as a marker interface
    return offset;
  }
  ClassDataItemIterator it(dex_file, class_data);
  CHECK_EQ(oat_classes_[oat_class_index]->method_offsets_.size(),
           it.NumDirectMethods() + it.NumVirtualMethods());
  // Skip fields
  while (it.HasNextStaticField()) {
    it.Next();
  }
  while (it.HasNextInstanceField()) {
    it.Next();
  }
  // Process methods
  size_t class_def_method_index = 0;
  while (it.HasNextDirectMethod()) {
    bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
    bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0;
    offset = InitOatCodeMethod(offset, oat_class_index, class_def_index, class_def_method_index, is_native,
                               is_static, true, it.GetMemberIndex(), &dex_file);
    class_def_method_index++;
    it.Next();
  }
  while (it.HasNextVirtualMethod()) {
    CHECK_EQ(it.GetMemberAccessFlags() & kAccStatic, 0U);
    bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0;
    offset = InitOatCodeMethod(offset, oat_class_index, class_def_index, class_def_method_index, is_native,
                               false, false, it.GetMemberIndex(), &dex_file);
    class_def_method_index++;
    it.Next();
  }
  DCHECK(!it.HasNext());
  return offset;
}

size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index,
                                    size_t __attribute__((unused)) class_def_index,
                                    size_t class_def_method_index,
                                    bool __attribute__((unused)) is_native,
                                    bool is_static, bool is_direct,
                                    uint32_t method_idx, const DexFile* dex_file) {
  // derived from CompiledMethod if available
  uint32_t code_offset = 0;
  uint16_t code_elf_idx = static_cast<uint16_t>(-1u);
  uint16_t code_elf_func_idx = static_cast<uint16_t>(-1u);
  uint32_t frame_size_in_bytes = kStackAlignment;
  uint32_t core_spill_mask = 0;
  uint32_t fp_spill_mask = 0;
  uint32_t mapping_table_offset = 0;
  uint32_t vmap_table_offset = 0;
  uint32_t gc_map_offset = 0;
  // derived from CompiledInvokeStub if available
  uint32_t invoke_stub_offset = 0;
  uint16_t invoke_stub_elf_idx = static_cast<uint16_t>(-1u);
  uint16_t invoke_stub_elf_func_idx = static_cast<uint16_t>(-1u);

  CompiledMethod* compiled_method =
      compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file, method_idx));
  if (compiled_method != NULL) {
    if (compiled_method->IsExecutableInElf()) {
      code_elf_idx = compiled_method->GetElfIndex();
      code_elf_func_idx = compiled_method->GetElfFuncIndex();
      frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
    } else {
      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();
      code_offset = offset + sizeof(code_size) + thumb_offset;

      // Deduplicate code arrays
      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
      if (code_iter != code_offsets_.end()) {
        code_offset = code_iter->second;
      } else {
        code_offsets_.Put(&code, code_offset);
        offset += sizeof(code_size);  // code size is prepended before code
        offset += code_size;
        oat_header_->UpdateChecksum(&code[0], code_size);
      }
      frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
      core_spill_mask = compiled_method->GetCoreSpillMask();
      fp_spill_mask = compiled_method->GetFpSpillMask();

      const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
      size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
      mapping_table_offset = (mapping_table_size == 0) ? 0 : offset;

      // Deduplicate mapping tables
      SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table);
      if (mapping_iter != mapping_table_offsets_.end()) {
        mapping_table_offset = mapping_iter->second;
      } else {
        mapping_table_offsets_.Put(&mapping_table, mapping_table_offset);
        offset += mapping_table_size;
        oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size);
      }

      const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
      size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
      vmap_table_offset = (vmap_table_size == 0) ? 0 : offset;

      // Deduplicate vmap tables
      SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table);
      if (vmap_iter != vmap_table_offsets_.end()) {
        vmap_table_offset = vmap_iter->second;
      } else {
        vmap_table_offsets_.Put(&vmap_table, vmap_table_offset);
        offset += vmap_table_size;
        oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size);
      }

      const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
      size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
      gc_map_offset = (gc_map_size == 0) ? 0 : offset;

#ifndef NDEBUG
      // We expect GC maps except when the class hasn't been verified or the method is native
      CompiledClass* compiled_class =
          compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index));
      Class::Status status =
          (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady;
      CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified)
          << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " << (status < Class::kStatusVerified) << " " << status << " " << PrettyMethod(method_idx, *dex_file);
#endif

      // Deduplicate GC maps
      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()) {
        gc_map_offset = gc_map_iter->second;
      } else {
        gc_map_offsets_.Put(&gc_map, gc_map_offset);
        offset += gc_map_size;
        oat_header_->UpdateChecksum(&gc_map[0], gc_map_size);
      }
    }
  }

  const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx));
  const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
  if (compiled_invoke_stub != NULL) {
    if (compiled_invoke_stub->IsExecutableInElf()) {
      invoke_stub_elf_idx = compiled_invoke_stub->GetElfIndex();
      invoke_stub_elf_func_idx = compiled_invoke_stub->GetElfFuncIndex();
    } else {
      offset = CompiledMethod::AlignCode(offset, compiler_->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);
      invoke_stub_offset = offset + sizeof(invoke_stub_size);

      // Deduplicate invoke stubs
      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub);
      if (stub_iter != code_offsets_.end()) {
        invoke_stub_offset = stub_iter->second;
      } else {
        code_offsets_.Put(&invoke_stub, invoke_stub_offset);
        offset += sizeof(invoke_stub_size);  // invoke stub size is prepended before code
        offset += invoke_stub_size;
        oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size);
      }
    }
  }

  oat_classes_[oat_class_index]->method_offsets_[class_def_method_index]
      = OatMethodOffsets(code_offset,
                         frame_size_in_bytes,
                         core_spill_mask,
                         fp_spill_mask,
                         mapping_table_offset,
                         vmap_table_offset,
                         gc_map_offset,
                         invoke_stub_offset
#if defined(ART_USE_LLVM_COMPILER)
                       , code_elf_idx,
                         code_elf_func_idx,
                         invoke_stub_elf_idx,
                         invoke_stub_elf_func_idx
#endif
                         );

  if (compiler_->IsImage()) {
    ClassLinker* linker = Runtime::Current()->GetClassLinker();
    DexCache* dex_cache = linker->FindDexCache(*dex_file);
    Method* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader_,
                                           is_direct);
    CHECK(method != NULL);
    method->SetFrameSizeInBytes(frame_size_in_bytes);
    method->SetCoreSpillMask(core_spill_mask);
    method->SetFpSpillMask(fp_spill_mask);
    method->SetOatMappingTableOffset(mapping_table_offset);
    // Don't overwrite static method trampoline
    if (!method->IsStatic() || method->IsConstructor() ||
        method->GetDeclaringClass()->IsInitialized()) {
      method->SetOatCodeOffset(code_offset);
    } else {
      method->SetCode(Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData());
    }
    method->SetOatVmapTableOffset(vmap_table_offset);
    method->SetOatGcMapOffset(gc_map_offset);
    method->SetOatInvokeStubOffset(invoke_stub_offset);
  }

  return offset;
}

#define DCHECK_CODE_OFFSET() \
  DCHECK_EQ(static_cast<off_t>(code_offset), lseek(file->Fd(), 0, SEEK_CUR))

bool OatWriter::Write(File* file) {
  if (!file->WriteFully(oat_header_, sizeof(*oat_header_))) {
    PLOG(ERROR) << "Failed to write oat header to " << file->name();
    return false;
  }

  if (!file->WriteFully(image_file_location_.data(),
                        image_file_location_.size())) {
    PLOG(ERROR) << "Failed to write oat header image file location to " << file->name();
    return false;
  }

  if (!WriteTables(file)) {
    LOG(ERROR) << "Failed to write oat tables to " << file->name();
    return false;
  }

  size_t code_offset = WriteCode(file);
  if (code_offset == 0) {
    LOG(ERROR) << "Failed to write oat code to " << file->name();
    return false;
  }

  code_offset = WriteCodeDexFiles(file, code_offset);
  if (code_offset == 0) {
    LOG(ERROR) << "Failed to write oat code for dex files to " << file->name();
    return false;
  }

  return true;
}

bool OatWriter::WriteTables(File* file) {
  for (size_t i = 0; i != oat_dex_files_.size(); ++i) {
    if (!oat_dex_files_[i]->Write(file)) {
      PLOG(ERROR) << "Failed to write oat dex information to " << file->name();
      return false;
    }
  }
  for (size_t i = 0; i != oat_dex_files_.size(); ++i) {
    uint32_t expected_offset = oat_dex_files_[i]->dex_file_offset_;
    off_t actual_offset = lseek(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_elf_images_.size(); ++i) {
    if (!oat_elf_images_[i]->Write(file)) {
      PLOG(ERROR) << "Failed to write oat elf information to " << file->name();
      return false;
    }
  }
  for (size_t i = 0; i != oat_elf_images_.size(); ++i) {
    uint32_t expected_offset = oat_elf_images_[i]->GetElfOffset();
    off_t actual_offset = lseek(file->Fd(), expected_offset, SEEK_SET);
    if (static_cast<uint32_t>(actual_offset) != expected_offset) {
      PLOG(ERROR) << "Failed to seek to dex file section."
                  << " Actual: " << actual_offset
                  << " Expected: " << expected_offset;
      return false;
    }
    if (!oat_elf_images_[i]->WriteElfImage(file)) {
      return false;
    }
  }
  for (size_t i = 0; i != oat_classes_.size(); ++i) {
    if (!oat_classes_[i]->Write(file)) {
      PLOG(ERROR) << "Failed to write oat methods information to " << file->name();
      return false;
    }
  }
  return true;
}

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);
  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();
    return 0;
  }
  DCHECK_CODE_OFFSET();
  return code_offset;
}

size_t OatWriter::WriteCodeDexFiles(File* file, size_t code_offset) {
  size_t oat_class_index = 0;
  for (size_t i = 0; i != oat_dex_files_.size(); ++i) {
    const DexFile* dex_file = (*dex_files_)[i];
    CHECK(dex_file != NULL);
    code_offset = WriteCodeDexFile(file, code_offset, oat_class_index, *dex_file);
    if (code_offset == 0) {
      return 0;
    }
  }
  return code_offset;
}

size_t OatWriter::WriteCodeDexFile(File* file, size_t code_offset, size_t& oat_class_index,
                                   const DexFile& dex_file) {
  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs();
      class_def_index++, oat_class_index++) {
    const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
    code_offset = WriteCodeClassDef(file, code_offset, oat_class_index, dex_file, class_def);
    if (code_offset == 0) {
      return 0;
    }
  }
  return code_offset;
}

void OatWriter::ReportWriteFailure(const char* what, uint32_t method_idx,
                                   const DexFile& dex_file, File* f) const {
  PLOG(ERROR) << "Failed to write " << what << " for " << PrettyMethod(method_idx, dex_file)
      << " to " << f->name();
}

size_t OatWriter::WriteCodeClassDef(File* file,
                                    size_t code_offset, size_t oat_class_index,
                                    const DexFile& dex_file,
                                    const DexFile::ClassDef& class_def) {
  const byte* class_data = dex_file.GetClassData(class_def);
  if (class_data == NULL) {
    // ie. an empty class such as a marker interface
    return code_offset;
  }
  ClassDataItemIterator it(dex_file, class_data);
  // Skip fields
  while (it.HasNextStaticField()) {
    it.Next();
  }
  while (it.HasNextInstanceField()) {
    it.Next();
  }
  // Process methods
  size_t class_def_method_index = 0;
  while (it.HasNextDirectMethod()) {
    bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
    code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index,
                                  is_static, it.GetMemberIndex(), dex_file);
    if (code_offset == 0) {
      return 0;
    }
    class_def_method_index++;
    it.Next();
  }
  while (it.HasNextVirtualMethod()) {
    code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index,
                                  false, it.GetMemberIndex(), dex_file);
    if (code_offset == 0) {
      return 0;
    }
    class_def_method_index++;
    it.Next();
  }
  return code_offset;
}

size_t OatWriter::WriteCodeMethod(File* file, size_t code_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 =
      compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file, method_idx));

  uint32_t frame_size_in_bytes = 0;
  uint32_t core_spill_mask = 0;
  uint32_t fp_spill_mask = 0;

  OatMethodOffsets method_offsets =
      oat_classes_[oat_class_index]->method_offsets_[class_def_method_index];


  if (compiled_method != NULL) {  // ie. not an abstract method
    if (!compiled_method->IsExecutableInElf()) {
      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);
        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();
          return 0;
        }
        code_offset += aligned_code_delta;
        DCHECK_CODE_OFFSET();
      }
      DCHECK_ALIGNED(code_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();
      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);
      } else {
        DCHECK(offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
        if (!file->WriteFully(&code_size, sizeof(code_size))) {
          ReportWriteFailure("method code size", method_idx, dex_file, file);
          return 0;
        }
        code_offset += sizeof(code_size);
        DCHECK_CODE_OFFSET();
        if (!file->WriteFully(&code[0], code_size)) {
          ReportWriteFailure("method code", method_idx, dex_file, file);
          return 0;
        }
        code_offset += code_size;
      }
      DCHECK_CODE_OFFSET();
      frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
      core_spill_mask = compiled_method->GetCoreSpillMask();
      fp_spill_mask = compiled_method->GetFpSpillMask();

      const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
      size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);

      // Deduplicate mapping tables
      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_) {
        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_)
            << PrettyMethod(method_idx, dex_file);
        if (!file->WriteFully(&mapping_table[0], mapping_table_size)) {
          ReportWriteFailure("mapping table", method_idx, dex_file, file);
          return 0;
        }
        code_offset += mapping_table_size;
      }
      DCHECK_CODE_OFFSET();

      const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
      size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);

      // Deduplicate vmap tables
      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_) {
        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_)
            << PrettyMethod(method_idx, dex_file);
        if (!file->WriteFully(&vmap_table[0], vmap_table_size)) {
          ReportWriteFailure("vmap table", method_idx, dex_file, file);
          return 0;
        }
        code_offset += vmap_table_size;
      }
      DCHECK_CODE_OFFSET();

      const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
      size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);

      // Deduplicate GC maps
      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_) {
        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_)
            << PrettyMethod(method_idx, dex_file);
        if (!file->WriteFully(&gc_map[0], gc_map_size)) {
          ReportWriteFailure("GC map", method_idx, dex_file, file);
          return 0;
        }
        code_offset += gc_map_size;
      }
      DCHECK_CODE_OFFSET();
    }
  }
  const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
  const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
  if (compiled_invoke_stub != NULL) {
    if (!compiled_invoke_stub->IsExecutableInElf()) {
      uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
                                                               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);
        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;
          return 0;
        }
        code_offset += aligned_code_delta;
        DCHECK_CODE_OFFSET();
      }
      DCHECK_ALIGNED(code_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);
      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);
      } else {
        DCHECK(offset == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
        if (!file->WriteFully(&invoke_stub_size, sizeof(invoke_stub_size))) {
          ReportWriteFailure("invoke stub code size", method_idx, dex_file, file);
          return 0;
        }
        code_offset += sizeof(invoke_stub_size);
        DCHECK_CODE_OFFSET();
        if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) {
          ReportWriteFailure("invoke stub code", method_idx, dex_file, file);
          return 0;
        }
        code_offset += invoke_stub_size;
      }
      DCHECK_CODE_OFFSET();
    }
  }

  return code_offset;
}

OatWriter::OatDexFile::OatDexFile(const DexFile& dex_file) {
  const std::string& location(dex_file.GetLocation());
  dex_file_location_size_ = location.size();
  dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data());
  dex_file_location_checksum_ = dex_file.GetLocationChecksum();
  dex_file_offset_ = 0;
  methods_offsets_.resize(dex_file.NumClassDefs());
}

size_t OatWriter::OatDexFile::SizeOf() const {
  return sizeof(dex_file_location_size_)
          + dex_file_location_size_
          + sizeof(dex_file_location_checksum_)
          + sizeof(dex_file_offset_)
          + (sizeof(methods_offsets_[0]) * methods_offsets_.size());
}

void OatWriter::OatDexFile::UpdateChecksum(OatHeader& oat_header) const {
  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_location_checksum_, sizeof(dex_file_location_checksum_));
  oat_header.UpdateChecksum(&dex_file_offset_, sizeof(dex_file_offset_));
  oat_header.UpdateChecksum(&methods_offsets_[0],
                            sizeof(methods_offsets_[0]) * methods_offsets_.size());
}

bool OatWriter::OatDexFile::Write(File* file) const {
  if (!file->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) {
    PLOG(ERROR) << "Failed to write dex file location length to " << file->name();
    return false;
  }
  if (!file->WriteFully(dex_file_location_data_, dex_file_location_size_)) {
    PLOG(ERROR) << "Failed to write dex file location data to " << file->name();
    return false;
  }
  if (!file->WriteFully(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_))) {
    PLOG(ERROR) << "Failed to write dex file location 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(&methods_offsets_[0],
                        sizeof(methods_offsets_[0]) * methods_offsets_.size())) {
    PLOG(ERROR) << "Failed to write methods offsets to " << file->name();
    return false;
  }
  return true;
}

OatWriter::OatClass::OatClass(Class::Status status, uint32_t methods_count) {
  status_ = status;
  method_offsets_.resize(methods_count);
}

size_t OatWriter::OatClass::SizeOf() const {
  return sizeof(status_)
          + (sizeof(method_offsets_[0]) * method_offsets_.size());
}

void OatWriter::OatClass::UpdateChecksum(OatHeader& oat_header) const {
  oat_header.UpdateChecksum(&status_, sizeof(status_));
  oat_header.UpdateChecksum(&method_offsets_[0],
                            sizeof(method_offsets_[0]) * method_offsets_.size());
}

bool OatWriter::OatClass::Write(File* file) const {
  if (!file->WriteFully(&status_, sizeof(status_))) {
    PLOG(ERROR) << "Failed to write class status to " << file->name();
    return false;
  }
  if (!file->WriteFully(&method_offsets_[0],
                        sizeof(method_offsets_[0]) * method_offsets_.size())) {
    PLOG(ERROR) << "Failed to write method offsets to " << file->name();
    return false;
  }
  return true;
}

OatWriter::OatElfImage::OatElfImage(const ElfImage& image)
    : elf_offset_(0), elf_size_(image.size()), elf_addr_(image.begin()) {
}

size_t OatWriter::OatElfImage::SizeOf() const {
  return (sizeof(elf_offset_) + sizeof(elf_size_));
}

uint32_t OatWriter::OatElfImage::GetElfSize() const {
  return elf_size_;
}

uint32_t OatWriter::OatElfImage::GetElfOffset() const {
  DCHECK_NE(elf_offset_, 0U);
  return elf_offset_;
}

void OatWriter::OatElfImage::SetElfOffset(uint32_t offset) {
  DCHECK_NE(offset, 0U);
  DCHECK((offset & 0x3LU) == 0);
  elf_offset_ = offset;
}

bool OatWriter::OatElfImage::Write(File* file) const {
  DCHECK_NE(elf_offset_, 0U);
  if (!file->WriteFully(&elf_offset_, sizeof(elf_offset_))) {
    PLOG(ERROR) << "Failed to write ELF offset to " << file->name();
    return false;
  }
  if (!file->WriteFully(&elf_size_, sizeof(elf_size_))) {
    PLOG(ERROR) << "Failed to write ELF size to " << file->name();
    return false;
  }
  return true;
}

bool OatWriter::OatElfImage::WriteElfImage(File* file) const {
  if (!file->WriteFully(elf_addr_, elf_size_)) {
    PLOG(ERROR) << "Failed to write ELF image to " << file->name();
    return false;
  }
  return true;
}

}  // namespace art
