Split .oat_patches to multiple sections.

.oat_patches section currently contains encoded patch locations for
several other sections. Split it to several sections - one for each
of the destination sections. For example, .text.oat_patches section
contains patch locations for the .text section.

This ensures that if we strip some the sections using standard
tools, we strip the corresponding .oat_patches section as well.

It also makes the overall design simpler.
I should have done it this way in the first place.

Since ApplyOatPatches has been simplified and uses unaligned memory
access, this also fixes bug 21403573.

Bug:20556771
Bug:21403573
Change-Id: Iae7c423911507b524eec500e8d61744046fcd3ba
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h
index 8a63a48..730d780 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -168,6 +168,10 @@
           patched_(false), patch_(patch), patch_base_section_(patch_base_section) {
     }
 
+    RawSection(const std::string& name, Elf_Word type)
+        : RawSection(name, type, 0, nullptr, 0, 1, 0, nullptr, nullptr) {
+    }
+
     Elf_Word GetSize() const OVERRIDE {
       return buffer_.size();
     }
@@ -779,10 +783,12 @@
 
   template<typename T>
   static bool WriteArray(File* elf_file, const T* data, size_t count) {
-    DCHECK(data != nullptr);
-    if (!elf_file->WriteFully(data, count * sizeof(T))) {
-      PLOG(ERROR) << "Failed to write to file " << elf_file->GetPath();
-      return false;
+    if (count != 0) {
+      DCHECK(data != nullptr);
+      if (!elf_file->WriteFully(data, count * sizeof(T))) {
+        PLOG(ERROR) << "Failed to write to file " << elf_file->GetPath();
+        return false;
+      }
     }
     return true;
   }
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 05b5c68..4a90b4e 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -19,6 +19,7 @@
 #include <unordered_map>
 #include <unordered_set>
 
+#include "base/casts.h"
 #include "base/logging.h"
 #include "base/unix_file/fd_file.h"
 #include "compiled_method.h"
@@ -69,36 +70,17 @@
 template <typename ElfTypes>
 static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer);
 
-// Encode patch locations in .oat_patches format.
+// Encode patch locations as LEB128 list of deltas between consecutive addresses.
 template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::EncodeOatPatches(
-    const OatWriter::PatchLocationsMap& sections,
-    std::vector<uint8_t>* buffer) {
-  for (const auto& section : sections) {
-    const std::string& name = section.first;
-    std::vector<uintptr_t>* locations = section.second.get();
-    DCHECK(!name.empty());
-    std::sort(locations->begin(), locations->end());
-    // Reserve buffer space - guess 2 bytes per ULEB128.
-    buffer->reserve(buffer->size() + name.size() + locations->size() * 2);
-    // Write null-terminated section name.
-    const uint8_t* name_data = reinterpret_cast<const uint8_t*>(name.c_str());
-    buffer->insert(buffer->end(), name_data, name_data + name.size() + 1);
-    // Write placeholder for data length.
-    size_t length_pos = buffer->size();
-    EncodeUnsignedLeb128(buffer, UINT32_MAX);
-    // Write LEB128 encoded list of advances (deltas between consequtive addresses).
-    size_t data_pos = buffer->size();
-    uintptr_t address = 0;  // relative to start of section.
-    for (uintptr_t location : *locations) {
-      DCHECK_LT(location - address, UINT32_MAX) << "Large gap between patch locations";
-      EncodeUnsignedLeb128(buffer, location - address);
-      address = location;
-    }
-    // Update length.
-    UpdateUnsignedLeb128(buffer->data() + length_pos, buffer->size() - data_pos);
+void ElfWriterQuick<ElfTypes>::EncodeOatPatches(const std::vector<uintptr_t>& locations,
+                                                std::vector<uint8_t>* buffer) {
+  buffer->reserve(buffer->size() + locations.size() * 2);  // guess 2 bytes per ULEB128.
+  uintptr_t address = 0;  // relative to start of section.
+  for (uintptr_t location : locations) {
+    DCHECK_GE(location, address) << "Patch locations are not in sorted order";
+    EncodeUnsignedLeb128(buffer, dchecked_integral_cast<uint32_t>(location - address));
+    address = location;
   }
-  buffer->push_back(0);  // End of sections.
 }
 
 class RodataWriter FINAL : public CodeOutput {
@@ -175,7 +157,7 @@
 
   // Add debug sections.
   // They are stack allocated here (in the same scope as the builder),
-  // but they are registred with the builder only if they are used.
+  // but they are registered with the builder only if they are used.
   using RawSection = typename ElfBuilder<ElfTypes>::RawSection;
   const auto* text = builder->GetText();
   const bool is64bit = Is64BitInstructionSet(isa);
@@ -190,12 +172,15 @@
                          is64bit ? Patch<Elf_Addr, uint64_t, kAbsoluteAddress> :
                                    Patch<Elf_Addr, uint32_t, kAbsoluteAddress>,
                          text);
+  RawSection debug_frame_oat_patches(".debug_frame.oat_patches", SHT_OAT_PATCH);
   RawSection debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
                         Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
-  RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
-  RawSection debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+  RawSection debug_info_oat_patches(".debug_info.oat_patches", SHT_OAT_PATCH);
+  RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS);
+  RawSection debug_str(".debug_str", SHT_PROGBITS);
   RawSection debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
                         Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
+  RawSection debug_line_oat_patches(".debug_line.oat_patches", SHT_OAT_PATCH);
   if (!oat_writer->GetMethodDebugInfo().empty()) {
     if (compiler_driver_->GetCompilerOptions().GetIncludeCFI()) {
       if (kCFIFormat == dwarf::DW_EH_FRAME_FORMAT) {
@@ -214,8 +199,9 @@
             debug_frame.GetBuffer(), debug_frame.GetPatchLocations(),
             nullptr, nullptr);
         builder->RegisterSection(&debug_frame);
-        *oat_writer->GetAbsolutePatchLocationsFor(".debug_frame") =
-            *debug_frame.GetPatchLocations();
+        EncodeOatPatches(*debug_frame.GetPatchLocations(),
+                         debug_frame_oat_patches.GetBuffer());
+        builder->RegisterSection(&debug_frame_oat_patches);
       }
     }
     if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
@@ -229,24 +215,26 @@
           debug_str.GetBuffer(),
           debug_line.GetBuffer(), debug_line.GetPatchLocations());
       builder->RegisterSection(&debug_info);
+      EncodeOatPatches(*debug_info.GetPatchLocations(),
+                       debug_info_oat_patches.GetBuffer());
+      builder->RegisterSection(&debug_info_oat_patches);
       builder->RegisterSection(&debug_abbrev);
       builder->RegisterSection(&debug_str);
       builder->RegisterSection(&debug_line);
-      *oat_writer->GetAbsolutePatchLocationsFor(".debug_info") =
-          *debug_info.GetPatchLocations();
-      *oat_writer->GetAbsolutePatchLocationsFor(".debug_line") =
-          *debug_line.GetPatchLocations();
+      EncodeOatPatches(*debug_line.GetPatchLocations(),
+                       debug_line_oat_patches.GetBuffer());
+      builder->RegisterSection(&debug_line_oat_patches);
     }
   }
 
-  // Add relocation section.
-  RawSection oat_patches(".oat_patches", SHT_OAT_PATCH, 0, nullptr, 0, 1, 0);
-  if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation() ||
-      // ElfWriter::Fixup will be called regardless and it needs to be able
-      // to patch debug sections so we have to include patches for them.
-      compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
-    EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(), oat_patches.GetBuffer());
-    builder->RegisterSection(&oat_patches);
+  // Add relocation section for .text.
+  RawSection text_oat_patches(".text.oat_patches", SHT_OAT_PATCH);
+  if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
+    // Note that ElfWriter::Fixup will be called regardless and therefore
+    // we need to include oat_patches for debug sections unconditionally.
+    EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(),
+                     text_oat_patches.GetBuffer());
+    builder->RegisterSection(&text_oat_patches);
   }
 
   return builder->Write(elf_file_);
diff --git a/compiler/elf_writer_quick.h b/compiler/elf_writer_quick.h
index 955b568..fd202ee 100644
--- a/compiler/elf_writer_quick.h
+++ b/compiler/elf_writer_quick.h
@@ -35,7 +35,7 @@
                      const CompilerDriver& driver)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static void EncodeOatPatches(const OatWriter::PatchLocationsMap& sections,
+  static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
                                std::vector<uint8_t>* buffer);
 
  protected:
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
index 08523d8..ccf34b8 100644
--- a/compiler/elf_writer_test.cc
+++ b/compiler/elf_writer_test.cc
@@ -88,73 +88,41 @@
   }
 }
 
-// Run only on host since we do unaligned memory accesses.
-#ifndef HAVE_ANDROID_OS
-
-static void PatchSection(const std::vector<uintptr_t>& patch_locations,
-                         std::vector<uint8_t>* section, int32_t delta) {
-  for (uintptr_t location : patch_locations) {
-    *reinterpret_cast<int32_t*>(section->data() + location) += delta;
-  }
-}
-
 TEST_F(ElfWriterTest, EncodeDecodeOatPatches) {
-  std::vector<uint8_t> oat_patches;  // Encoded patches.
+  const std::vector<std::vector<uintptr_t>> test_data {
+      { 0, 4, 8, 15, 128, 200 },
+      { 8, 8 + 127 },
+      { 8, 8 + 128 },
+      { },
+  };
+  for (const auto& patch_locations : test_data) {
+    constexpr int32_t delta = 0x11235813;
 
-  // Encode patch locations for a few sections.
-  OatWriter::PatchLocationsMap sections;
-  std::vector<uintptr_t> patches0 { 0, 4, 8, 15, 128, 200 };  // NOLINT
-  sections.emplace(".section0", std::unique_ptr<std::vector<uintptr_t>>(
-      new std::vector<uintptr_t> { patches0 }));
-  std::vector<uintptr_t> patches1 { 8, 127 };  // NOLINT
-  sections.emplace(".section1", std::unique_ptr<std::vector<uintptr_t>>(
-      new std::vector<uintptr_t> { patches1 }));
-  std::vector<uintptr_t> patches2 { };  // NOLINT
-  sections.emplace(".section2", std::unique_ptr<std::vector<uintptr_t>>(
-      new std::vector<uintptr_t> { patches2 }));
-  ElfWriterQuick32::EncodeOatPatches(sections, &oat_patches);
+    // Encode patch locations.
+    std::vector<uint8_t> oat_patches;
+    ElfWriterQuick32::EncodeOatPatches(patch_locations, &oat_patches);
 
-  // Create buffers to be patched.
-  std::vector<uint8_t> initial_data(256);
-  for (size_t i = 0; i < initial_data.size(); i++) {
-    initial_data[i] = i;
+    // Create buffer to be patched.
+    std::vector<uint8_t> initial_data(256);
+    for (size_t i = 0; i < initial_data.size(); i++) {
+      initial_data[i] = i;
+    }
+
+    // Patch manually.
+    std::vector<uint8_t> expected = initial_data;
+    for (uintptr_t location : patch_locations) {
+      typedef __attribute__((__aligned__(1))) uint32_t UnalignedAddress;
+      *reinterpret_cast<UnalignedAddress*>(expected.data() + location) += delta;
+    }
+
+    // Decode and apply patch locations.
+    std::vector<uint8_t> actual = initial_data;
+    ElfFileImpl32::ApplyOatPatches(
+        oat_patches.data(), oat_patches.data() + oat_patches.size(), delta,
+        actual.data(), actual.data() + actual.size());
+
+    EXPECT_EQ(expected, actual);
   }
-  std::vector<uint8_t> section0_expected = initial_data;
-  std::vector<uint8_t> section1_expected = initial_data;
-  std::vector<uint8_t> section2_expected = initial_data;
-  std::vector<uint8_t> section0_actual = initial_data;
-  std::vector<uint8_t> section1_actual = initial_data;
-  std::vector<uint8_t> section2_actual = initial_data;
-
-  // Patch manually.
-  constexpr int32_t delta = 0x11235813;
-  PatchSection(patches0, &section0_expected, delta);
-  PatchSection(patches1, &section1_expected, delta);
-  PatchSection(patches2, &section2_expected, delta);
-
-  // Decode and apply patch locations.
-  bool section0_successful = ElfFileImpl32::ApplyOatPatches(
-      oat_patches.data(), oat_patches.data() + oat_patches.size(),
-      ".section0", delta,
-      section0_actual.data(), section0_actual.data() + section0_actual.size());
-  EXPECT_TRUE(section0_successful);
-  EXPECT_EQ(section0_expected, section0_actual);
-
-  bool section1_successful = ElfFileImpl32::ApplyOatPatches(
-      oat_patches.data(), oat_patches.data() + oat_patches.size(),
-      ".section1", delta,
-      section1_actual.data(), section1_actual.data() + section1_actual.size());
-  EXPECT_TRUE(section1_successful);
-  EXPECT_EQ(section1_expected, section1_actual);
-
-  bool section2_successful = ElfFileImpl32::ApplyOatPatches(
-      oat_patches.data(), oat_patches.data() + oat_patches.size(),
-      ".section2", delta,
-      section2_actual.data(), section2_actual.data() + section2_actual.size());
-  EXPECT_TRUE(section2_successful);
-  EXPECT_EQ(section2_expected, section2_actual);
 }
 
-#endif
-
 }  // namespace art
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 15b4017..745cdcf 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -351,9 +351,8 @@
  public:
   InitCodeMethodVisitor(OatWriter* writer, size_t offset)
     : OatDexMethodVisitor(writer, offset),
-      text_absolute_patch_locations_(writer->GetAbsolutePatchLocationsFor(".text")),
       debuggable_(writer->GetCompilerDriver()->GetCompilerOptions().GetDebuggable()) {
-    text_absolute_patch_locations_->reserve(
+    writer_->absolute_patch_locations_.reserve(
         writer_->compiler_driver_->GetNonRelativeLinkerPatchCount());
   }
 
@@ -444,7 +443,7 @@
           uintptr_t base_loc = offset_ - code_size - writer_->oat_header_->GetExecutableOffset();
           for (const LinkerPatch& patch : compiled_method->GetPatches()) {
             if (!patch.IsPcRelative()) {
-              text_absolute_patch_locations_->push_back(base_loc + patch.LiteralOffset());
+              writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset());
             }
           }
         }
@@ -547,9 +546,6 @@
   // so we can simply compare the pointers to find out if things are duplicated.
   SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_;
 
-  // Patch locations for the .text section.
-  std::vector<uintptr_t>* const text_absolute_patch_locations_;
-
   // Cache of compiler's --debuggable option.
   const bool debuggable_;
 };
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 6f1b4ec..82b9377 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -19,7 +19,6 @@
 
 #include <stdint.h>
 #include <cstddef>
-#include <map>
 #include <memory>
 
 #include "linker/relative_patcher.h"  // For linker::RelativePatcherTargetProvider.
@@ -82,8 +81,6 @@
 //
 class OatWriter {
  public:
-  typedef std::map<std::string, std::unique_ptr<std::vector<uintptr_t>>> PatchLocationsMap;
-
   OatWriter(const std::vector<const DexFile*>& dex_files,
             uint32_t image_file_location_oat_checksum,
             uintptr_t image_file_location_oat_begin,
@@ -105,19 +102,10 @@
     return bss_size_;
   }
 
-  const PatchLocationsMap& GetAbsolutePatchLocations() const {
+  const std::vector<uintptr_t>& GetAbsolutePatchLocations() const {
     return absolute_patch_locations_;
   }
 
-  std::vector<uintptr_t>* GetAbsolutePatchLocationsFor(const char* section_name) {
-    auto it = absolute_patch_locations_.emplace(
-        std::string(section_name), std::unique_ptr<std::vector<uintptr_t>>());
-    if (it.second) {  // Inserted new item.
-      it.first->second.reset(new std::vector<uintptr_t>());
-    }
-    return it.first->second.get();
-  }
-
   bool WriteRodata(OutputStream* out);
   bool WriteCode(OutputStream* out);
 
@@ -339,9 +327,8 @@
 
   std::unique_ptr<linker::RelativePatcher> relative_patcher_;
 
-  // The locations of absolute patches relative to the start of section.
-  // The map's key is the ELF's section name (including the dot).
-  PatchLocationsMap absolute_patch_locations_;
+  // The locations of absolute patches relative to the start of the executable section.
+  std::vector<uintptr_t> absolute_patch_locations_;
 
   // Map method reference to assigned offset.
   // Wrap the map in a class implementing linker::RelativePatcherTargetProvider.
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index b1d933d..9fd8c87 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1401,86 +1401,53 @@
 }
 
 template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta) {
+bool ElfFileImpl<ElfTypes>::FixupDebugSections(Elf_Addr base_address_delta) {
   if (base_address_delta == 0) {
     return true;
   }
-  if (FindSectionByName(".debug_frame") != nullptr) {
-    if (!ApplyOatPatchesTo(".debug_frame", base_address_delta)) {
-      return false;
-    }
-  }
-  if (FindSectionByName(".debug_info") != nullptr) {
-    if (!ApplyOatPatchesTo(".debug_info", base_address_delta)) {
-      return false;
-    }
-  }
-  if (FindSectionByName(".debug_line") != nullptr) {
-    if (!ApplyOatPatchesTo(".debug_line", base_address_delta)) {
-      return false;
-    }
-  }
-  return true;
+  return ApplyOatPatchesTo(".debug_frame", base_address_delta) &&
+         ApplyOatPatchesTo(".debug_info", base_address_delta) &&
+         ApplyOatPatchesTo(".debug_line", base_address_delta);
 }
 
 template <typename ElfTypes>
 bool ElfFileImpl<ElfTypes>::ApplyOatPatchesTo(
-    const char* target_section_name,
-    typename std::make_signed<Elf_Off>::type delta) {
-  auto patches_section = FindSectionByName(".oat_patches");
+    const char* target_section_name, Elf_Addr delta) {
+  auto target_section = FindSectionByName(target_section_name);
+  if (target_section == nullptr) {
+    return true;
+  }
+  std::string patches_name = target_section_name + std::string(".oat_patches");
+  auto patches_section = FindSectionByName(patches_name.c_str());
   if (patches_section == nullptr) {
-    LOG(ERROR) << ".oat_patches section not found.";
+    LOG(ERROR) << patches_name << " section not found.";
     return false;
   }
   if (patches_section->sh_type != SHT_OAT_PATCH) {
-    LOG(ERROR) << "Unexpected type of .oat_patches.";
+    LOG(ERROR) << "Unexpected type of " << patches_name;
     return false;
   }
-  auto target_section = FindSectionByName(target_section_name);
-  if (target_section == nullptr) {
-    LOG(ERROR) << target_section_name << " section not found.";
-    return false;
-  }
-  if (!ApplyOatPatches(
+  ApplyOatPatches(
       Begin() + patches_section->sh_offset,
       Begin() + patches_section->sh_offset + patches_section->sh_size,
-      target_section_name, delta,
+      delta,
       Begin() + target_section->sh_offset,
-      Begin() + target_section->sh_offset + target_section->sh_size)) {
-    LOG(ERROR) << target_section_name << " section not found in .oat_patches.";
-  }
+      Begin() + target_section->sh_offset + target_section->sh_size);
   return true;
 }
 
-// Apply .oat_patches to given section.
+// Apply LEB128 encoded patches to given section.
 template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::ApplyOatPatches(
-    const uint8_t* patches, const uint8_t* patches_end,
-    const char* target_section_name,
-    typename std::make_signed<Elf_Off>::type delta,
+void ElfFileImpl<ElfTypes>::ApplyOatPatches(
+    const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
     uint8_t* to_patch, const uint8_t* to_patch_end) {
-  // Read null-terminated section name.
-  const char* section_name;
-  while ((section_name = reinterpret_cast<const char*>(patches))[0] != '\0') {
-    patches += strlen(section_name) + 1;
-    uint32_t length = DecodeUnsignedLeb128(&patches);
-    const uint8_t* next_section = patches + length;
-    // Is it the section we want to patch?
-    if (strcmp(section_name, target_section_name) == 0) {
-      // Read LEB128 encoded list of advances.
-      while (patches < next_section) {
-        DCHECK_LT(patches, patches_end) << "Unexpected end of .oat_patches.";
-        to_patch += DecodeUnsignedLeb128(&patches);
-        DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of " << section_name;
-        // TODO: 32-bit vs 64-bit.  What is the right type to use here?
-        auto* patch_loc = reinterpret_cast<typename std::make_signed<Elf_Off>::type*>(to_patch);
-        *patch_loc += delta;
-      }
-      return true;
-    }
-    patches = next_section;
+  typedef __attribute__((__aligned__(1))) Elf_Addr UnalignedAddress;
+  while (patches < patches_end) {
+    to_patch += DecodeUnsignedLeb128(&patches);
+    DCHECK_LE(patches, patches_end) << "Unexpected end of patch list.";
+    DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of section.";
+    *reinterpret_cast<UnalignedAddress*>(to_patch) += delta;
   }
-  return false;
 }
 
 template <typename ElfTypes>
diff --git a/runtime/elf_file_impl.h b/runtime/elf_file_impl.h
index 3ad096f..0f466bd 100644
--- a/runtime/elf_file_impl.h
+++ b/runtime/elf_file_impl.h
@@ -119,12 +119,9 @@
   bool FixupProgramHeaders(Elf_Addr base_address);
   bool FixupSymbols(Elf_Addr base_address, bool dynamic);
   bool FixupRelocations(Elf_Addr base_address);
-  bool FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta);
-  bool ApplyOatPatchesTo(const char* target_section_name,
-                         typename std::make_signed<Elf_Off>::type base_address_delta);
-  static bool ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end,
-                              const char* target_section_name,
-                              typename std::make_signed<Elf_Off>::type delta,
+  bool FixupDebugSections(Elf_Addr base_address_delta);
+  bool ApplyOatPatchesTo(const char* target_section_name, Elf_Addr base_address_delta);
+  static void ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
                               uint8_t* to_patch, const uint8_t* to_patch_end);
 
   bool Strip(std::string* error_msg);