OSDN Git Service

Add patchoat check that input oat file has patch section.
[android-x86/art.git] / patchoat / patchoat.cc
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "patchoat.h"
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <sys/file.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23
24 #include <string>
25 #include <vector>
26
27 #include "art_field-inl.h"
28 #include "art_method-inl.h"
29 #include "base/dumpable.h"
30 #include "base/scoped_flock.h"
31 #include "base/stringpiece.h"
32 #include "base/stringprintf.h"
33 #include "base/unix_file/fd_file.h"
34 #include "elf_utils.h"
35 #include "elf_file.h"
36 #include "elf_file_impl.h"
37 #include "gc/space/image_space.h"
38 #include "image-inl.h"
39 #include "mirror/abstract_method.h"
40 #include "mirror/object-inl.h"
41 #include "mirror/method.h"
42 #include "mirror/reference.h"
43 #include "noop_compiler_callbacks.h"
44 #include "offsets.h"
45 #include "os.h"
46 #include "runtime.h"
47 #include "scoped_thread_state_change.h"
48 #include "thread.h"
49 #include "utils.h"
50
51 namespace art {
52
53 static bool LocationToFilename(const std::string& location, InstructionSet isa,
54                                std::string* filename) {
55   bool has_system = false;
56   bool has_cache = false;
57   // image_location = /system/framework/boot.art
58   // system_image_filename = /system/framework/<image_isa>/boot.art
59   std::string system_filename(GetSystemImageFilename(location.c_str(), isa));
60   if (OS::FileExists(system_filename.c_str())) {
61     has_system = true;
62   }
63
64   bool have_android_data = false;
65   bool dalvik_cache_exists = false;
66   bool is_global_cache = false;
67   std::string dalvik_cache;
68   GetDalvikCache(GetInstructionSetString(isa), false, &dalvik_cache,
69                  &have_android_data, &dalvik_cache_exists, &is_global_cache);
70
71   std::string cache_filename;
72   if (have_android_data && dalvik_cache_exists) {
73     // Always set output location even if it does not exist,
74     // so that the caller knows where to create the image.
75     //
76     // image_location = /system/framework/boot.art
77     // *image_filename = /data/dalvik-cache/<image_isa>/boot.art
78     std::string error_msg;
79     if (GetDalvikCacheFilename(location.c_str(), dalvik_cache.c_str(),
80                                &cache_filename, &error_msg)) {
81       has_cache = true;
82     }
83   }
84   if (has_system) {
85     *filename = system_filename;
86     return true;
87   } else if (has_cache) {
88     *filename = cache_filename;
89     return true;
90   } else {
91     return false;
92   }
93 }
94
95 static const OatHeader* GetOatHeader(const ElfFile* elf_file) {
96   uint64_t off = 0;
97   if (!elf_file->GetSectionOffsetAndSize(".rodata", &off, nullptr)) {
98     return nullptr;
99   }
100
101   OatHeader* oat_header = reinterpret_cast<OatHeader*>(elf_file->Begin() + off);
102   return oat_header;
103 }
104
105 // This function takes an elf file and reads the current patch delta value
106 // encoded in its oat header value
107 static bool ReadOatPatchDelta(const ElfFile* elf_file, off_t* delta, std::string* error_msg) {
108   const OatHeader* oat_header = GetOatHeader(elf_file);
109   if (oat_header == nullptr) {
110     *error_msg = "Unable to get oat header from elf file.";
111     return false;
112   }
113   if (!oat_header->IsValid()) {
114     *error_msg = "Elf file has an invalid oat header";
115     return false;
116   }
117   *delta = oat_header->GetImagePatchDelta();
118   return true;
119 }
120
121 static File* CreateOrOpen(const char* name, bool* created) {
122   if (OS::FileExists(name)) {
123     *created = false;
124     return OS::OpenFileReadWrite(name);
125   } else {
126     *created = true;
127     std::unique_ptr<File> f(OS::CreateEmptyFile(name));
128     if (f.get() != nullptr) {
129       if (fchmod(f->Fd(), 0644) != 0) {
130         PLOG(ERROR) << "Unable to make " << name << " world readable";
131         TEMP_FAILURE_RETRY(unlink(name));
132         return nullptr;
133       }
134     }
135     return f.release();
136   }
137 }
138
139 // Either try to close the file (close=true), or erase it.
140 static bool FinishFile(File* file, bool close) {
141   if (close) {
142     if (file->FlushCloseOrErase() != 0) {
143       PLOG(ERROR) << "Failed to flush and close file.";
144       return false;
145     }
146     return true;
147   } else {
148     file->Erase();
149     return false;
150   }
151 }
152
153 bool PatchOat::Patch(const std::string& image_location,
154                      off_t delta,
155                      const std::string& output_directory,
156                      InstructionSet isa,
157                      TimingLogger* timings) {
158   CHECK(Runtime::Current() == nullptr);
159   CHECK(!image_location.empty()) << "image file must have a filename.";
160
161   TimingLogger::ScopedTiming t("Runtime Setup", timings);
162
163   CHECK_NE(isa, kNone);
164   const char* isa_name = GetInstructionSetString(isa);
165
166   // Set up the runtime
167   RuntimeOptions options;
168   NoopCompilerCallbacks callbacks;
169   options.push_back(std::make_pair("compilercallbacks", &callbacks));
170   std::string img = "-Ximage:" + image_location;
171   options.push_back(std::make_pair(img.c_str(), nullptr));
172   options.push_back(std::make_pair("imageinstructionset", reinterpret_cast<const void*>(isa_name)));
173   options.push_back(std::make_pair("-Xno-sig-chain", nullptr));
174   if (!Runtime::Create(options, false)) {
175     LOG(ERROR) << "Unable to initialize runtime";
176     return false;
177   }
178   // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
179   // give it away now and then switch to a more manageable ScopedObjectAccess.
180   Thread::Current()->TransitionFromRunnableToSuspended(kNative);
181   ScopedObjectAccess soa(Thread::Current());
182
183   t.NewTiming("Image and oat Patching setup");
184   std::vector<gc::space::ImageSpace*> spaces = Runtime::Current()->GetHeap()->GetBootImageSpaces();
185   std::map<gc::space::ImageSpace*, std::unique_ptr<File>> space_to_file_map;
186   std::map<gc::space::ImageSpace*, std::unique_ptr<MemMap>> space_to_memmap_map;
187   std::map<gc::space::ImageSpace*, PatchOat> space_to_patchoat_map;
188   std::map<gc::space::ImageSpace*, bool> space_to_skip_patching_map;
189
190   for (size_t i = 0; i < spaces.size(); ++i) {
191     gc::space::ImageSpace* space = spaces[i];
192     std::string input_image_filename = space->GetImageFilename();
193     std::unique_ptr<File> input_image(OS::OpenFileForReading(input_image_filename.c_str()));
194     if (input_image.get() == nullptr) {
195       LOG(ERROR) << "Unable to open input image file at " << input_image_filename;
196       return false;
197     }
198
199     int64_t image_len = input_image->GetLength();
200     if (image_len < 0) {
201       LOG(ERROR) << "Error while getting image length";
202       return false;
203     }
204     ImageHeader image_header;
205     if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header),
206                                                   sizeof(image_header), 0)) {
207       LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath();
208     }
209
210     /*bool is_image_pic = */IsImagePic(image_header, input_image->GetPath());
211     // Nothing special to do right now since the image always needs to get patched.
212     // Perhaps in some far-off future we may have images with relative addresses that are true-PIC.
213
214     // Create the map where we will write the image patches to.
215     std::string error_msg;
216     std::unique_ptr<MemMap> image(MemMap::MapFile(image_len,
217                                                   PROT_READ | PROT_WRITE,
218                                                   MAP_PRIVATE,
219                                                   input_image->Fd(),
220                                                   0,
221                                                   /*low_4gb*/false,
222                                                   input_image->GetPath().c_str(),
223                                                   &error_msg));
224     if (image.get() == nullptr) {
225       LOG(ERROR) << "Unable to map image file " << input_image->GetPath() << " : " << error_msg;
226       return false;
227     }
228     space_to_file_map.emplace(space, std::move(input_image));
229     space_to_memmap_map.emplace(space, std::move(image));
230   }
231
232   for (size_t i = 0; i < spaces.size(); ++i) {
233     gc::space::ImageSpace* space = spaces[i];
234     std::string input_image_filename = space->GetImageFilename();
235     std::string input_oat_filename =
236         ImageHeader::GetOatLocationFromImageLocation(input_image_filename);
237     std::unique_ptr<File> input_oat_file(OS::OpenFileForReading(input_oat_filename.c_str()));
238     if (input_oat_file.get() == nullptr) {
239       LOG(ERROR) << "Unable to open input oat file at " << input_oat_filename;
240       return false;
241     }
242     std::string error_msg;
243     std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat_file.get(),
244                                                PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg));
245     if (elf.get() == nullptr) {
246       LOG(ERROR) << "Unable to open oat file " << input_oat_file->GetPath() << " : " << error_msg;
247       return false;
248     }
249
250     bool skip_patching_oat = false;
251     MaybePic is_oat_pic = IsOatPic(elf.get());
252     if (is_oat_pic >= ERROR_FIRST) {
253       // Error logged by IsOatPic
254       return false;
255     } else if (is_oat_pic == PIC) {
256       // Do not need to do ELF-file patching. Create a symlink and skip the ELF patching.
257
258       std::string converted_image_filename = space->GetImageLocation();
259       std::replace(converted_image_filename.begin() + 1, converted_image_filename.end(), '/', '@');
260       std::string output_image_filename = output_directory +
261                                           (StartsWith(converted_image_filename, "/") ? "" : "/") +
262                                           converted_image_filename;
263       std::string output_oat_filename =
264           ImageHeader::GetOatLocationFromImageLocation(output_image_filename);
265
266       if (!ReplaceOatFileWithSymlink(input_oat_file->GetPath(),
267                                      output_oat_filename,
268                                      false,
269                                      true)) {
270         // Errors already logged by above call.
271         return false;
272       }
273       // Don't patch the OAT, since we just symlinked it. Image still needs patching.
274       skip_patching_oat = true;
275     } else {
276       CHECK(is_oat_pic == NOT_PIC);
277     }
278
279     PatchOat& p = space_to_patchoat_map.emplace(space,
280                                                 PatchOat(
281                                                     isa,
282                                                     elf.release(),
283                                                     space_to_memmap_map.find(space)->second.get(),
284                                                     space->GetLiveBitmap(),
285                                                     space->GetMemMap(),
286                                                     delta,
287                                                     &space_to_memmap_map,
288                                                     timings)).first->second;
289
290     t.NewTiming("Patching files");
291     if (!skip_patching_oat && !p.PatchElf()) {
292       LOG(ERROR) << "Failed to patch oat file " << input_oat_file->GetPath();
293       return false;
294     }
295     if (!p.PatchImage(i == 0)) {
296       LOG(ERROR) << "Failed to patch image file " << input_image_filename;
297       return false;
298     }
299
300     space_to_skip_patching_map.emplace(space, skip_patching_oat);
301   }
302
303   for (size_t i = 0; i < spaces.size(); ++i) {
304     gc::space::ImageSpace* space = spaces[i];
305     std::string input_image_filename = space->GetImageFilename();
306
307     t.NewTiming("Writing files");
308     std::string converted_image_filename = space->GetImageLocation();
309     std::replace(converted_image_filename.begin() + 1, converted_image_filename.end(), '/', '@');
310     std::string output_image_filename = output_directory +
311                                         (StartsWith(converted_image_filename, "/") ? "" : "/") +
312                                         converted_image_filename;
313     bool new_oat_out;
314     std::unique_ptr<File>
315         output_image_file(CreateOrOpen(output_image_filename.c_str(), &new_oat_out));
316     if (output_image_file.get() == nullptr) {
317       LOG(ERROR) << "Failed to open output image file at " << output_image_filename;
318       return false;
319     }
320
321     PatchOat& p = space_to_patchoat_map.find(space)->second;
322
323     if (!p.WriteImage(output_image_file.get())) {
324       LOG(ERROR) << "Failed to write image file " << output_image_file->GetPath();
325       return false;
326     }
327     FinishFile(output_image_file.get(), true);
328
329     bool skip_patching_oat = space_to_skip_patching_map.find(space)->second;
330     if (!skip_patching_oat) {
331       std::string output_oat_filename =
332           ImageHeader::GetOatLocationFromImageLocation(output_image_filename);
333       std::unique_ptr<File>
334           output_oat_file(CreateOrOpen(output_oat_filename.c_str(), &new_oat_out));
335       if (output_oat_file.get() == nullptr) {
336         LOG(ERROR) << "Failed to open output oat file at " << output_oat_filename;
337         return false;
338       }
339       if (!p.WriteElf(output_oat_file.get())) {
340         LOG(ERROR) << "Failed to write oat file " << output_oat_file->GetPath();
341         return false;
342       }
343       FinishFile(output_oat_file.get(), true);
344     }
345   }
346   return true;
347 }
348
349 bool PatchOat::WriteElf(File* out) {
350   TimingLogger::ScopedTiming t("Writing Elf File", timings_);
351
352   CHECK(oat_file_.get() != nullptr);
353   CHECK(out != nullptr);
354   size_t expect = oat_file_->Size();
355   if (out->WriteFully(reinterpret_cast<char*>(oat_file_->Begin()), expect) &&
356       out->SetLength(expect) == 0) {
357     return true;
358   } else {
359     LOG(ERROR) << "Writing to oat file " << out->GetPath() << " failed.";
360     return false;
361   }
362 }
363
364 bool PatchOat::WriteImage(File* out) {
365   TimingLogger::ScopedTiming t("Writing image File", timings_);
366   std::string error_msg;
367
368   ScopedFlock img_flock;
369   img_flock.Init(out, &error_msg);
370
371   CHECK(image_ != nullptr);
372   CHECK(out != nullptr);
373   size_t expect = image_->Size();
374   if (out->WriteFully(reinterpret_cast<char*>(image_->Begin()), expect) &&
375       out->SetLength(expect) == 0) {
376     return true;
377   } else {
378     LOG(ERROR) << "Writing to image file " << out->GetPath() << " failed.";
379     return false;
380   }
381 }
382
383 bool PatchOat::IsImagePic(const ImageHeader& image_header, const std::string& image_path) {
384   if (!image_header.CompilePic()) {
385     if (kIsDebugBuild) {
386       LOG(INFO) << "image at location " << image_path << " was *not* compiled pic";
387     }
388     return false;
389   }
390
391   if (kIsDebugBuild) {
392     LOG(INFO) << "image at location " << image_path << " was compiled PIC";
393   }
394
395   return true;
396 }
397
398 PatchOat::MaybePic PatchOat::IsOatPic(const ElfFile* oat_in) {
399   if (oat_in == nullptr) {
400     LOG(ERROR) << "No ELF input oat fie available";
401     return ERROR_OAT_FILE;
402   }
403
404   const std::string& file_path = oat_in->GetFile().GetPath();
405
406   const OatHeader* oat_header = GetOatHeader(oat_in);
407   if (oat_header == nullptr) {
408     LOG(ERROR) << "Failed to find oat header in oat file " << file_path;
409     return ERROR_OAT_FILE;
410   }
411
412   if (!oat_header->IsValid()) {
413     LOG(ERROR) << "Elf file " << file_path << " has an invalid oat header";
414     return ERROR_OAT_FILE;
415   }
416
417   bool is_pic = oat_header->IsPic();
418   if (kIsDebugBuild) {
419     LOG(INFO) << "Oat file at " << file_path << " is " << (is_pic ? "PIC" : "not pic");
420   }
421
422   return is_pic ? PIC : NOT_PIC;
423 }
424
425 bool PatchOat::ReplaceOatFileWithSymlink(const std::string& input_oat_filename,
426                                          const std::string& output_oat_filename,
427                                          bool output_oat_opened_from_fd,
428                                          bool new_oat_out) {
429   // Need a file when we are PIC, since we symlink over it. Refusing to symlink into FD.
430   if (output_oat_opened_from_fd) {
431     // TODO: installd uses --output-oat-fd. Should we change class linking logic for PIC?
432     LOG(ERROR) << "No output oat filename specified, needs filename for when we are PIC";
433     return false;
434   }
435
436   // Image was PIC. Create symlink where the oat is supposed to go.
437   if (!new_oat_out) {
438     LOG(ERROR) << "Oat file " << output_oat_filename << " already exists, refusing to overwrite";
439     return false;
440   }
441
442   // Delete the original file, since we won't need it.
443   TEMP_FAILURE_RETRY(unlink(output_oat_filename.c_str()));
444
445   // Create a symlink from the old oat to the new oat
446   if (symlink(input_oat_filename.c_str(), output_oat_filename.c_str()) < 0) {
447     int err = errno;
448     LOG(ERROR) << "Failed to create symlink at " << output_oat_filename
449                << " error(" << err << "): " << strerror(err);
450     return false;
451   }
452
453   if (kIsDebugBuild) {
454     LOG(INFO) << "Created symlink " << output_oat_filename << " -> " << input_oat_filename;
455   }
456
457   return true;
458 }
459
460 class PatchOatArtFieldVisitor : public ArtFieldVisitor {
461  public:
462   explicit PatchOatArtFieldVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {}
463
464   void Visit(ArtField* field) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
465     ArtField* const dest = patch_oat_->RelocatedCopyOf(field);
466     dest->SetDeclaringClass(patch_oat_->RelocatedAddressOfPointer(field->GetDeclaringClass()));
467   }
468
469  private:
470   PatchOat* const patch_oat_;
471 };
472
473 void PatchOat::PatchArtFields(const ImageHeader* image_header) {
474   PatchOatArtFieldVisitor visitor(this);
475   const auto& section = image_header->GetImageSection(ImageHeader::kSectionArtFields);
476   section.VisitPackedArtFields(&visitor, heap_->Begin());
477 }
478
479 class PatchOatArtMethodVisitor : public ArtMethodVisitor {
480  public:
481   explicit PatchOatArtMethodVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {}
482
483   void Visit(ArtMethod* method) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
484     ArtMethod* const dest = patch_oat_->RelocatedCopyOf(method);
485     patch_oat_->FixupMethod(method, dest);
486   }
487
488  private:
489   PatchOat* const patch_oat_;
490 };
491
492 void PatchOat::PatchArtMethods(const ImageHeader* image_header) {
493   const auto& section = image_header->GetMethodsSection();
494   const size_t pointer_size = InstructionSetPointerSize(isa_);
495   PatchOatArtMethodVisitor visitor(this);
496   section.VisitPackedArtMethods(&visitor, heap_->Begin(), pointer_size);
497 }
498
499 class FixupRootVisitor : public RootVisitor {
500  public:
501   explicit FixupRootVisitor(const PatchOat* patch_oat) : patch_oat_(patch_oat) {
502   }
503
504   void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info ATTRIBUTE_UNUSED)
505       OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
506     for (size_t i = 0; i < count; ++i) {
507       *roots[i] = patch_oat_->RelocatedAddressOfPointer(*roots[i]);
508     }
509   }
510
511   void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
512                   const RootInfo& info ATTRIBUTE_UNUSED)
513       OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
514     for (size_t i = 0; i < count; ++i) {
515       roots[i]->Assign(patch_oat_->RelocatedAddressOfPointer(roots[i]->AsMirrorPtr()));
516     }
517   }
518
519  private:
520   const PatchOat* const patch_oat_;
521 };
522
523 void PatchOat::PatchInternedStrings(const ImageHeader* image_header) {
524   const auto& section = image_header->GetImageSection(ImageHeader::kSectionInternedStrings);
525   InternTable temp_table;
526   // Note that we require that ReadFromMemory does not make an internal copy of the elements.
527   // This also relies on visit roots not doing any verification which could fail after we update
528   // the roots to be the image addresses.
529   temp_table.AddTableFromMemory(image_->Begin() + section.Offset());
530   FixupRootVisitor visitor(this);
531   temp_table.VisitRoots(&visitor, kVisitRootFlagAllRoots);
532 }
533
534 void PatchOat::PatchClassTable(const ImageHeader* image_header) {
535   const auto& section = image_header->GetImageSection(ImageHeader::kSectionClassTable);
536   if (section.Size() == 0) {
537     return;
538   }
539   // Note that we require that ReadFromMemory does not make an internal copy of the elements.
540   // This also relies on visit roots not doing any verification which could fail after we update
541   // the roots to be the image addresses.
542   WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
543   ClassTable temp_table;
544   temp_table.ReadFromMemory(image_->Begin() + section.Offset());
545   FixupRootVisitor visitor(this);
546   BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(&visitor, RootInfo(kRootUnknown));
547   temp_table.VisitRoots(buffered_visitor);
548 }
549
550
551 class RelocatedPointerVisitor {
552  public:
553   explicit RelocatedPointerVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {}
554
555   template <typename T>
556   T* operator()(T* ptr) const {
557     return patch_oat_->RelocatedAddressOfPointer(ptr);
558   }
559
560  private:
561   PatchOat* const patch_oat_;
562 };
563
564 void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots) {
565   auto* dex_caches = down_cast<mirror::ObjectArray<mirror::DexCache>*>(
566       img_roots->Get(ImageHeader::kDexCaches));
567   const size_t pointer_size = InstructionSetPointerSize(isa_);
568   for (size_t i = 0, count = dex_caches->GetLength(); i < count; ++i) {
569     auto* orig_dex_cache = dex_caches->GetWithoutChecks(i);
570     auto* copy_dex_cache = RelocatedCopyOf(orig_dex_cache);
571     // Though the DexCache array fields are usually treated as native pointers, we set the full
572     // 64-bit values here, clearing the top 32 bits for 32-bit targets. The zero-extension is
573     // done by casting to the unsigned type uintptr_t before casting to int64_t, i.e.
574     //     static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + offset))).
575     GcRoot<mirror::String>* orig_strings = orig_dex_cache->GetStrings();
576     GcRoot<mirror::String>* relocated_strings = RelocatedAddressOfPointer(orig_strings);
577     copy_dex_cache->SetField64<false>(
578         mirror::DexCache::StringsOffset(),
579         static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_strings)));
580     if (orig_strings != nullptr) {
581       orig_dex_cache->FixupStrings(RelocatedCopyOf(orig_strings), RelocatedPointerVisitor(this));
582     }
583     GcRoot<mirror::Class>* orig_types = orig_dex_cache->GetResolvedTypes();
584     GcRoot<mirror::Class>* relocated_types = RelocatedAddressOfPointer(orig_types);
585     copy_dex_cache->SetField64<false>(
586         mirror::DexCache::ResolvedTypesOffset(),
587         static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_types)));
588     if (orig_types != nullptr) {
589       orig_dex_cache->FixupResolvedTypes(RelocatedCopyOf(orig_types),
590                                          RelocatedPointerVisitor(this));
591     }
592     ArtMethod** orig_methods = orig_dex_cache->GetResolvedMethods();
593     ArtMethod** relocated_methods = RelocatedAddressOfPointer(orig_methods);
594     copy_dex_cache->SetField64<false>(
595         mirror::DexCache::ResolvedMethodsOffset(),
596         static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_methods)));
597     if (orig_methods != nullptr) {
598       ArtMethod** copy_methods = RelocatedCopyOf(orig_methods);
599       for (size_t j = 0, num = orig_dex_cache->NumResolvedMethods(); j != num; ++j) {
600         ArtMethod* orig = mirror::DexCache::GetElementPtrSize(orig_methods, j, pointer_size);
601         ArtMethod* copy = RelocatedAddressOfPointer(orig);
602         mirror::DexCache::SetElementPtrSize(copy_methods, j, copy, pointer_size);
603       }
604     }
605     ArtField** orig_fields = orig_dex_cache->GetResolvedFields();
606     ArtField** relocated_fields = RelocatedAddressOfPointer(orig_fields);
607     copy_dex_cache->SetField64<false>(
608         mirror::DexCache::ResolvedFieldsOffset(),
609         static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_fields)));
610     if (orig_fields != nullptr) {
611       ArtField** copy_fields = RelocatedCopyOf(orig_fields);
612       for (size_t j = 0, num = orig_dex_cache->NumResolvedFields(); j != num; ++j) {
613         ArtField* orig = mirror::DexCache::GetElementPtrSize(orig_fields, j, pointer_size);
614         ArtField* copy = RelocatedAddressOfPointer(orig);
615         mirror::DexCache::SetElementPtrSize(copy_fields, j, copy, pointer_size);
616       }
617     }
618   }
619 }
620
621 bool PatchOat::PatchImage(bool primary_image) {
622   ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
623   CHECK_GT(image_->Size(), sizeof(ImageHeader));
624   // These are the roots from the original file.
625   auto* img_roots = image_header->GetImageRoots();
626   image_header->RelocateImage(delta_);
627
628   PatchArtFields(image_header);
629   PatchArtMethods(image_header);
630   PatchInternedStrings(image_header);
631   PatchClassTable(image_header);
632   // Patch dex file int/long arrays which point to ArtFields.
633   PatchDexFileArrays(img_roots);
634
635   if (primary_image) {
636     VisitObject(img_roots);
637   }
638
639   if (!image_header->IsValid()) {
640     LOG(ERROR) << "relocation renders image header invalid";
641     return false;
642   }
643
644   {
645     TimingLogger::ScopedTiming t("Walk Bitmap", timings_);
646     // Walk the bitmap.
647     WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
648     bitmap_->Walk(PatchOat::BitmapCallback, this);
649   }
650   return true;
651 }
652
653 bool PatchOat::InHeap(mirror::Object* o) {
654   uintptr_t begin = reinterpret_cast<uintptr_t>(heap_->Begin());
655   uintptr_t end = reinterpret_cast<uintptr_t>(heap_->End());
656   uintptr_t obj = reinterpret_cast<uintptr_t>(o);
657   return o == nullptr || (begin <= obj && obj < end);
658 }
659
660 void PatchOat::PatchVisitor::operator() (mirror::Object* obj, MemberOffset off,
661                                          bool is_static_unused ATTRIBUTE_UNUSED) const {
662   mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off);
663   mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent);
664   copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object);
665 }
666
667 void PatchOat::PatchVisitor::operator() (mirror::Class* cls ATTRIBUTE_UNUSED,
668                                          mirror::Reference* ref) const {
669   MemberOffset off = mirror::Reference::ReferentOffset();
670   mirror::Object* referent = ref->GetReferent();
671   DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap.";
672   mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent);
673   copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object);
674 }
675
676 // Called by BitmapCallback
677 void PatchOat::VisitObject(mirror::Object* object) {
678   mirror::Object* copy = RelocatedCopyOf(object);
679   CHECK(copy != nullptr);
680   if (kUseBakerOrBrooksReadBarrier) {
681     object->AssertReadBarrierPointer();
682     if (kUseBrooksReadBarrier) {
683       mirror::Object* moved_to = RelocatedAddressOfPointer(object);
684       copy->SetReadBarrierPointer(moved_to);
685       DCHECK_EQ(copy->GetReadBarrierPointer(), moved_to);
686     }
687   }
688   PatchOat::PatchVisitor visitor(this, copy);
689   object->VisitReferences<kVerifyNone>(visitor, visitor);
690   if (object->IsClass<kVerifyNone>()) {
691     const size_t pointer_size = InstructionSetPointerSize(isa_);
692     mirror::Class* klass = object->AsClass();
693     mirror::Class* copy_klass = down_cast<mirror::Class*>(copy);
694     RelocatedPointerVisitor native_visitor(this);
695     klass->FixupNativePointers(copy_klass, pointer_size, native_visitor);
696     auto* vtable = klass->GetVTable();
697     if (vtable != nullptr) {
698       vtable->Fixup(RelocatedCopyOfFollowImages(vtable), pointer_size, native_visitor);
699     }
700     auto* iftable = klass->GetIfTable();
701     if (iftable != nullptr) {
702       for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
703         if (iftable->GetMethodArrayCount(i) > 0) {
704           auto* method_array = iftable->GetMethodArray(i);
705           CHECK(method_array != nullptr);
706           method_array->Fixup(RelocatedCopyOfFollowImages(method_array),
707                               pointer_size,
708                               native_visitor);
709         }
710       }
711     }
712   } else if (object->GetClass() == mirror::Method::StaticClass() ||
713              object->GetClass() == mirror::Constructor::StaticClass()) {
714     // Need to go update the ArtMethod.
715     auto* dest = down_cast<mirror::AbstractMethod*>(copy);
716     auto* src = down_cast<mirror::AbstractMethod*>(object);
717     dest->SetArtMethod(RelocatedAddressOfPointer(src->GetArtMethod()));
718   }
719 }
720
721 void PatchOat::FixupMethod(ArtMethod* object, ArtMethod* copy) {
722   const size_t pointer_size = InstructionSetPointerSize(isa_);
723   copy->CopyFrom(object, pointer_size);
724   // Just update the entry points if it looks like we should.
725   // TODO: sanity check all the pointers' values
726   copy->SetDeclaringClass(RelocatedAddressOfPointer(object->GetDeclaringClass()));
727   copy->SetDexCacheResolvedMethods(
728       RelocatedAddressOfPointer(object->GetDexCacheResolvedMethods(pointer_size)), pointer_size);
729   copy->SetDexCacheResolvedTypes(
730       RelocatedAddressOfPointer(object->GetDexCacheResolvedTypes(pointer_size)), pointer_size);
731   copy->SetEntryPointFromQuickCompiledCodePtrSize(RelocatedAddressOfPointer(
732       object->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size)), pointer_size);
733   copy->SetEntryPointFromJniPtrSize(RelocatedAddressOfPointer(
734       object->GetEntryPointFromJniPtrSize(pointer_size)), pointer_size);
735 }
736
737 bool PatchOat::Patch(File* input_oat, off_t delta, File* output_oat, TimingLogger* timings,
738                      bool output_oat_opened_from_fd, bool new_oat_out) {
739   CHECK(input_oat != nullptr);
740   CHECK(output_oat != nullptr);
741   CHECK_GE(input_oat->Fd(), 0);
742   CHECK_GE(output_oat->Fd(), 0);
743   TimingLogger::ScopedTiming t("Setup Oat File Patching", timings);
744
745   std::string error_msg;
746   std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat,
747                                              PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg));
748   if (elf.get() == nullptr) {
749     LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg;
750     return false;
751   }
752
753   MaybePic is_oat_pic = IsOatPic(elf.get());
754   if (is_oat_pic >= ERROR_FIRST) {
755     // Error logged by IsOatPic
756     return false;
757   } else if (is_oat_pic == PIC) {
758     // Do not need to do ELF-file patching. Create a symlink and skip the rest.
759     // Any errors will be logged by the function call.
760     return ReplaceOatFileWithSymlink(input_oat->GetPath(),
761                                      output_oat->GetPath(),
762                                      output_oat_opened_from_fd,
763                                      new_oat_out);
764   } else {
765     CHECK(is_oat_pic == NOT_PIC);
766   }
767
768   PatchOat p(elf.release(), delta, timings);
769   t.NewTiming("Patch Oat file");
770   if (!p.PatchElf()) {
771     return false;
772   }
773
774   t.NewTiming("Writing oat file");
775   if (!p.WriteElf(output_oat)) {
776     return false;
777   }
778   return true;
779 }
780
781 template <typename ElfFileImpl>
782 bool PatchOat::PatchOatHeader(ElfFileImpl* oat_file) {
783   auto rodata_sec = oat_file->FindSectionByName(".rodata");
784   if (rodata_sec == nullptr) {
785     return false;
786   }
787   OatHeader* oat_header = reinterpret_cast<OatHeader*>(oat_file->Begin() + rodata_sec->sh_offset);
788   if (!oat_header->IsValid()) {
789     LOG(ERROR) << "Elf file " << oat_file->GetFile().GetPath() << " has an invalid oat header";
790     return false;
791   }
792   oat_header->RelocateOat(delta_);
793   return true;
794 }
795
796 bool PatchOat::PatchElf() {
797   if (oat_file_->Is64Bit())
798     return PatchElf<ElfFileImpl64>(oat_file_->GetImpl64());
799   else
800     return PatchElf<ElfFileImpl32>(oat_file_->GetImpl32());
801 }
802
803 template <typename ElfFileImpl>
804 bool PatchOat::PatchElf(ElfFileImpl* oat_file) {
805   TimingLogger::ScopedTiming t("Fixup Elf Text Section", timings_);
806
807   // Fix up absolute references to locations within the boot image.
808   if (!oat_file->ApplyOatPatchesTo(".text", delta_)) {
809     return false;
810   }
811
812   // Update the OatHeader fields referencing the boot image.
813   if (!PatchOatHeader<ElfFileImpl>(oat_file)) {
814     return false;
815   }
816
817   bool need_boot_oat_fixup = true;
818   for (unsigned int i = 0; i < oat_file->GetProgramHeaderNum(); ++i) {
819     auto hdr = oat_file->GetProgramHeader(i);
820     if (hdr->p_type == PT_LOAD && hdr->p_vaddr == 0u) {
821       need_boot_oat_fixup = false;
822       break;
823     }
824   }
825   if (!need_boot_oat_fixup) {
826     // This is an app oat file that can be loaded at an arbitrary address in memory.
827     // Boot image references were patched above and there's nothing else to do.
828     return true;
829   }
830
831   // This is a boot oat file that's loaded at a particular address and we need
832   // to patch all absolute addresses, starting with ELF program headers.
833
834   t.NewTiming("Fixup Elf Headers");
835   // Fixup Phdr's
836   oat_file->FixupProgramHeaders(delta_);
837
838   t.NewTiming("Fixup Section Headers");
839   // Fixup Shdr's
840   oat_file->FixupSectionHeaders(delta_);
841
842   t.NewTiming("Fixup Dynamics");
843   oat_file->FixupDynamic(delta_);
844
845   t.NewTiming("Fixup Elf Symbols");
846   // Fixup dynsym
847   if (!oat_file->FixupSymbols(delta_, true)) {
848     return false;
849   }
850   // Fixup symtab
851   if (!oat_file->FixupSymbols(delta_, false)) {
852     return false;
853   }
854
855   t.NewTiming("Fixup Debug Sections");
856   if (!oat_file->FixupDebugSections(delta_)) {
857     return false;
858   }
859
860   return true;
861 }
862
863 static int orig_argc;
864 static char** orig_argv;
865
866 static std::string CommandLine() {
867   std::vector<std::string> command;
868   for (int i = 0; i < orig_argc; ++i) {
869     command.push_back(orig_argv[i]);
870   }
871   return Join(command, ' ');
872 }
873
874 static void UsageErrorV(const char* fmt, va_list ap) {
875   std::string error;
876   StringAppendV(&error, fmt, ap);
877   LOG(ERROR) << error;
878 }
879
880 static void UsageError(const char* fmt, ...) {
881   va_list ap;
882   va_start(ap, fmt);
883   UsageErrorV(fmt, ap);
884   va_end(ap);
885 }
886
887 NO_RETURN static void Usage(const char *fmt, ...) {
888   va_list ap;
889   va_start(ap, fmt);
890   UsageErrorV(fmt, ap);
891   va_end(ap);
892
893   UsageError("Command: %s", CommandLine().c_str());
894   UsageError("Usage: patchoat [options]...");
895   UsageError("");
896   UsageError("  --instruction-set=<isa>: Specifies the instruction set the patched code is");
897   UsageError("      compiled for. Required if you use --input-oat-location");
898   UsageError("");
899   UsageError("  --input-oat-file=<file.oat>: Specifies the exact filename of the oat file to be");
900   UsageError("      patched.");
901   UsageError("");
902   UsageError("  --input-oat-fd=<file-descriptor>: Specifies the file-descriptor of the oat file");
903   UsageError("      to be patched.");
904   UsageError("");
905   UsageError("  --input-oat-location=<file.oat>: Specifies the 'location' to read the patched");
906   UsageError("      oat file from. If used one must also supply the --instruction-set");
907   UsageError("");
908   UsageError("  --input-image-location=<file.art>: Specifies the 'location' of the image file to");
909   UsageError("      be patched. If --instruction-set is not given it will use the instruction set");
910   UsageError("      extracted from the --input-oat-file.");
911   UsageError("");
912   UsageError("  --output-oat-file=<file.oat>: Specifies the exact file to write the patched oat");
913   UsageError("      file to.");
914   UsageError("");
915   UsageError("  --output-oat-fd=<file-descriptor>: Specifies the file-descriptor to write the");
916   UsageError("      the patched oat file to.");
917   UsageError("");
918   UsageError("  --output-image-file=<file.art>: Specifies the exact file to write the patched");
919   UsageError("      image file to.");
920   UsageError("");
921   UsageError("  --base-offset-delta=<delta>: Specify the amount to change the old base-offset by.");
922   UsageError("      This value may be negative.");
923   UsageError("");
924   UsageError("  --patched-image-location=<file.art>: Relocate the oat file to be the same as the");
925   UsageError("      image at the given location. If used one must also specify the");
926   UsageError("      --instruction-set flag. It will search for this image in the same way that");
927   UsageError("      is done when loading one.");
928   UsageError("");
929   UsageError("  --lock-output: Obtain a flock on output oat file before starting.");
930   UsageError("");
931   UsageError("  --no-lock-output: Do not attempt to obtain a flock on output oat file.");
932   UsageError("");
933   UsageError("  --dump-timings: dump out patch timing information");
934   UsageError("");
935   UsageError("  --no-dump-timings: do not dump out patch timing information");
936   UsageError("");
937
938   exit(EXIT_FAILURE);
939 }
940
941 static bool ReadBaseDelta(const char* name, off_t* delta, std::string* error_msg) {
942   CHECK(name != nullptr);
943   CHECK(delta != nullptr);
944   std::unique_ptr<File> file;
945   if (OS::FileExists(name)) {
946     file.reset(OS::OpenFileForReading(name));
947     if (file.get() == nullptr) {
948       *error_msg = "Failed to open file %s for reading";
949       return false;
950     }
951   } else {
952     *error_msg = "File %s does not exist";
953     return false;
954   }
955   CHECK(file.get() != nullptr);
956   ImageHeader hdr;
957   if (sizeof(hdr) != file->Read(reinterpret_cast<char*>(&hdr), sizeof(hdr), 0)) {
958     *error_msg = "Failed to read file %s";
959     return false;
960   }
961   if (!hdr.IsValid()) {
962     *error_msg = "%s does not contain a valid image header.";
963     return false;
964   }
965   *delta = hdr.GetPatchDelta();
966   return true;
967 }
968
969 static int patchoat_image(TimingLogger& timings,
970                           InstructionSet isa,
971                           const std::string& input_image_location,
972                           const std::string& output_image_filename,
973                           off_t base_delta,
974                           bool base_delta_set,
975                           bool debug) {
976   CHECK(!input_image_location.empty());
977   if (output_image_filename.empty()) {
978     Usage("Image patching requires --output-image-file");
979   }
980
981   if (!base_delta_set) {
982     Usage("Must supply a desired new offset or delta.");
983   }
984
985   if (!IsAligned<kPageSize>(base_delta)) {
986     Usage("Base offset/delta must be aligned to a pagesize (0x%08x) boundary.", kPageSize);
987   }
988
989   if (debug) {
990     LOG(INFO) << "moving offset by " << base_delta
991         << " (0x" << std::hex << base_delta << ") bytes or "
992         << std::dec << (base_delta/kPageSize) << " pages.";
993   }
994
995   TimingLogger::ScopedTiming pt("patch image and oat", &timings);
996
997   std::string output_directory =
998       output_image_filename.substr(0, output_image_filename.find_last_of("/"));
999   bool ret = PatchOat::Patch(input_image_location, base_delta, output_directory, isa, &timings);
1000
1001   if (kIsDebugBuild) {
1002     LOG(INFO) << "Exiting with return ... " << ret;
1003   }
1004   return ret ? EXIT_SUCCESS : EXIT_FAILURE;
1005 }
1006
1007 static int patchoat_oat(TimingLogger& timings,
1008                         InstructionSet isa,
1009                         const std::string& patched_image_location,
1010                         off_t base_delta,
1011                         bool base_delta_set,
1012                         int input_oat_fd,
1013                         const std::string& input_oat_location,
1014                         std::string input_oat_filename,
1015                         bool have_input_oat,
1016                         int output_oat_fd,
1017                         std::string output_oat_filename,
1018                         bool have_output_oat,
1019                         bool lock_output,
1020                         bool debug) {
1021   {
1022     // Only 1 of these may be set.
1023     uint32_t cnt = 0;
1024     cnt += (base_delta_set) ? 1 : 0;
1025     cnt += (!patched_image_location.empty()) ? 1 : 0;
1026     if (cnt > 1) {
1027       Usage("Only one of --base-offset-delta or --patched-image-location may be used.");
1028     } else if (cnt == 0) {
1029       Usage("Must specify --base-offset-delta or --patched-image-location.");
1030     }
1031   }
1032
1033   if (!have_input_oat || !have_output_oat) {
1034     Usage("Both input and output oat must be supplied to patch an app odex.");
1035   }
1036
1037   if (!input_oat_location.empty()) {
1038     if (!LocationToFilename(input_oat_location, isa, &input_oat_filename)) {
1039       Usage("Unable to find filename for input oat location %s", input_oat_location.c_str());
1040     }
1041     if (debug) {
1042       LOG(INFO) << "Using input-oat-file " << input_oat_filename;
1043     }
1044   }
1045
1046   bool match_delta = false;
1047   if (!patched_image_location.empty()) {
1048     std::string system_filename;
1049     bool has_system = false;
1050     std::string cache_filename;
1051     bool has_cache = false;
1052     bool has_android_data_unused = false;
1053     bool is_global_cache = false;
1054     if (!gc::space::ImageSpace::FindImageFilename(patched_image_location.c_str(), isa,
1055                                                   &system_filename, &has_system, &cache_filename,
1056                                                   &has_android_data_unused, &has_cache,
1057                                                   &is_global_cache)) {
1058       Usage("Unable to determine image file for location %s", patched_image_location.c_str());
1059     }
1060     std::string patched_image_filename;
1061     if (has_cache) {
1062       patched_image_filename = cache_filename;
1063     } else if (has_system) {
1064       LOG(WARNING) << "Only image file found was in /system for image location "
1065           << patched_image_location;
1066       patched_image_filename = system_filename;
1067     } else {
1068       Usage("Unable to determine image file for location %s", patched_image_location.c_str());
1069     }
1070     if (debug) {
1071       LOG(INFO) << "Using patched-image-file " << patched_image_filename;
1072     }
1073
1074     base_delta_set = true;
1075     match_delta = true;
1076     std::string error_msg;
1077     if (!ReadBaseDelta(patched_image_filename.c_str(), &base_delta, &error_msg)) {
1078       Usage(error_msg.c_str(), patched_image_filename.c_str());
1079     }
1080   }
1081
1082   if (!IsAligned<kPageSize>(base_delta)) {
1083     Usage("Base offset/delta must be alligned to a pagesize (0x%08x) boundary.", kPageSize);
1084   }
1085
1086   // Do we need to cleanup output files if we fail?
1087   bool new_oat_out = false;
1088
1089   std::unique_ptr<File> input_oat;
1090   std::unique_ptr<File> output_oat;
1091
1092   if (input_oat_fd != -1) {
1093     if (input_oat_filename.empty()) {
1094       input_oat_filename = "input-oat-file";
1095     }
1096     input_oat.reset(new File(input_oat_fd, input_oat_filename, false));
1097     if (input_oat_fd == output_oat_fd) {
1098       input_oat.get()->DisableAutoClose();
1099     }
1100     if (input_oat == nullptr) {
1101       // Unlikely, but ensure exhaustive logging in non-0 exit code case
1102       LOG(ERROR) << "Failed to open input oat file by its FD" << input_oat_fd;
1103       return EXIT_FAILURE;
1104     }
1105   } else {
1106     CHECK(!input_oat_filename.empty());
1107     input_oat.reset(OS::OpenFileForReading(input_oat_filename.c_str()));
1108     if (input_oat == nullptr) {
1109       int err = errno;
1110       LOG(ERROR) << "Failed to open input oat file " << input_oat_filename
1111           << ": " << strerror(err) << "(" << err << ")";
1112       return EXIT_FAILURE;
1113     }
1114   }
1115
1116   std::string error_msg;
1117   std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat.get(), PROT_READ, MAP_PRIVATE, &error_msg));
1118   if (elf.get() == nullptr) {
1119     LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg;
1120     return EXIT_FAILURE;
1121   }
1122   if (!elf->HasSection(".text.oat_patches")) {
1123     LOG(ERROR) << "missing oat patch section in input oat file " << input_oat->GetPath();
1124     return EXIT_FAILURE;
1125   }
1126
1127   if (output_oat_fd != -1) {
1128     if (output_oat_filename.empty()) {
1129       output_oat_filename = "output-oat-file";
1130     }
1131     output_oat.reset(new File(output_oat_fd, output_oat_filename, true));
1132     if (output_oat == nullptr) {
1133       // Unlikely, but ensure exhaustive logging in non-0 exit code case
1134       LOG(ERROR) << "Failed to open output oat file by its FD" << output_oat_fd;
1135     }
1136   } else {
1137     CHECK(!output_oat_filename.empty());
1138     output_oat.reset(CreateOrOpen(output_oat_filename.c_str(), &new_oat_out));
1139     if (output_oat == nullptr) {
1140       int err = errno;
1141       LOG(ERROR) << "Failed to open output oat file " << output_oat_filename
1142           << ": " << strerror(err) << "(" << err << ")";
1143     }
1144   }
1145
1146   // TODO: get rid of this.
1147   auto cleanup = [&output_oat_filename, &new_oat_out](bool success) {
1148     if (!success) {
1149       if (new_oat_out) {
1150         CHECK(!output_oat_filename.empty());
1151         TEMP_FAILURE_RETRY(unlink(output_oat_filename.c_str()));
1152       }
1153     }
1154
1155     if (kIsDebugBuild) {
1156       LOG(INFO) << "Cleaning up.. success? " << success;
1157     }
1158   };
1159
1160   if (output_oat.get() == nullptr) {
1161     cleanup(false);
1162     return EXIT_FAILURE;
1163   }
1164
1165   if (match_delta) {
1166     // Figure out what the current delta is so we can match it to the desired delta.
1167     off_t current_delta = 0;
1168     if (!ReadOatPatchDelta(elf.get(), &current_delta, &error_msg)) {
1169       LOG(ERROR) << "Unable to get current delta: " << error_msg;
1170       cleanup(false);
1171       return EXIT_FAILURE;
1172     }
1173     // Before this line base_delta is the desired final delta. We need it to be the actual amount to
1174     // change everything by. We subtract the current delta from it to make it this.
1175     base_delta -= current_delta;
1176     if (!IsAligned<kPageSize>(base_delta)) {
1177       LOG(ERROR) << "Given image file was relocated by an illegal delta";
1178       cleanup(false);
1179       return false;
1180     }
1181   }
1182
1183   if (debug) {
1184     LOG(INFO) << "moving offset by " << base_delta
1185         << " (0x" << std::hex << base_delta << ") bytes or "
1186         << std::dec << (base_delta/kPageSize) << " pages.";
1187   }
1188
1189   ScopedFlock output_oat_lock;
1190   if (lock_output) {
1191     if (!output_oat_lock.Init(output_oat.get(), &error_msg)) {
1192       LOG(ERROR) << "Unable to lock output oat " << output_oat->GetPath() << ": " << error_msg;
1193       cleanup(false);
1194       return EXIT_FAILURE;
1195     }
1196   }
1197
1198   TimingLogger::ScopedTiming pt("patch oat", &timings);
1199   bool ret = PatchOat::Patch(input_oat.get(), base_delta, output_oat.get(), &timings,
1200                              output_oat_fd >= 0,  // was it opened from FD?
1201                              new_oat_out);
1202   ret = FinishFile(output_oat.get(), ret);
1203
1204   if (kIsDebugBuild) {
1205     LOG(INFO) << "Exiting with return ... " << ret;
1206   }
1207   cleanup(ret);
1208   return ret ? EXIT_SUCCESS : EXIT_FAILURE;
1209 }
1210
1211 static int patchoat(int argc, char **argv) {
1212   InitLogging(argv);
1213   MemMap::Init();
1214   const bool debug = kIsDebugBuild;
1215   orig_argc = argc;
1216   orig_argv = argv;
1217   TimingLogger timings("patcher", false, false);
1218
1219   InitLogging(argv);
1220
1221   // Skip over the command name.
1222   argv++;
1223   argc--;
1224
1225   if (argc == 0) {
1226     Usage("No arguments specified");
1227   }
1228
1229   timings.StartTiming("Patchoat");
1230
1231   // cmd line args
1232   bool isa_set = false;
1233   InstructionSet isa = kNone;
1234   std::string input_oat_filename;
1235   std::string input_oat_location;
1236   int input_oat_fd = -1;
1237   bool have_input_oat = false;
1238   std::string input_image_location;
1239   std::string output_oat_filename;
1240   int output_oat_fd = -1;
1241   bool have_output_oat = false;
1242   std::string output_image_filename;
1243   off_t base_delta = 0;
1244   bool base_delta_set = false;
1245   std::string patched_image_filename;
1246   std::string patched_image_location;
1247   bool dump_timings = kIsDebugBuild;
1248   bool lock_output = true;
1249
1250   for (int i = 0; i < argc; ++i) {
1251     const StringPiece option(argv[i]);
1252     const bool log_options = false;
1253     if (log_options) {
1254       LOG(INFO) << "patchoat: option[" << i << "]=" << argv[i];
1255     }
1256     if (option.starts_with("--instruction-set=")) {
1257       isa_set = true;
1258       const char* isa_str = option.substr(strlen("--instruction-set=")).data();
1259       isa = GetInstructionSetFromString(isa_str);
1260       if (isa == kNone) {
1261         Usage("Unknown or invalid instruction set %s", isa_str);
1262       }
1263     } else if (option.starts_with("--input-oat-location=")) {
1264       if (have_input_oat) {
1265         Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used.");
1266       }
1267       have_input_oat = true;
1268       input_oat_location = option.substr(strlen("--input-oat-location=")).data();
1269     } else if (option.starts_with("--input-oat-file=")) {
1270       if (have_input_oat) {
1271         Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used.");
1272       }
1273       have_input_oat = true;
1274       input_oat_filename = option.substr(strlen("--input-oat-file=")).data();
1275     } else if (option.starts_with("--input-oat-fd=")) {
1276       if (have_input_oat) {
1277         Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used.");
1278       }
1279       have_input_oat = true;
1280       const char* oat_fd_str = option.substr(strlen("--input-oat-fd=")).data();
1281       if (!ParseInt(oat_fd_str, &input_oat_fd)) {
1282         Usage("Failed to parse --input-oat-fd argument '%s' as an integer", oat_fd_str);
1283       }
1284       if (input_oat_fd < 0) {
1285         Usage("--input-oat-fd pass a negative value %d", input_oat_fd);
1286       }
1287     } else if (option.starts_with("--input-image-location=")) {
1288       input_image_location = option.substr(strlen("--input-image-location=")).data();
1289     } else if (option.starts_with("--output-oat-file=")) {
1290       if (have_output_oat) {
1291         Usage("Only one of --output-oat-file, and --output-oat-fd may be used.");
1292       }
1293       have_output_oat = true;
1294       output_oat_filename = option.substr(strlen("--output-oat-file=")).data();
1295     } else if (option.starts_with("--output-oat-fd=")) {
1296       if (have_output_oat) {
1297         Usage("Only one of --output-oat-file, --output-oat-fd may be used.");
1298       }
1299       have_output_oat = true;
1300       const char* oat_fd_str = option.substr(strlen("--output-oat-fd=")).data();
1301       if (!ParseInt(oat_fd_str, &output_oat_fd)) {
1302         Usage("Failed to parse --output-oat-fd argument '%s' as an integer", oat_fd_str);
1303       }
1304       if (output_oat_fd < 0) {
1305         Usage("--output-oat-fd pass a negative value %d", output_oat_fd);
1306       }
1307     } else if (option.starts_with("--output-image-file=")) {
1308       output_image_filename = option.substr(strlen("--output-image-file=")).data();
1309     } else if (option.starts_with("--base-offset-delta=")) {
1310       const char* base_delta_str = option.substr(strlen("--base-offset-delta=")).data();
1311       base_delta_set = true;
1312       if (!ParseInt(base_delta_str, &base_delta)) {
1313         Usage("Failed to parse --base-offset-delta argument '%s' as an off_t", base_delta_str);
1314       }
1315     } else if (option.starts_with("--patched-image-location=")) {
1316       patched_image_location = option.substr(strlen("--patched-image-location=")).data();
1317     } else if (option == "--lock-output") {
1318       lock_output = true;
1319     } else if (option == "--no-lock-output") {
1320       lock_output = false;
1321     } else if (option == "--dump-timings") {
1322       dump_timings = true;
1323     } else if (option == "--no-dump-timings") {
1324       dump_timings = false;
1325     } else {
1326       Usage("Unknown argument %s", option.data());
1327     }
1328   }
1329
1330   // The instruction set is mandatory. This simplifies things...
1331   if (!isa_set) {
1332     Usage("Instruction set must be set.");
1333   }
1334
1335   int ret;
1336   if (!input_image_location.empty()) {
1337     ret = patchoat_image(timings,
1338                          isa,
1339                          input_image_location,
1340                          output_image_filename,
1341                          base_delta,
1342                          base_delta_set,
1343                          debug);
1344   } else {
1345     ret = patchoat_oat(timings,
1346                        isa,
1347                        patched_image_location,
1348                        base_delta,
1349                        base_delta_set,
1350                        input_oat_fd,
1351                        input_oat_location,
1352                        input_oat_filename,
1353                        have_input_oat,
1354                        output_oat_fd,
1355                        output_oat_filename,
1356                        have_output_oat,
1357                        lock_output,
1358                        debug);
1359   }
1360
1361   timings.EndTiming();
1362   if (dump_timings) {
1363     LOG(INFO) << Dumpable<TimingLogger>(timings);
1364   }
1365
1366   return ret;
1367 }
1368
1369 }  // namespace art
1370
1371 int main(int argc, char **argv) {
1372   return art::patchoat(argc, argv);
1373 }