/*
 * Copyright (C) 2014 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 "patchoat.h"

#include <openssl/sha.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>

#include <string>
#include <vector>

#include "android-base/file.h"
#include <android-base/parseint.h>
#include "android-base/stringprintf.h"
#include "android-base/strings.h"

#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/bit_memory_region.h"
#include "base/dumpable.h"
#include "base/file_utils.h"
#include "base/leb128.h"
#include "base/logging.h"  // For InitLogging.
#include "base/mutex.h"
#include "base/memory_region.h"
#include "base/memory_tool.h"
#include "base/os.h"
#include "base/scoped_flock.h"
#include "base/stringpiece.h"
#include "base/unix_file/fd_file.h"
#include "base/unix_file/random_access_file_utils.h"
#include "base/utils.h"
#include "class_root.h"
#include "elf_file.h"
#include "elf_file_impl.h"
#include "elf_utils.h"
#include "gc/space/image_space.h"
#include "image-inl.h"
#include "intern_table.h"
#include "mirror/dex_cache.h"
#include "mirror/executable.h"
#include "mirror/method.h"
#include "mirror/object-inl.h"
#include "mirror/object-refvisitor-inl.h"
#include "mirror/reference.h"
#include "noop_compiler_callbacks.h"
#include "offsets.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "thread.h"

namespace art {

using android::base::StringPrintf;

namespace {

static const OatHeader* GetOatHeader(const ElfFile* elf_file) {
  uint64_t off = 0;
  if (!elf_file->GetSectionOffsetAndSize(".rodata", &off, nullptr)) {
    return nullptr;
  }

  OatHeader* oat_header = reinterpret_cast<OatHeader*>(elf_file->Begin() + off);
  return oat_header;
}

static File* CreateOrOpen(const char* name) {
  if (OS::FileExists(name)) {
    return OS::OpenFileReadWrite(name);
  } else {
    std::unique_ptr<File> f(OS::CreateEmptyFile(name));
    if (f.get() != nullptr) {
      if (fchmod(f->Fd(), 0644) != 0) {
        PLOG(ERROR) << "Unable to make " << name << " world readable";
        unlink(name);
        return nullptr;
      }
    }
    return f.release();
  }
}

// Either try to close the file (close=true), or erase it.
static bool FinishFile(File* file, bool close) {
  if (close) {
    if (file->FlushCloseOrErase() != 0) {
      PLOG(ERROR) << "Failed to flush and close file.";
      return false;
    }
    return true;
  } else {
    file->Erase();
    return false;
  }
}

static bool SymlinkFile(const std::string& input_filename, const std::string& output_filename) {
  if (input_filename == output_filename) {
    // Input and output are the same, nothing to do.
    return true;
  }

  // Unlink the original filename, since we are overwriting it.
  unlink(output_filename.c_str());

  // Create a symlink from the source file to the target path.
  if (symlink(input_filename.c_str(), output_filename.c_str()) < 0) {
    PLOG(ERROR) << "Failed to create symlink " << output_filename << " -> " << input_filename;
    return false;
  }

  if (kIsDebugBuild) {
    LOG(INFO) << "Created symlink " << output_filename << " -> " << input_filename;
  }

  return true;
}

// Holder class for runtime options and related objects.
class PatchoatRuntimeOptionsHolder {
 public:
  PatchoatRuntimeOptionsHolder(const std::string& image_location, InstructionSet isa) {
    options_.push_back(std::make_pair("compilercallbacks", &callbacks_));
    img_ = "-Ximage:" + image_location;
    options_.push_back(std::make_pair(img_.c_str(), nullptr));
    isa_name_ = GetInstructionSetString(isa);
    options_.push_back(std::make_pair("imageinstructionset",
                                      reinterpret_cast<const void*>(isa_name_.c_str())));
    options_.push_back(std::make_pair("-Xno-sig-chain", nullptr));
    // We do not want the runtime to attempt to patch the image.
    options_.push_back(std::make_pair("-Xnorelocate", nullptr));
    // Don't try to compile.
    options_.push_back(std::make_pair("-Xnoimage-dex2oat", nullptr));
    // Do not accept broken image.
    options_.push_back(std::make_pair("-Xno-dex-file-fallback", nullptr));
  }

  const RuntimeOptions& GetRuntimeOptions() {
    return options_;
  }

 private:
  RuntimeOptions options_;
  NoopCompilerCallbacks callbacks_;
  std::string isa_name_;
  std::string img_;
};

}  // namespace

bool PatchOat::GeneratePatch(
    const MemMap& original,
    const MemMap& relocated,
    std::vector<uint8_t>* output,
    std::string* error_msg) {
  // FORMAT of the patch (aka image relocation) file:
  // * SHA-256 digest (32 bytes) of original/unrelocated file (e.g., the one from /system)
  // * List of monotonically increasing offsets (max value defined by uint32_t) at which relocations
  //   occur.
  //   Each element is represented as the delta from the previous offset in the list (first element
  //   is a delta from 0). Each delta is encoded using unsigned LEB128: little-endian
  //   variable-length 7 bits per byte encoding, where all bytes have the highest bit (0x80) set
  //   except for the final byte which does not have that bit set. For example, 0x3f is offset 0x3f,
  //   whereas 0xbf 0x05 is offset (0x3f & 0x7f) | (0x5 << 7) which is 0x2bf. Most deltas end up
  //   being encoding using just one byte, achieving ~4x decrease in relocation file size compared
  //   to the encoding where offsets are stored verbatim, as uint32_t.

  size_t original_size = original.Size();
  size_t relocated_size = relocated.Size();
  if (original_size != relocated_size) {
    *error_msg =
        StringPrintf(
            "Original and relocated image sizes differ: %zu vs %zu", original_size, relocated_size);
    return false;
  }
  if (original_size > UINT32_MAX) {
    *error_msg = StringPrintf("Image too large: %zu" , original_size);
    return false;
  }

  const ImageHeader& relocated_header =
      *reinterpret_cast<const ImageHeader*>(relocated.Begin());
  // Offsets are supposed to differ between original and relocated by this value
  off_t expected_diff = relocated_header.GetPatchDelta();
  if (expected_diff == 0) {
    // Can't identify offsets which are supposed to differ due to relocation
    *error_msg = "Relocation delta is 0";
    return false;
  }

  const ImageHeader* image_header = reinterpret_cast<const ImageHeader*>(original.Begin());
  if (image_header->GetStorageMode() != ImageHeader::kStorageModeUncompressed) {
    *error_msg = "Unexpected compressed image.";
    return false;
  }
  if (image_header->IsAppImage()) {
    *error_msg = "Unexpected app image.";
    return false;
  }
  if (image_header->GetPointerSize() != PointerSize::k32 &&
      image_header->GetPointerSize() != PointerSize::k64) {
    *error_msg = "Unexpected pointer size.";
    return false;
  }
  static_assert(sizeof(GcRoot<mirror::Object>) == sizeof(mirror::HeapReference<mirror::Object>),
                "Expecting heap GC roots and references to have the same size.");
  DCHECK_LE(sizeof(GcRoot<mirror::Object>), static_cast<size_t>(image_header->GetPointerSize()));

  const size_t image_bitmap_offset = RoundUp(sizeof(ImageHeader) + image_header->GetDataSize(),
                                             kPageSize);
  const size_t end_of_bitmap = image_bitmap_offset + image_header->GetImageBitmapSection().Size();
  const ImageSection& relocation_section = image_header->GetImageRelocationsSection();
  MemoryRegion relocations_data(original.Begin() + end_of_bitmap, relocation_section.Size());
  size_t image_end = image_header->GetClassTableSection().End();
  if (!IsAligned<sizeof(GcRoot<mirror::Object>)>(image_end)) {
    *error_msg = StringPrintf("Unaligned image end: %zu", image_end);
    return false;
  }
  size_t num_indexes = image_end / sizeof(GcRoot<mirror::Object>);
  if (relocation_section.Size() != BitsToBytesRoundUp(num_indexes)) {
    *error_msg = StringPrintf("Unexpected size of relocation section: %zu expected: %zu",
                              static_cast<size_t>(relocation_section.Size()),
                              BitsToBytesRoundUp(num_indexes));
    return false;
  }
  BitMemoryRegion relocation_bitmap(relocations_data, /* bit_offset */ 0u, num_indexes);

  // Output the SHA-256 digest of the original
  output->resize(SHA256_DIGEST_LENGTH);
  const uint8_t* original_bytes = original.Begin();
  SHA256(original_bytes, original_size, output->data());

  // Check the list of offsets at which the original and patched images differ.
  size_t diff_offset_count = 0;
  const uint8_t* relocated_bytes = relocated.Begin();
  for (size_t index = 0; index != num_indexes; ++index) {
    size_t offset = index * sizeof(GcRoot<mirror::Object>);
    uint32_t original_value = *reinterpret_cast<const uint32_t*>(original_bytes + offset);
    uint32_t relocated_value = *reinterpret_cast<const uint32_t*>(relocated_bytes + offset);
    off_t diff = relocated_value - original_value;
    if (diff == 0) {
      CHECK(!relocation_bitmap.LoadBit(index));
      continue;
    } else if (diff != expected_diff) {
      *error_msg =
          StringPrintf(
              "Unexpected diff at offset %zu. Expected: %jd, but was: %jd",
              offset,
              (intmax_t) expected_diff,
              (intmax_t) diff);
      return false;
    }
    CHECK(relocation_bitmap.LoadBit(index));
    diff_offset_count++;
  }
  size_t tail_bytes = original_size - image_end;
  CHECK_EQ(memcmp(original_bytes + image_end, relocated_bytes + image_end, tail_bytes), 0);

  if (diff_offset_count == 0) {
    *error_msg = "Original and patched images are identical";
    return false;
  }

  return true;
}

static bool WriteRelFile(
    const MemMap& original,
    const MemMap& relocated,
    const std::string& rel_filename,
    std::string* error_msg) {
  std::vector<uint8_t> output;
  if (!PatchOat::GeneratePatch(original, relocated, &output, error_msg)) {
    return false;
  }

  std::unique_ptr<File> rel_file(OS::CreateEmptyFileWriteOnly(rel_filename.c_str()));
  if (rel_file.get() == nullptr) {
    *error_msg = StringPrintf("Failed to create/open output file %s", rel_filename.c_str());
    return false;
  }
  if (!rel_file->WriteFully(output.data(), output.size())) {
    *error_msg = StringPrintf("Failed to write to %s", rel_filename.c_str());
    return false;
  }
  if (rel_file->FlushCloseOrErase() != 0) {
    *error_msg = StringPrintf("Failed to flush and close %s", rel_filename.c_str());
    return false;
  }

  return true;
}

static bool CheckImageIdenticalToOriginalExceptForRelocation(
    const std::string& relocated_filename,
    const std::string& original_filename,
    std::string* error_msg) {
  *error_msg = "";
  std::string rel_filename = original_filename + ".rel";
  std::unique_ptr<File> rel_file(OS::OpenFileForReading(rel_filename.c_str()));
  if (rel_file.get() == nullptr) {
    *error_msg = StringPrintf("Failed to open image relocation file %s", rel_filename.c_str());
    return false;
  }
  int64_t rel_size = rel_file->GetLength();
  if (rel_size < 0) {
    *error_msg = StringPrintf("Error while getting size of image relocation file %s",
                              rel_filename.c_str());
    return false;
  }
  if (rel_size != SHA256_DIGEST_LENGTH) {
    *error_msg = StringPrintf("Unexpected size of image relocation file %s: %" PRId64
                                  ", expected %zu",
                              rel_filename.c_str(),
                              rel_size,
                              static_cast<size_t>(SHA256_DIGEST_LENGTH));
    return false;
  }
  std::unique_ptr<uint8_t[]> rel(new uint8_t[rel_size]);
  if (!rel_file->ReadFully(rel.get(), rel_size)) {
    *error_msg = StringPrintf("Failed to read image relocation file %s", rel_filename.c_str());
    return false;
  }

  std::unique_ptr<File> image_file(OS::OpenFileForReading(relocated_filename.c_str()));
  if (image_file.get() == nullptr) {
    *error_msg = StringPrintf("Unable to open relocated image file  %s",
                              relocated_filename.c_str());
    return false;
  }

  int64_t image_size = image_file->GetLength();
  if (image_size < 0) {
    *error_msg = StringPrintf("Error while getting size of relocated image file %s",
                              relocated_filename.c_str());
    return false;
  }
  if (static_cast<uint64_t>(image_size) < sizeof(ImageHeader)) {
    *error_msg =
        StringPrintf(
            "Relocated image file %s too small: %" PRId64,
                relocated_filename.c_str(), image_size);
    return false;
  }
  if (image_size > std::numeric_limits<uint32_t>::max()) {
    *error_msg =
        StringPrintf(
            "Relocated image file %s too large: %" PRId64, relocated_filename.c_str(), image_size);
    return false;
  }

  std::unique_ptr<uint8_t[]> image(new uint8_t[image_size]);
  if (!image_file->ReadFully(image.get(), image_size)) {
    *error_msg = StringPrintf("Failed to read relocated image file %s", relocated_filename.c_str());
    return false;
  }

  const ImageHeader& image_header = *reinterpret_cast<const ImageHeader*>(image.get());
  if (image_header.GetStorageMode() != ImageHeader::kStorageModeUncompressed) {
    *error_msg = StringPrintf("Unsuported compressed image file %s",
                              relocated_filename.c_str());
    return false;
  }
  size_t image_end = image_header.GetClassTableSection().End();
  if (image_end > static_cast<uint64_t>(image_size) || !IsAligned<4u>(image_end)) {
    *error_msg = StringPrintf("Heap size too big or unaligned in image file %s: %zu",
                              relocated_filename.c_str(),
                              image_end);
    return false;
  }
  size_t number_of_relocation_locations = image_end / 4u;
  const ImageSection& relocation_section = image_header.GetImageRelocationsSection();
  if (relocation_section.Size() != BitsToBytesRoundUp(number_of_relocation_locations)) {
    *error_msg = StringPrintf("Unexpected size of relocation section in image file %s: %zu"
                                  " expected: %zu",
                              relocated_filename.c_str(),
                              static_cast<size_t>(relocation_section.Size()),
                              BitsToBytesRoundUp(number_of_relocation_locations));
    return false;
  }
  if (relocation_section.End() != image_size) {
    *error_msg = StringPrintf("Relocation section does not end at file end in image file %s: %zu"
                                  " expected: %" PRId64,
                              relocated_filename.c_str(),
                              static_cast<size_t>(relocation_section.End()),
                              image_size);
    return false;
  }

  off_t expected_diff = image_header.GetPatchDelta();
  if (expected_diff == 0) {
    *error_msg = StringPrintf("Unsuported patch delta of zero in %s",
                              relocated_filename.c_str());
    return false;
  }

  // Relocated image is expected to differ from the original due to relocation.
  // Unrelocate the image in memory to compensate.
  MemoryRegion relocations(image.get() + relocation_section.Offset(), relocation_section.Size());
  BitMemoryRegion relocation_bitmask(relocations,
                                     /* bit_offset */ 0u,
                                     number_of_relocation_locations);
  for (size_t index = 0; index != number_of_relocation_locations; ++index) {
    if (relocation_bitmask.LoadBit(index)) {
      uint32_t* image_value = reinterpret_cast<uint32_t*>(image.get() + index * 4u);
      *image_value -= expected_diff;
    }
  }

  // Image in memory is now supposed to be identical to the original.  We
  // confirm this by comparing the digest of the in-memory image to the expected
  // digest from relocation file.
  uint8_t image_digest[SHA256_DIGEST_LENGTH];
  SHA256(image.get(), image_size, image_digest);
  if (memcmp(image_digest, rel.get(), SHA256_DIGEST_LENGTH) != 0) {
    *error_msg =
        StringPrintf(
            "Relocated image %s does not match the original %s after unrelocation",
            relocated_filename.c_str(),
            original_filename.c_str());
    return false;
  }

  // Relocated image is identical to the original, once relocations are taken into account
  return true;
}

static bool VerifySymlink(const std::string& intended_target, const std::string& link_name) {
  std::string actual_target;
  if (!android::base::Readlink(link_name, &actual_target)) {
    PLOG(ERROR) << "Readlink on " << link_name << " failed.";
    return false;
  }
  return actual_target == intended_target;
}

static bool VerifyVdexAndOatSymlinks(const std::string& input_image_filename,
                                     const std::string& output_image_filename) {
  return VerifySymlink(ImageHeader::GetVdexLocationFromImageLocation(input_image_filename),
                       ImageHeader::GetVdexLocationFromImageLocation(output_image_filename))
      && VerifySymlink(ImageHeader::GetOatLocationFromImageLocation(input_image_filename),
                       ImageHeader::GetOatLocationFromImageLocation(output_image_filename));
}

bool PatchOat::CreateVdexAndOatSymlinks(const std::string& input_image_filename,
                                        const std::string& output_image_filename) {
  std::string input_vdex_filename =
      ImageHeader::GetVdexLocationFromImageLocation(input_image_filename);
  std::string input_oat_filename =
      ImageHeader::GetOatLocationFromImageLocation(input_image_filename);

  std::unique_ptr<File> input_oat_file(OS::OpenFileForReading(input_oat_filename.c_str()));
  if (input_oat_file.get() == nullptr) {
    LOG(ERROR) << "Unable to open input oat file at " << input_oat_filename;
    return false;
  }
  std::string error_msg;
  std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat_file.get(),
                                             PROT_READ | PROT_WRITE,
                                             MAP_PRIVATE,
                                             &error_msg));
  if (elf == nullptr) {
    LOG(ERROR) << "Unable to open oat file " << input_oat_filename << " : " << error_msg;
    return false;
  }

  const OatHeader* oat_header = GetOatHeader(elf.get());
  if (oat_header == nullptr) {
    LOG(ERROR) << "Failed to find oat header in oat file " << input_oat_filename;
    return false;
  }

  if (!oat_header->IsValid()) {
    LOG(ERROR) << "Elf file " << input_oat_filename << " has an invalid oat header";
    return false;
  }

  std::string output_vdex_filename =
      ImageHeader::GetVdexLocationFromImageLocation(output_image_filename);
  std::string output_oat_filename =
      ImageHeader::GetOatLocationFromImageLocation(output_image_filename);

  return SymlinkFile(input_oat_filename, output_oat_filename) &&
         SymlinkFile(input_vdex_filename, output_vdex_filename);
}

bool PatchOat::Patch(const std::string& image_location,
                     off_t delta,
                     const std::string& output_image_directory,
                     const std::string& output_image_relocation_directory,
                     InstructionSet isa,
                     TimingLogger* timings) {
  bool output_image = !output_image_directory.empty();
  bool output_image_relocation = !output_image_relocation_directory.empty();
  if ((!output_image) && (!output_image_relocation)) {
    // Nothing to do
    return true;
  }
  if ((output_image_relocation) && (delta == 0)) {
    LOG(ERROR) << "Cannot output image relocation information when requested relocation delta is 0";
    return false;
  }

  CHECK(Runtime::Current() == nullptr);
  CHECK(!image_location.empty()) << "image file must have a filename.";

  TimingLogger::ScopedTiming t("Runtime Setup", timings);

  CHECK_NE(isa, InstructionSet::kNone);

  // Set up the runtime
  PatchoatRuntimeOptionsHolder options_holder(image_location, isa);
  if (!Runtime::Create(options_holder.GetRuntimeOptions(), false)) {
    LOG(ERROR) << "Unable to initialize runtime";
    return false;
  }
  std::unique_ptr<Runtime> runtime(Runtime::Current());

  // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
  // give it away now and then switch to a more manageable ScopedObjectAccess.
  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
  ScopedObjectAccess soa(Thread::Current());

  std::vector<gc::space::ImageSpace*> spaces = Runtime::Current()->GetHeap()->GetBootImageSpaces();
  std::map<gc::space::ImageSpace*, MemMap> space_to_memmap_map;

  for (size_t i = 0; i < spaces.size(); ++i) {
    t.NewTiming("Image Patching setup");
    gc::space::ImageSpace* space = spaces[i];
    std::string input_image_filename = space->GetImageFilename();
    std::unique_ptr<File> input_image(OS::OpenFileForReading(input_image_filename.c_str()));
    if (input_image.get() == nullptr) {
      LOG(ERROR) << "Unable to open input image file at " << input_image_filename;
      return false;
    }

    int64_t image_len = input_image->GetLength();
    if (image_len < 0) {
      LOG(ERROR) << "Error while getting image length";
      return false;
    }
    ImageHeader image_header;
    if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header),
                                                  sizeof(image_header), 0)) {
      LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath();
    }

    /*bool is_image_pic = */IsImagePic(image_header, input_image->GetPath());
    // Nothing special to do right now since the image always needs to get patched.
    // Perhaps in some far-off future we may have images with relative addresses that are true-PIC.

    // Create the map where we will write the image patches to.
    std::string error_msg;
    MemMap image = MemMap::MapFile(image_len,
                                   PROT_READ | PROT_WRITE,
                                   MAP_PRIVATE,
                                   input_image->Fd(),
                                   0,
                                   /*low_4gb*/false,
                                   input_image->GetPath().c_str(),
                                   &error_msg);
    if (!image.IsValid()) {
      LOG(ERROR) << "Unable to map image file " << input_image->GetPath() << " : " << error_msg;
      return false;
    }


    space_to_memmap_map.emplace(space, std::move(image));
    PatchOat p = PatchOat(isa,
                          &space_to_memmap_map[space],
                          space->GetLiveBitmap(),
                          space->GetMemMap(),
                          delta,
                          &space_to_memmap_map,
                          timings);

    t.NewTiming("Patching image");
    if (!p.PatchImage(i == 0)) {
      LOG(ERROR) << "Failed to patch image file " << input_image_filename;
      return false;
    }

    // Write the patched image spaces.
    if (output_image) {
      std::string output_image_filename;
      if (!GetDalvikCacheFilename(space->GetImageLocation().c_str(),
                                  output_image_directory.c_str(),
                                  &output_image_filename,
                                  &error_msg)) {
        LOG(ERROR) << "Failed to find relocated image file name: " << error_msg;
        return false;
      }

      if (!CreateVdexAndOatSymlinks(input_image_filename, output_image_filename))
        return false;

      t.NewTiming("Writing image");
      std::unique_ptr<File> output_image_file(CreateOrOpen(output_image_filename.c_str()));
      if (output_image_file.get() == nullptr) {
        LOG(ERROR) << "Failed to open output image file at " << output_image_filename;
        return false;
      }

      bool success = p.WriteImage(output_image_file.get());
      success = FinishFile(output_image_file.get(), success);
      if (!success) {
        return false;
      }
    }

    if (output_image_relocation) {
      t.NewTiming("Writing image relocation");
      std::string original_image_filename(space->GetImageLocation() + ".rel");
      std::string image_relocation_filename =
          output_image_relocation_directory
              + (android::base::StartsWith(original_image_filename, "/") ? "" : "/")
              + original_image_filename.substr(original_image_filename.find_last_of('/'));
      int64_t input_image_size = input_image->GetLength();
      if (input_image_size < 0) {
        LOG(ERROR) << "Error while getting input image size";
        return false;
      }
      MemMap original = MemMap::MapFile(input_image_size,
                                        PROT_READ,
                                        MAP_PRIVATE,
                                        input_image->Fd(),
                                        0,
                                        /*low_4gb*/false,
                                        input_image->GetPath().c_str(),
                                        &error_msg);
      if (!original.IsValid()) {
        LOG(ERROR) << "Unable to map image file " << input_image->GetPath() << " : " << error_msg;
        return false;
      }

      const MemMap* relocated = p.image_;

      if (!WriteRelFile(original, *relocated, image_relocation_filename, &error_msg)) {
        LOG(ERROR) << "Failed to create image relocation file " << image_relocation_filename
            << ": " << error_msg;
        return false;
      }
    }
  }

  if (!kIsDebugBuild && !(kRunningOnMemoryTool && kMemoryToolDetectsLeaks)) {
    // We want to just exit on non-debug builds, not bringing the runtime down
    // in an orderly fashion. So release the following fields.
    runtime.release();
  }

  return true;
}

bool PatchOat::Verify(const std::string& image_location,
                      const std::string& output_image_directory,
                      InstructionSet isa,
                      TimingLogger* timings) {
  if (image_location.empty()) {
    LOG(ERROR) << "Original image file not provided";
    return false;
  }
  if (output_image_directory.empty()) {
    LOG(ERROR) << "Relocated image directory not provided";
    return false;
  }

  TimingLogger::ScopedTiming t("Runtime Setup", timings);

  CHECK_NE(isa, InstructionSet::kNone);

  // Set up the runtime
  PatchoatRuntimeOptionsHolder options_holder(image_location, isa);
  if (!Runtime::Create(options_holder.GetRuntimeOptions(), false)) {
    LOG(ERROR) << "Unable to initialize runtime";
    return false;
  }
  std::unique_ptr<Runtime> runtime(Runtime::Current());

  // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
  // give it away now and then switch to a more manageable ScopedObjectAccess.
  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
  ScopedObjectAccess soa(Thread::Current());

  t.NewTiming("Image Verification setup");
  std::vector<gc::space::ImageSpace*> spaces = Runtime::Current()->GetHeap()->GetBootImageSpaces();

  // TODO: Check that no other .rel files exist in the original dir

  bool success = true;
  std::string image_location_dir = android::base::Dirname(image_location);
  for (size_t i = 0; i < spaces.size(); ++i) {
    gc::space::ImageSpace* space = spaces[i];

    std::string relocated_image_filename;
    std::string error_msg;
    if (!GetDalvikCacheFilename(space->GetImageLocation().c_str(),
            output_image_directory.c_str(), &relocated_image_filename, &error_msg)) {
      LOG(ERROR) << "Failed to find relocated image file name: " << error_msg;
      success = false;
      break;
    }
    // location:     /system/framework/boot.art
    // isa:          arm64
    // basename:     boot.art
    // original:     /system/framework/arm64/boot.art
    // relocation:   /system/framework/arm64/boot.art.rel
    std::string original_image_filename =
        GetSystemImageFilename(space->GetImageLocation().c_str(), isa);

    if (!CheckImageIdenticalToOriginalExceptForRelocation(
            relocated_image_filename, original_image_filename, &error_msg)) {
      LOG(ERROR) << error_msg;
      success = false;
      break;
    }

    if (!VerifyVdexAndOatSymlinks(original_image_filename, relocated_image_filename)) {
      LOG(ERROR) << "Verification of vdex and oat symlinks for "
                 << space->GetImageLocation() << " failed.";
      success = false;
      break;
    }
  }

  if (!kIsDebugBuild && !(kRunningOnMemoryTool && kMemoryToolDetectsLeaks)) {
    // We want to just exit on non-debug builds, not bringing the runtime down
    // in an orderly fashion. So release the following fields.
    runtime.release();
  }

  return success;
}

bool PatchOat::WriteImage(File* out) {
  CHECK(out != nullptr);
  TimingLogger::ScopedTiming t("Writing image File", timings_);
  std::string error_msg;

  // No error checking here, this is best effort. The locking may or may not
  // succeed and we don't really care either way.
  ScopedFlock img_flock = LockedFile::DupOf(out->Fd(), out->GetPath(),
                                            true /* read_only_mode */, &error_msg);

  CHECK(image_ != nullptr);
  size_t expect = image_->Size();
  if (out->WriteFully(reinterpret_cast<char*>(image_->Begin()), expect) &&
      out->SetLength(expect) == 0) {
    return true;
  } else {
    LOG(ERROR) << "Writing to image file " << out->GetPath() << " failed.";
    return false;
  }
}

bool PatchOat::IsImagePic(const ImageHeader& image_header, const std::string& image_path) {
  if (!image_header.CompilePic()) {
    if (kIsDebugBuild) {
      LOG(INFO) << "image at location " << image_path << " was *not* compiled pic";
    }
    return false;
  }

  if (kIsDebugBuild) {
    LOG(INFO) << "image at location " << image_path << " was compiled PIC";
  }

  return true;
}

class PatchOat::PatchOatArtFieldVisitor : public ArtFieldVisitor {
 public:
  explicit PatchOatArtFieldVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {}

  void Visit(ArtField* field) override REQUIRES_SHARED(Locks::mutator_lock_) {
    ArtField* const dest = patch_oat_->RelocatedCopyOf(field);
    dest->SetDeclaringClass(
        patch_oat_->RelocatedAddressOfPointer(field->GetDeclaringClass().Ptr()));
  }

 private:
  PatchOat* const patch_oat_;
};

void PatchOat::PatchArtFields(const ImageHeader* image_header) {
  PatchOatArtFieldVisitor visitor(this);
  image_header->VisitPackedArtFields(&visitor, heap_->Begin());
}

class PatchOat::PatchOatArtMethodVisitor : public ArtMethodVisitor {
 public:
  explicit PatchOatArtMethodVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {}

  void Visit(ArtMethod* method) override REQUIRES_SHARED(Locks::mutator_lock_) {
    ArtMethod* const dest = patch_oat_->RelocatedCopyOf(method);
    patch_oat_->FixupMethod(method, dest);
  }

 private:
  PatchOat* const patch_oat_;
};

void PatchOat::PatchArtMethods(const ImageHeader* image_header) {
  const PointerSize pointer_size = InstructionSetPointerSize(isa_);
  PatchOatArtMethodVisitor visitor(this);
  image_header->VisitPackedArtMethods(&visitor, heap_->Begin(), pointer_size);
}

void PatchOat::PatchImTables(const ImageHeader* image_header) {
  const PointerSize pointer_size = InstructionSetPointerSize(isa_);
  // We can safely walk target image since the conflict tables are independent.
  image_header->VisitPackedImTables(
      [this](ArtMethod* method) {
        return RelocatedAddressOfPointer(method);
      },
      image_->Begin(),
      pointer_size);
}

void PatchOat::PatchImtConflictTables(const ImageHeader* image_header) {
  const PointerSize pointer_size = InstructionSetPointerSize(isa_);
  // We can safely walk target image since the conflict tables are independent.
  image_header->VisitPackedImtConflictTables(
      [this](ArtMethod* method) {
        return RelocatedAddressOfPointer(method);
      },
      image_->Begin(),
      pointer_size);
}

class PatchOat::FixupRootVisitor : public RootVisitor {
 public:
  explicit FixupRootVisitor(const PatchOat* patch_oat) : patch_oat_(patch_oat) {
  }

  void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info ATTRIBUTE_UNUSED)
      override REQUIRES_SHARED(Locks::mutator_lock_) {
    for (size_t i = 0; i < count; ++i) {
      *roots[i] = patch_oat_->RelocatedAddressOfPointer(*roots[i]);
    }
  }

  void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
                  const RootInfo& info ATTRIBUTE_UNUSED)
      override REQUIRES_SHARED(Locks::mutator_lock_) {
    for (size_t i = 0; i < count; ++i) {
      roots[i]->Assign(patch_oat_->RelocatedAddressOfPointer(roots[i]->AsMirrorPtr()));
    }
  }

 private:
  const PatchOat* const patch_oat_;
};

void PatchOat::PatchInternedStrings(const ImageHeader* image_header) {
  const auto& section = image_header->GetInternedStringsSection();
  if (section.Size() == 0) {
    return;
  }
  InternTable temp_table;
  // Note that we require that ReadFromMemory does not make an internal copy of the elements.
  // This also relies on visit roots not doing any verification which could fail after we update
  // the roots to be the image addresses.
  temp_table.AddTableFromMemory(image_->Begin() + section.Offset());
  FixupRootVisitor visitor(this);
  temp_table.VisitRoots(&visitor, kVisitRootFlagAllRoots);
}

void PatchOat::PatchClassTable(const ImageHeader* image_header) {
  const auto& section = image_header->GetClassTableSection();
  if (section.Size() == 0) {
    return;
  }
  // Note that we require that ReadFromMemory does not make an internal copy of the elements.
  // This also relies on visit roots not doing any verification which could fail after we update
  // the roots to be the image addresses.
  WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
  ClassTable temp_table;
  temp_table.ReadFromMemory(image_->Begin() + section.Offset());
  FixupRootVisitor visitor(this);
  temp_table.VisitRoots(UnbufferedRootVisitor(&visitor, RootInfo(kRootUnknown)));
}


class PatchOat::RelocatedPointerVisitor {
 public:
  explicit RelocatedPointerVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {}

  template <typename T>
  T* operator()(T* ptr, void** dest_addr ATTRIBUTE_UNUSED = nullptr) const {
    return patch_oat_->RelocatedAddressOfPointer(ptr);
  }

 private:
  PatchOat* const patch_oat_;
};

void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots) {
  auto* dex_caches = down_cast<mirror::ObjectArray<mirror::DexCache>*>(
      img_roots->Get(ImageHeader::kDexCaches));
  const PointerSize pointer_size = InstructionSetPointerSize(isa_);
  for (size_t i = 0, count = dex_caches->GetLength(); i < count; ++i) {
    auto* orig_dex_cache = dex_caches->GetWithoutChecks(i);
    auto* copy_dex_cache = RelocatedCopyOf(orig_dex_cache);
    // Though the DexCache array fields are usually treated as native pointers, we set the full
    // 64-bit values here, clearing the top 32 bits for 32-bit targets. The zero-extension is
    // done by casting to the unsigned type uintptr_t before casting to int64_t, i.e.
    //     static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + offset))).
    mirror::StringDexCacheType* orig_strings = orig_dex_cache->GetStrings();
    mirror::StringDexCacheType* relocated_strings = RelocatedAddressOfPointer(orig_strings);
    copy_dex_cache->SetField64<false>(
        mirror::DexCache::StringsOffset(),
        static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_strings)));
    if (orig_strings != nullptr) {
      orig_dex_cache->FixupStrings(RelocatedCopyOf(orig_strings), RelocatedPointerVisitor(this));
    }
    mirror::TypeDexCacheType* orig_types = orig_dex_cache->GetResolvedTypes();
    mirror::TypeDexCacheType* relocated_types = RelocatedAddressOfPointer(orig_types);
    copy_dex_cache->SetField64<false>(
        mirror::DexCache::ResolvedTypesOffset(),
        static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_types)));
    if (orig_types != nullptr) {
      orig_dex_cache->FixupResolvedTypes(RelocatedCopyOf(orig_types),
                                         RelocatedPointerVisitor(this));
    }
    mirror::MethodDexCacheType* orig_methods = orig_dex_cache->GetResolvedMethods();
    mirror::MethodDexCacheType* relocated_methods = RelocatedAddressOfPointer(orig_methods);
    copy_dex_cache->SetField64<false>(
        mirror::DexCache::ResolvedMethodsOffset(),
        static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_methods)));
    if (orig_methods != nullptr) {
      mirror::MethodDexCacheType* copy_methods = RelocatedCopyOf(orig_methods);
      for (size_t j = 0, num = orig_dex_cache->NumResolvedMethods(); j != num; ++j) {
        mirror::MethodDexCachePair orig =
            mirror::DexCache::GetNativePairPtrSize(orig_methods, j, pointer_size);
        mirror::MethodDexCachePair copy(RelocatedAddressOfPointer(orig.object), orig.index);
        mirror::DexCache::SetNativePairPtrSize(copy_methods, j, copy, pointer_size);
      }
    }
    mirror::FieldDexCacheType* orig_fields = orig_dex_cache->GetResolvedFields();
    mirror::FieldDexCacheType* relocated_fields = RelocatedAddressOfPointer(orig_fields);
    copy_dex_cache->SetField64<false>(
        mirror::DexCache::ResolvedFieldsOffset(),
        static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_fields)));
    if (orig_fields != nullptr) {
      mirror::FieldDexCacheType* copy_fields = RelocatedCopyOf(orig_fields);
      for (size_t j = 0, num = orig_dex_cache->NumResolvedFields(); j != num; ++j) {
        mirror::FieldDexCachePair orig =
            mirror::DexCache::GetNativePairPtrSize(orig_fields, j, pointer_size);
        mirror::FieldDexCachePair copy(RelocatedAddressOfPointer(orig.object), orig.index);
        mirror::DexCache::SetNativePairPtrSize(copy_fields, j, copy, pointer_size);
      }
    }
    mirror::MethodTypeDexCacheType* orig_method_types = orig_dex_cache->GetResolvedMethodTypes();
    mirror::MethodTypeDexCacheType* relocated_method_types =
        RelocatedAddressOfPointer(orig_method_types);
    copy_dex_cache->SetField64<false>(
        mirror::DexCache::ResolvedMethodTypesOffset(),
        static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_method_types)));
    if (orig_method_types != nullptr) {
      orig_dex_cache->FixupResolvedMethodTypes(RelocatedCopyOf(orig_method_types),
                                               RelocatedPointerVisitor(this));
    }

    GcRoot<mirror::CallSite>* orig_call_sites = orig_dex_cache->GetResolvedCallSites();
    GcRoot<mirror::CallSite>* relocated_call_sites = RelocatedAddressOfPointer(orig_call_sites);
    copy_dex_cache->SetField64<false>(
        mirror::DexCache::ResolvedCallSitesOffset(),
        static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_call_sites)));
    if (orig_call_sites != nullptr) {
      orig_dex_cache->FixupResolvedCallSites(RelocatedCopyOf(orig_call_sites),
                                             RelocatedPointerVisitor(this));
    }
  }
}

bool PatchOat::PatchImage(bool primary_image) {
  ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
  CHECK_GT(image_->Size(), sizeof(ImageHeader));
  // These are the roots from the original file.
  mirror::ObjectArray<mirror::Object>* img_roots = image_header->GetImageRoots().Ptr();
  image_header->RelocateImage(delta_);

  PatchArtFields(image_header);
  PatchArtMethods(image_header);
  PatchImTables(image_header);
  PatchImtConflictTables(image_header);
  PatchInternedStrings(image_header);
  PatchClassTable(image_header);
  // Patch dex file int/long arrays which point to ArtFields.
  PatchDexFileArrays(img_roots);

  if (primary_image) {
    VisitObject(img_roots);
  }

  if (!image_header->IsValid()) {
    LOG(ERROR) << "relocation renders image header invalid";
    return false;
  }

  {
    TimingLogger::ScopedTiming t("Walk Bitmap", timings_);
    // Walk the bitmap.
    WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
    auto visitor = [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
      VisitObject(obj);
    };
    bitmap_->Walk(visitor);
  }
  return true;
}


void PatchOat::PatchVisitor::operator() (ObjPtr<mirror::Object> obj,
                                         MemberOffset off,
                                         bool is_static_unused ATTRIBUTE_UNUSED) const {
  mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off);
  mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent);
  copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object);
}

void PatchOat::PatchVisitor::operator() (ObjPtr<mirror::Class> cls ATTRIBUTE_UNUSED,
                                         ObjPtr<mirror::Reference> ref) const {
  MemberOffset off = mirror::Reference::ReferentOffset();
  mirror::Object* referent = ref->GetReferent();
  DCHECK(referent == nullptr ||
         Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(referent)) << referent;
  mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent);
  copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object);
}

// Called by PatchImage.
void PatchOat::VisitObject(mirror::Object* object) {
  mirror::Object* copy = RelocatedCopyOf(object);
  CHECK(copy != nullptr);
  if (kUseBakerReadBarrier) {
    object->AssertReadBarrierState();
  }
  PatchOat::PatchVisitor visitor(this, copy);
  object->VisitReferences<kVerifyNone>(visitor, visitor);
  if (object->IsClass<kVerifyNone>()) {
    const PointerSize pointer_size = InstructionSetPointerSize(isa_);
    mirror::Class* klass = object->AsClass();
    mirror::Class* copy_klass = down_cast<mirror::Class*>(copy);
    RelocatedPointerVisitor native_visitor(this);
    klass->FixupNativePointers(copy_klass, pointer_size, native_visitor);
    auto* vtable = klass->GetVTable();
    if (vtable != nullptr) {
      vtable->Fixup(RelocatedCopyOfFollowImages(vtable), pointer_size, native_visitor);
    }
    mirror::IfTable* iftable = klass->GetIfTable();
    for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
      if (iftable->GetMethodArrayCount(i) > 0) {
        auto* method_array = iftable->GetMethodArray(i);
        CHECK(method_array != nullptr);
        method_array->Fixup(RelocatedCopyOfFollowImages(method_array),
                            pointer_size,
                            native_visitor);
      }
    }
  } else if (object->GetClass() == GetClassRoot<mirror::Method>() ||
             object->GetClass() == GetClassRoot<mirror::Constructor>()) {
    // Need to go update the ArtMethod.
    auto* dest = down_cast<mirror::Executable*>(copy);
    auto* src = down_cast<mirror::Executable*>(object);
    dest->SetArtMethod(RelocatedAddressOfPointer(src->GetArtMethod()));
  }
}

void PatchOat::FixupMethod(ArtMethod* object, ArtMethod* copy) {
  const PointerSize pointer_size = InstructionSetPointerSize(isa_);
  copy->CopyFrom(object, pointer_size);
  // Just update the entry points if it looks like we should.
  // TODO: sanity check all the pointers' values
  copy->SetDeclaringClass(RelocatedAddressOfPointer(object->GetDeclaringClass().Ptr()));
  copy->SetEntryPointFromQuickCompiledCodePtrSize(RelocatedAddressOfPointer(
      object->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size)), pointer_size);
  // No special handling for IMT conflict table since all pointers are moved by the same offset.
  copy->SetDataPtrSize(RelocatedAddressOfPointer(
      object->GetDataPtrSize(pointer_size)), pointer_size);
}

static int orig_argc;
static char** orig_argv;

static std::string CommandLine() {
  std::vector<std::string> command;
  for (int i = 0; i < orig_argc; ++i) {
    command.push_back(orig_argv[i]);
  }
  return android::base::Join(command, ' ');
}

static void UsageErrorV(const char* fmt, va_list ap) {
  std::string error;
  android::base::StringAppendV(&error, fmt, ap);
  LOG(ERROR) << error;
}

static void UsageError(const char* fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  UsageErrorV(fmt, ap);
  va_end(ap);
}

NO_RETURN static void Usage(const char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  UsageErrorV(fmt, ap);
  va_end(ap);

  UsageError("Command: %s", CommandLine().c_str());
  UsageError("Usage: patchoat [options]...");
  UsageError("");
  UsageError("  --instruction-set=<isa>: Specifies the instruction set the patched code is");
  UsageError("      compiled for (required).");
  UsageError("");
  UsageError("  --input-image-location=<file.art>: Specifies the 'location' of the image file to");
  UsageError("      be patched.");
  UsageError("");
  UsageError("  --output-image-directory=<dir>: Specifies the directory to write the patched");
  UsageError("      image file(s) to.");
  UsageError("");
  UsageError("  --output-image-relocation-directory=<dir>: Specifies the directory to write");
  UsageError("      the image relocation information to.");
  UsageError("");
  UsageError("  --base-offset-delta=<delta>: Specify the amount to change the old base-offset by.");
  UsageError("      This value may be negative.");
  UsageError("");
  UsageError("  --verify: Verify an existing patched file instead of creating one.");
  UsageError("");
  UsageError("  --dump-timings: dump out patch timing information");
  UsageError("");
  UsageError("  --no-dump-timings: do not dump out patch timing information");
  UsageError("");

  exit(EXIT_FAILURE);
}

static int patchoat_patch_image(TimingLogger& timings,
                                InstructionSet isa,
                                const std::string& input_image_location,
                                const std::string& output_image_directory,
                                const std::string& output_image_relocation_directory,
                                off_t base_delta,
                                bool base_delta_set,
                                bool debug) {
  CHECK(!input_image_location.empty());
  if ((output_image_directory.empty()) && (output_image_relocation_directory.empty())) {
    Usage("Image patching requires --output-image-directory or --output-image-relocation-directory");
  }

  if (!base_delta_set) {
    Usage("Must supply a desired new offset or delta.");
  }

  if (!IsAligned<kPageSize>(base_delta)) {
    Usage("Base offset/delta must be aligned to a pagesize (0x%08x) boundary.", kPageSize);
  }

  if (debug) {
    LOG(INFO) << "moving offset by " << base_delta
        << " (0x" << std::hex << base_delta << ") bytes or "
        << std::dec << (base_delta/kPageSize) << " pages.";
  }

  TimingLogger::ScopedTiming pt("patch image and oat", &timings);

  bool ret =
      PatchOat::Patch(
          input_image_location,
          base_delta,
          output_image_directory,
          output_image_relocation_directory,
          isa,
          &timings);

  if (kIsDebugBuild) {
    LOG(INFO) << "Exiting with return ... " << ret;
  }
  return ret ? EXIT_SUCCESS : EXIT_FAILURE;
}

static int patchoat_verify_image(TimingLogger& timings,
                                 InstructionSet isa,
                                 const std::string& input_image_location,
                                 const std::string& output_image_directory) {
  CHECK(!input_image_location.empty());
  TimingLogger::ScopedTiming pt("verify image and oat", &timings);

  bool ret =
      PatchOat::Verify(
          input_image_location,
          output_image_directory,
          isa,
          &timings);

  if (kIsDebugBuild) {
    LOG(INFO) << "Exiting with return ... " << ret;
  }
  return ret ? EXIT_SUCCESS : EXIT_FAILURE;
}

static int patchoat(int argc, char **argv) {
  Locks::Init();
  InitLogging(argv, Runtime::Abort);
  MemMap::Init();
  const bool debug = kIsDebugBuild;
  orig_argc = argc;
  orig_argv = argv;
  TimingLogger timings("patcher", false, false);

  // Skip over the command name.
  argv++;
  argc--;

  if (argc == 0) {
    Usage("No arguments specified");
  }

  timings.StartTiming("Patchoat");

  // cmd line args
  bool isa_set = false;
  InstructionSet isa = InstructionSet::kNone;
  std::string input_image_location;
  std::string output_image_directory;
  std::string output_image_relocation_directory;
  off_t base_delta = 0;
  bool base_delta_set = false;
  bool dump_timings = kIsDebugBuild;
  bool verify = false;

  for (int i = 0; i < argc; ++i) {
    const StringPiece option(argv[i]);
    const bool log_options = false;
    if (log_options) {
      LOG(INFO) << "patchoat: option[" << i << "]=" << argv[i];
    }
    if (option.starts_with("--instruction-set=")) {
      isa_set = true;
      const char* isa_str = option.substr(strlen("--instruction-set=")).data();
      isa = GetInstructionSetFromString(isa_str);
      if (isa == InstructionSet::kNone) {
        Usage("Unknown or invalid instruction set %s", isa_str);
      }
    } else if (option.starts_with("--input-image-location=")) {
      input_image_location = option.substr(strlen("--input-image-location=")).data();
    } else if (option.starts_with("--output-image-directory=")) {
      output_image_directory = option.substr(strlen("--output-image-directory=")).data();
    } else if (option.starts_with("--output-image-relocation-directory=")) {
      output_image_relocation_directory =
          option.substr(strlen("--output-image-relocation-directory=")).data();
    } else if (option.starts_with("--base-offset-delta=")) {
      const char* base_delta_str = option.substr(strlen("--base-offset-delta=")).data();
      base_delta_set = true;
      if (!android::base::ParseInt(base_delta_str, &base_delta)) {
        Usage("Failed to parse --base-offset-delta argument '%s' as an off_t", base_delta_str);
      }
    } else if (option == "--dump-timings") {
      dump_timings = true;
    } else if (option == "--no-dump-timings") {
      dump_timings = false;
    } else if (option == "--verify") {
      verify = true;
    } else {
      Usage("Unknown argument %s", option.data());
    }
  }

  // The instruction set is mandatory. This simplifies things...
  if (!isa_set) {
    Usage("Instruction set must be set.");
  }

  int ret;
  if (verify) {
    ret = patchoat_verify_image(timings,
                                isa,
                                input_image_location,
                                output_image_directory);
  } else {
    ret = patchoat_patch_image(timings,
                               isa,
                               input_image_location,
                               output_image_directory,
                               output_image_relocation_directory,
                               base_delta,
                               base_delta_set,
                               debug);
  }

  timings.EndTiming();
  if (dump_timings) {
    LOG(INFO) << Dumpable<TimingLogger>(timings);
  }

  return ret;
}

}  // namespace art

int main(int argc, char **argv) {
  return art::patchoat(argc, argv);
}
