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 "base/scoped_flock.h"
28 #include "base/stringpiece.h"
29 #include "base/stringprintf.h"
30 #include "elf_utils.h"
31 #include "elf_file.h"
32 #include "gc/space/image_space.h"
33 #include "image.h"
34 #include "instruction_set.h"
35 #include "mirror/art_field.h"
36 #include "mirror/art_field-inl.h"
37 #include "mirror/art_method.h"
38 #include "mirror/art_method-inl.h"
39 #include "mirror/object.h"
40 #include "mirror/object-inl.h"
41 #include "mirror/reference.h"
42 #include "noop_compiler_callbacks.h"
43 #include "offsets.h"
44 #include "os.h"
45 #include "runtime.h"
46 #include "scoped_thread_state_change.h"
47 #include "thread.h"
48 #include "utils.h"
49 
50 namespace art {
51 
ElfISAToInstructionSet(Elf32_Word isa)52 static InstructionSet ElfISAToInstructionSet(Elf32_Word isa) {
53   switch (isa) {
54     case EM_ARM:
55       return kArm;
56     case EM_AARCH64:
57       return kArm64;
58     case EM_386:
59       return kX86;
60     case EM_X86_64:
61       return kX86_64;
62     case EM_MIPS:
63       return kMips;
64     default:
65       return kNone;
66   }
67 }
68 
LocationToFilename(const std::string & location,InstructionSet isa,std::string * filename)69 static bool LocationToFilename(const std::string& location, InstructionSet isa,
70                                std::string* filename) {
71   bool has_system = false;
72   bool has_cache = false;
73   // image_location = /system/framework/boot.art
74   // system_image_filename = /system/framework/<image_isa>/boot.art
75   std::string system_filename(GetSystemImageFilename(location.c_str(), isa));
76   if (OS::FileExists(system_filename.c_str())) {
77     has_system = true;
78   }
79 
80   bool have_android_data = false;
81   bool dalvik_cache_exists = false;
82   bool is_global_cache = false;
83   std::string dalvik_cache;
84   GetDalvikCache(GetInstructionSetString(isa), false, &dalvik_cache,
85                  &have_android_data, &dalvik_cache_exists, &is_global_cache);
86 
87   std::string cache_filename;
88   if (have_android_data && dalvik_cache_exists) {
89     // Always set output location even if it does not exist,
90     // so that the caller knows where to create the image.
91     //
92     // image_location = /system/framework/boot.art
93     // *image_filename = /data/dalvik-cache/<image_isa>/boot.art
94     std::string error_msg;
95     if (GetDalvikCacheFilename(location.c_str(), dalvik_cache.c_str(),
96                                &cache_filename, &error_msg)) {
97       has_cache = true;
98     }
99   }
100   if (has_system) {
101     *filename = system_filename;
102     return true;
103   } else if (has_cache) {
104     *filename = cache_filename;
105     return true;
106   } else {
107     return false;
108   }
109 }
110 
Patch(const std::string & image_location,off_t delta,File * output_image,InstructionSet isa,TimingLogger * timings)111 bool PatchOat::Patch(const std::string& image_location, off_t delta,
112                      File* output_image, InstructionSet isa,
113                      TimingLogger* timings) {
114   CHECK(Runtime::Current() == nullptr);
115   CHECK(output_image != nullptr);
116   CHECK_GE(output_image->Fd(), 0);
117   CHECK(!image_location.empty()) << "image file must have a filename.";
118   CHECK_NE(isa, kNone);
119 
120   TimingLogger::ScopedTiming t("Runtime Setup", timings);
121   const char *isa_name = GetInstructionSetString(isa);
122   std::string image_filename;
123   if (!LocationToFilename(image_location, isa, &image_filename)) {
124     LOG(ERROR) << "Unable to find image at location " << image_location;
125     return false;
126   }
127   std::unique_ptr<File> input_image(OS::OpenFileForReading(image_filename.c_str()));
128   if (input_image.get() == nullptr) {
129     LOG(ERROR) << "unable to open input image file at " << image_filename
130                << " for location " << image_location;
131     return false;
132   }
133 
134   int64_t image_len = input_image->GetLength();
135   if (image_len < 0) {
136     LOG(ERROR) << "Error while getting image length";
137     return false;
138   }
139   ImageHeader image_header;
140   if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header),
141                                               sizeof(image_header), 0)) {
142     LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath();
143     return false;
144   }
145 
146   /*bool is_image_pic = */IsImagePic(image_header, input_image->GetPath());
147   // Nothing special to do right now since the image always needs to get patched.
148   // Perhaps in some far-off future we may have images with relative addresses that are true-PIC.
149 
150   // Set up the runtime
151   RuntimeOptions options;
152   NoopCompilerCallbacks callbacks;
153   options.push_back(std::make_pair("compilercallbacks", &callbacks));
154   std::string img = "-Ximage:" + image_location;
155   options.push_back(std::make_pair(img.c_str(), nullptr));
156   options.push_back(std::make_pair("imageinstructionset", reinterpret_cast<const void*>(isa_name)));
157   if (!Runtime::Create(options, false)) {
158     LOG(ERROR) << "Unable to initialize runtime";
159     return false;
160   }
161   // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
162   // give it away now and then switch to a more manageable ScopedObjectAccess.
163   Thread::Current()->TransitionFromRunnableToSuspended(kNative);
164   ScopedObjectAccess soa(Thread::Current());
165 
166   t.NewTiming("Image and oat Patching setup");
167   // Create the map where we will write the image patches to.
168   std::string error_msg;
169   std::unique_ptr<MemMap> image(MemMap::MapFile(image_len, PROT_READ | PROT_WRITE, MAP_PRIVATE,
170                                                 input_image->Fd(), 0,
171                                                 input_image->GetPath().c_str(),
172                                                 &error_msg));
173   if (image.get() == nullptr) {
174     LOG(ERROR) << "unable to map image file " << input_image->GetPath() << " : " << error_msg;
175     return false;
176   }
177   gc::space::ImageSpace* ispc = Runtime::Current()->GetHeap()->GetImageSpace();
178 
179   PatchOat p(isa, image.release(), ispc->GetLiveBitmap(), ispc->GetMemMap(),
180              delta, timings);
181   t.NewTiming("Patching files");
182   if (!p.PatchImage()) {
183     LOG(ERROR) << "Failed to patch image file " << input_image->GetPath();
184     return false;
185   }
186 
187   t.NewTiming("Writing files");
188   if (!p.WriteImage(output_image)) {
189     return false;
190   }
191   return true;
192 }
193 
Patch(File * input_oat,const std::string & image_location,off_t delta,File * output_oat,File * output_image,InstructionSet isa,TimingLogger * timings,bool output_oat_opened_from_fd,bool new_oat_out)194 bool PatchOat::Patch(File* input_oat, const std::string& image_location, off_t delta,
195                      File* output_oat, File* output_image, InstructionSet isa,
196                      TimingLogger* timings,
197                      bool output_oat_opened_from_fd,
198                      bool new_oat_out) {
199   CHECK(Runtime::Current() == nullptr);
200   CHECK(output_image != nullptr);
201   CHECK_GE(output_image->Fd(), 0);
202   CHECK(input_oat != nullptr);
203   CHECK(output_oat != nullptr);
204   CHECK_GE(input_oat->Fd(), 0);
205   CHECK_GE(output_oat->Fd(), 0);
206   CHECK(!image_location.empty()) << "image file must have a filename.";
207 
208   TimingLogger::ScopedTiming t("Runtime Setup", timings);
209 
210   if (isa == kNone) {
211     Elf32_Ehdr elf_hdr;
212     if (sizeof(elf_hdr) != input_oat->Read(reinterpret_cast<char*>(&elf_hdr), sizeof(elf_hdr), 0)) {
213       LOG(ERROR) << "unable to read elf header";
214       return false;
215     }
216     isa = ElfISAToInstructionSet(elf_hdr.e_machine);
217   }
218   const char* isa_name = GetInstructionSetString(isa);
219   std::string image_filename;
220   if (!LocationToFilename(image_location, isa, &image_filename)) {
221     LOG(ERROR) << "Unable to find image at location " << image_location;
222     return false;
223   }
224   std::unique_ptr<File> input_image(OS::OpenFileForReading(image_filename.c_str()));
225   if (input_image.get() == nullptr) {
226     LOG(ERROR) << "unable to open input image file at " << image_filename
227                << " for location " << image_location;
228     return false;
229   }
230   int64_t image_len = input_image->GetLength();
231   if (image_len < 0) {
232     LOG(ERROR) << "Error while getting image length";
233     return false;
234   }
235   ImageHeader image_header;
236   if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header),
237                                               sizeof(image_header), 0)) {
238     LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath();
239   }
240 
241   /*bool is_image_pic = */IsImagePic(image_header, input_image->GetPath());
242   // Nothing special to do right now since the image always needs to get patched.
243   // Perhaps in some far-off future we may have images with relative addresses that are true-PIC.
244 
245   // Set up the runtime
246   RuntimeOptions options;
247   NoopCompilerCallbacks callbacks;
248   options.push_back(std::make_pair("compilercallbacks", &callbacks));
249   std::string img = "-Ximage:" + image_location;
250   options.push_back(std::make_pair(img.c_str(), nullptr));
251   options.push_back(std::make_pair("imageinstructionset", reinterpret_cast<const void*>(isa_name)));
252   if (!Runtime::Create(options, false)) {
253     LOG(ERROR) << "Unable to initialize runtime";
254     return false;
255   }
256   // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
257   // give it away now and then switch to a more manageable ScopedObjectAccess.
258   Thread::Current()->TransitionFromRunnableToSuspended(kNative);
259   ScopedObjectAccess soa(Thread::Current());
260 
261   t.NewTiming("Image and oat Patching setup");
262   // Create the map where we will write the image patches to.
263   std::string error_msg;
264   std::unique_ptr<MemMap> image(MemMap::MapFile(image_len, PROT_READ | PROT_WRITE, MAP_PRIVATE,
265                                                 input_image->Fd(), 0,
266                                                 input_image->GetPath().c_str(),
267                                                 &error_msg));
268   if (image.get() == nullptr) {
269     LOG(ERROR) << "unable to map image file " << input_image->GetPath() << " : " << error_msg;
270     return false;
271   }
272   gc::space::ImageSpace* ispc = Runtime::Current()->GetHeap()->GetImageSpace();
273 
274   std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat,
275                                              PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg));
276   if (elf.get() == nullptr) {
277     LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg;
278     return false;
279   }
280 
281   bool skip_patching_oat = false;
282   MaybePic is_oat_pic = IsOatPic(elf.get());
283   if (is_oat_pic >= ERROR_FIRST) {
284     // Error logged by IsOatPic
285     return false;
286   } else if (is_oat_pic == PIC) {
287     // Do not need to do ELF-file patching. Create a symlink and skip the ELF patching.
288     if (!ReplaceOatFileWithSymlink(input_oat->GetPath(),
289                                    output_oat->GetPath(),
290                                    output_oat_opened_from_fd,
291                                    new_oat_out)) {
292       // Errors already logged by above call.
293       return false;
294     }
295     // Don't patch the OAT, since we just symlinked it. Image still needs patching.
296     skip_patching_oat = true;
297   } else {
298     CHECK(is_oat_pic == NOT_PIC);
299   }
300 
301   PatchOat p(isa, elf.release(), image.release(), ispc->GetLiveBitmap(), ispc->GetMemMap(),
302              delta, timings);
303   t.NewTiming("Patching files");
304   if (!skip_patching_oat && !p.PatchElf()) {
305     LOG(ERROR) << "Failed to patch oat file " << input_oat->GetPath();
306     return false;
307   }
308   if (!p.PatchImage()) {
309     LOG(ERROR) << "Failed to patch image file " << input_image->GetPath();
310     return false;
311   }
312 
313   t.NewTiming("Writing files");
314   if (!skip_patching_oat && !p.WriteElf(output_oat)) {
315     LOG(ERROR) << "Failed to write oat file " << input_oat->GetPath();
316     return false;
317   }
318   if (!p.WriteImage(output_image)) {
319     LOG(ERROR) << "Failed to write image file " << input_image->GetPath();
320     return false;
321   }
322   return true;
323 }
324 
WriteElf(File * out)325 bool PatchOat::WriteElf(File* out) {
326   TimingLogger::ScopedTiming t("Writing Elf File", timings_);
327 
328   CHECK(oat_file_.get() != nullptr);
329   CHECK(out != nullptr);
330   size_t expect = oat_file_->Size();
331   if (out->WriteFully(reinterpret_cast<char*>(oat_file_->Begin()), expect) &&
332       out->SetLength(expect) == 0) {
333     return true;
334   } else {
335     LOG(ERROR) << "Writing to oat file " << out->GetPath() << " failed.";
336     return false;
337   }
338 }
339 
WriteImage(File * out)340 bool PatchOat::WriteImage(File* out) {
341   TimingLogger::ScopedTiming t("Writing image File", timings_);
342   std::string error_msg;
343 
344   ScopedFlock img_flock;
345   img_flock.Init(out, &error_msg);
346 
347   CHECK(image_ != nullptr);
348   CHECK(out != nullptr);
349   size_t expect = image_->Size();
350   if (out->WriteFully(reinterpret_cast<char*>(image_->Begin()), expect) &&
351       out->SetLength(expect) == 0) {
352     return true;
353   } else {
354     LOG(ERROR) << "Writing to image file " << out->GetPath() << " failed.";
355     return false;
356   }
357 }
358 
IsImagePic(const ImageHeader & image_header,const std::string & image_path)359 bool PatchOat::IsImagePic(const ImageHeader& image_header, const std::string& image_path) {
360   if (!image_header.CompilePic()) {
361     if (kIsDebugBuild) {
362       LOG(INFO) << "image at location " << image_path << " was *not* compiled pic";
363     }
364     return false;
365   }
366 
367   if (kIsDebugBuild) {
368     LOG(INFO) << "image at location " << image_path << " was compiled PIC";
369   }
370 
371   return true;
372 }
373 
IsOatPic(const ElfFile * oat_in)374 PatchOat::MaybePic PatchOat::IsOatPic(const ElfFile* oat_in) {
375   if (oat_in == nullptr) {
376     LOG(ERROR) << "No ELF input oat fie available";
377     return ERROR_OAT_FILE;
378   }
379 
380   const std::string& file_path = oat_in->GetFile().GetPath();
381 
382   const OatHeader* oat_header = GetOatHeader(oat_in);
383   if (oat_header == nullptr) {
384     LOG(ERROR) << "Failed to find oat header in oat file " << file_path;
385     return ERROR_OAT_FILE;
386   }
387 
388   if (!oat_header->IsValid()) {
389     LOG(ERROR) << "Elf file " << file_path << " has an invalid oat header";
390     return ERROR_OAT_FILE;
391   }
392 
393   bool is_pic = oat_header->IsPic();
394   if (kIsDebugBuild) {
395     LOG(INFO) << "Oat file at " << file_path << " is " << (is_pic ? "PIC" : "not pic");
396   }
397 
398   return is_pic ? PIC : NOT_PIC;
399 }
400 
ReplaceOatFileWithSymlink(const std::string & input_oat_filename,const std::string & output_oat_filename,bool output_oat_opened_from_fd,bool new_oat_out)401 bool PatchOat::ReplaceOatFileWithSymlink(const std::string& input_oat_filename,
402                                          const std::string& output_oat_filename,
403                                          bool output_oat_opened_from_fd,
404                                          bool new_oat_out) {
405   // Need a file when we are PIC, since we symlink over it. Refusing to symlink into FD.
406   if (output_oat_opened_from_fd) {
407     // TODO: installd uses --output-oat-fd. Should we change class linking logic for PIC?
408     LOG(ERROR) << "No output oat filename specified, needs filename for when we are PIC";
409     return false;
410   }
411 
412   // Image was PIC. Create symlink where the oat is supposed to go.
413   if (!new_oat_out) {
414     LOG(ERROR) << "Oat file " << output_oat_filename << " already exists, refusing to overwrite";
415     return false;
416   }
417 
418   // Delete the original file, since we won't need it.
419   TEMP_FAILURE_RETRY(unlink(output_oat_filename.c_str()));
420 
421   // Create a symlink from the old oat to the new oat
422   if (symlink(input_oat_filename.c_str(), output_oat_filename.c_str()) < 0) {
423     int err = errno;
424     LOG(ERROR) << "Failed to create symlink at " << output_oat_filename
425                << " error(" << err << "): " << strerror(err);
426     return false;
427   }
428 
429   if (kIsDebugBuild) {
430     LOG(INFO) << "Created symlink " << output_oat_filename << " -> " << input_oat_filename;
431   }
432 
433   return true;
434 }
435 
PatchImage()436 bool PatchOat::PatchImage() {
437   ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
438   CHECK_GT(image_->Size(), sizeof(ImageHeader));
439   // These are the roots from the original file.
440   mirror::Object* img_roots = image_header->GetImageRoots();
441   image_header->RelocateImage(delta_);
442 
443   VisitObject(img_roots);
444   if (!image_header->IsValid()) {
445     LOG(ERROR) << "reloction renders image header invalid";
446     return false;
447   }
448 
449   {
450     TimingLogger::ScopedTiming t("Walk Bitmap", timings_);
451     // Walk the bitmap.
452     WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
453     bitmap_->Walk(PatchOat::BitmapCallback, this);
454   }
455   return true;
456 }
457 
InHeap(mirror::Object * o)458 bool PatchOat::InHeap(mirror::Object* o) {
459   uintptr_t begin = reinterpret_cast<uintptr_t>(heap_->Begin());
460   uintptr_t end = reinterpret_cast<uintptr_t>(heap_->End());
461   uintptr_t obj = reinterpret_cast<uintptr_t>(o);
462   return o == nullptr || (begin <= obj && obj < end);
463 }
464 
operator ()(mirror::Object * obj,MemberOffset off,bool is_static_unused) const465 void PatchOat::PatchVisitor::operator() (mirror::Object* obj, MemberOffset off,
466                                          bool is_static_unused) const {
467   mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off);
468   DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap.";
469   mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent);
470   copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object);
471 }
472 
operator ()(mirror::Class * cls,mirror::Reference * ref) const473 void PatchOat::PatchVisitor::operator() (mirror::Class* cls, mirror::Reference* ref) const {
474   MemberOffset off = mirror::Reference::ReferentOffset();
475   mirror::Object* referent = ref->GetReferent();
476   DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap.";
477   mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent);
478   copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object);
479 }
480 
RelocatedCopyOf(mirror::Object * obj)481 mirror::Object* PatchOat::RelocatedCopyOf(mirror::Object* obj) {
482   if (obj == nullptr) {
483     return nullptr;
484   }
485   DCHECK_GT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->Begin()));
486   DCHECK_LT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->End()));
487   uintptr_t heap_off =
488       reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(heap_->Begin());
489   DCHECK_LT(heap_off, image_->Size());
490   return reinterpret_cast<mirror::Object*>(image_->Begin() + heap_off);
491 }
492 
RelocatedAddressOf(mirror::Object * obj)493 mirror::Object* PatchOat::RelocatedAddressOf(mirror::Object* obj) {
494   if (obj == nullptr) {
495     return nullptr;
496   } else {
497     return reinterpret_cast<mirror::Object*>(reinterpret_cast<byte*>(obj) + delta_);
498   }
499 }
500 
GetOatHeader(const ElfFile * elf_file)501 const OatHeader* PatchOat::GetOatHeader(const ElfFile* elf_file) {
502   auto rodata_sec = elf_file->FindSectionByName(".rodata");
503   if (rodata_sec == nullptr) {
504     return nullptr;
505   }
506 
507   OatHeader* oat_header = reinterpret_cast<OatHeader*>(elf_file->Begin() + rodata_sec->sh_offset);
508   return oat_header;
509 }
510 
511 // Called by BitmapCallback
VisitObject(mirror::Object * object)512 void PatchOat::VisitObject(mirror::Object* object) {
513   mirror::Object* copy = RelocatedCopyOf(object);
514   CHECK(copy != nullptr);
515   if (kUseBakerOrBrooksReadBarrier) {
516     object->AssertReadBarrierPointer();
517     if (kUseBrooksReadBarrier) {
518       mirror::Object* moved_to = RelocatedAddressOf(object);
519       copy->SetReadBarrierPointer(moved_to);
520       DCHECK_EQ(copy->GetReadBarrierPointer(), moved_to);
521     }
522   }
523   PatchOat::PatchVisitor visitor(this, copy);
524   object->VisitReferences<true, kVerifyNone>(visitor, visitor);
525   if (object->IsArtMethod<kVerifyNone>()) {
526     FixupMethod(down_cast<mirror::ArtMethod*>(object), down_cast<mirror::ArtMethod*>(copy));
527   }
528 }
529 
FixupMethod(mirror::ArtMethod * object,mirror::ArtMethod * copy)530 void PatchOat::FixupMethod(mirror::ArtMethod* object, mirror::ArtMethod* copy) {
531   const size_t pointer_size = InstructionSetPointerSize(isa_);
532   // Just update the entry points if it looks like we should.
533   // TODO: sanity check all the pointers' values
534 #if defined(ART_USE_PORTABLE_COMPILER)
535   uintptr_t portable = reinterpret_cast<uintptr_t>(
536       object->GetEntryPointFromPortableCompiledCodePtrSize<kVerifyNone>(pointer_size));
537   if (portable != 0) {
538     copy->SetEntryPointFromPortableCompiledCodePtrSize(reinterpret_cast<void*>(portable + delta_),
539                                                        pointer_size);
540   }
541 #endif
542   uintptr_t quick= reinterpret_cast<uintptr_t>(
543       object->GetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(pointer_size));
544   if (quick != 0) {
545     copy->SetEntryPointFromQuickCompiledCodePtrSize(reinterpret_cast<void*>(quick + delta_),
546                                                     pointer_size);
547   }
548   uintptr_t interpreter = reinterpret_cast<uintptr_t>(
549       object->GetEntryPointFromInterpreterPtrSize<kVerifyNone>(pointer_size));
550   if (interpreter != 0) {
551     copy->SetEntryPointFromInterpreterPtrSize(
552         reinterpret_cast<mirror::EntryPointFromInterpreter*>(interpreter + delta_), pointer_size);
553   }
554 
555   uintptr_t native_method = reinterpret_cast<uintptr_t>(
556       object->GetEntryPointFromJniPtrSize(pointer_size));
557   if (native_method != 0) {
558     copy->SetEntryPointFromJniPtrSize(reinterpret_cast<void*>(native_method + delta_),
559                                       pointer_size);
560   }
561 }
562 
Patch(File * input_oat,off_t delta,File * output_oat,TimingLogger * timings,bool output_oat_opened_from_fd,bool new_oat_out)563 bool PatchOat::Patch(File* input_oat, off_t delta, File* output_oat, TimingLogger* timings,
564                      bool output_oat_opened_from_fd, bool new_oat_out) {
565   CHECK(input_oat != nullptr);
566   CHECK(output_oat != nullptr);
567   CHECK_GE(input_oat->Fd(), 0);
568   CHECK_GE(output_oat->Fd(), 0);
569   TimingLogger::ScopedTiming t("Setup Oat File Patching", timings);
570 
571   std::string error_msg;
572   std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat,
573                                              PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg));
574   if (elf.get() == nullptr) {
575     LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg;
576     return false;
577   }
578 
579   MaybePic is_oat_pic = IsOatPic(elf.get());
580   if (is_oat_pic >= ERROR_FIRST) {
581     // Error logged by IsOatPic
582     return false;
583   } else if (is_oat_pic == PIC) {
584     // Do not need to do ELF-file patching. Create a symlink and skip the rest.
585     // Any errors will be logged by the function call.
586     return ReplaceOatFileWithSymlink(input_oat->GetPath(),
587                                      output_oat->GetPath(),
588                                      output_oat_opened_from_fd,
589                                      new_oat_out);
590   } else {
591     CHECK(is_oat_pic == NOT_PIC);
592   }
593 
594   PatchOat p(elf.release(), delta, timings);
595   t.NewTiming("Patch Oat file");
596   if (!p.PatchElf()) {
597     return false;
598   }
599 
600   t.NewTiming("Writing oat file");
601   if (!p.WriteElf(output_oat)) {
602     return false;
603   }
604   return true;
605 }
606 
CheckOatFile()607 bool PatchOat::CheckOatFile() {
608   Elf32_Shdr* patches_sec = oat_file_->FindSectionByName(".oat_patches");
609   if (patches_sec == nullptr) {
610     return false;
611   }
612   if (patches_sec->sh_type != SHT_OAT_PATCH) {
613     return false;
614   }
615   uintptr_t* patches = reinterpret_cast<uintptr_t*>(oat_file_->Begin() + patches_sec->sh_offset);
616   uintptr_t* patches_end = patches + (patches_sec->sh_size/sizeof(uintptr_t));
617   Elf32_Shdr* oat_data_sec = oat_file_->FindSectionByName(".rodata");
618   Elf32_Shdr* oat_text_sec = oat_file_->FindSectionByName(".text");
619   if (oat_data_sec == nullptr) {
620     return false;
621   }
622   if (oat_text_sec == nullptr) {
623     return false;
624   }
625   if (oat_text_sec->sh_offset <= oat_data_sec->sh_offset) {
626     return false;
627   }
628 
629   for (; patches < patches_end; patches++) {
630     if (oat_text_sec->sh_size <= *patches) {
631       return false;
632     }
633   }
634 
635   return true;
636 }
637 
PatchOatHeader()638 bool PatchOat::PatchOatHeader() {
639   Elf32_Shdr *rodata_sec = oat_file_->FindSectionByName(".rodata");
640   if (rodata_sec == nullptr) {
641     return false;
642   }
643   OatHeader* oat_header = reinterpret_cast<OatHeader*>(oat_file_->Begin() + rodata_sec->sh_offset);
644   if (!oat_header->IsValid()) {
645     LOG(ERROR) << "Elf file " << oat_file_->GetFile().GetPath() << " has an invalid oat header";
646     return false;
647   }
648   oat_header->RelocateOat(delta_);
649   return true;
650 }
651 
PatchElf()652 bool PatchOat::PatchElf() {
653   TimingLogger::ScopedTiming t("Fixup Elf Text Section", timings_);
654   if (!PatchTextSection()) {
655     return false;
656   }
657 
658   if (!PatchOatHeader()) {
659     return false;
660   }
661 
662   bool need_fixup = false;
663   t.NewTiming("Fixup Elf Headers");
664   // Fixup Phdr's
665   for (unsigned int i = 0; i < oat_file_->GetProgramHeaderNum(); i++) {
666     Elf32_Phdr* hdr = oat_file_->GetProgramHeader(i);
667     CHECK(hdr != nullptr);
668     if (hdr->p_vaddr != 0 && hdr->p_vaddr != hdr->p_offset) {
669       need_fixup = true;
670       hdr->p_vaddr += delta_;
671     }
672     if (hdr->p_paddr != 0 && hdr->p_paddr != hdr->p_offset) {
673       need_fixup = true;
674       hdr->p_paddr += delta_;
675     }
676   }
677   if (!need_fixup) {
678     // This was never passed through ElfFixup so all headers/symbols just have their offset as
679     // their addr. Therefore we do not need to update these parts.
680     return true;
681   }
682   t.NewTiming("Fixup Section Headers");
683   for (unsigned int i = 0; i < oat_file_->GetSectionHeaderNum(); i++) {
684     Elf32_Shdr* hdr = oat_file_->GetSectionHeader(i);
685     CHECK(hdr != nullptr);
686     if (hdr->sh_addr != 0) {
687       hdr->sh_addr += delta_;
688     }
689   }
690 
691   t.NewTiming("Fixup Dynamics");
692   for (Elf32_Word i = 0; i < oat_file_->GetDynamicNum(); i++) {
693     Elf32_Dyn& dyn = oat_file_->GetDynamic(i);
694     if (IsDynamicSectionPointer(dyn.d_tag, oat_file_->GetHeader().e_machine)) {
695       dyn.d_un.d_ptr += delta_;
696     }
697   }
698 
699   t.NewTiming("Fixup Elf Symbols");
700   // Fixup dynsym
701   Elf32_Shdr* dynsym_sec = oat_file_->FindSectionByName(".dynsym");
702   CHECK(dynsym_sec != nullptr);
703   if (!PatchSymbols(dynsym_sec)) {
704     return false;
705   }
706 
707   // Fixup symtab
708   Elf32_Shdr* symtab_sec = oat_file_->FindSectionByName(".symtab");
709   if (symtab_sec != nullptr) {
710     if (!PatchSymbols(symtab_sec)) {
711       return false;
712     }
713   }
714 
715   return true;
716 }
717 
PatchSymbols(Elf32_Shdr * section)718 bool PatchOat::PatchSymbols(Elf32_Shdr* section) {
719   Elf32_Sym* syms = reinterpret_cast<Elf32_Sym*>(oat_file_->Begin() + section->sh_offset);
720   const Elf32_Sym* last_sym =
721       reinterpret_cast<Elf32_Sym*>(oat_file_->Begin() + section->sh_offset + section->sh_size);
722   CHECK_EQ(section->sh_size % sizeof(Elf32_Sym), 0u)
723       << "Symtab section size is not multiple of symbol size";
724   for (; syms < last_sym; syms++) {
725     uint8_t sttype = ELF32_ST_TYPE(syms->st_info);
726     Elf32_Word shndx = syms->st_shndx;
727     if (shndx != SHN_ABS && shndx != SHN_COMMON && shndx != SHN_UNDEF &&
728         (sttype == STT_FUNC || sttype == STT_OBJECT)) {
729       CHECK_NE(syms->st_value, 0u);
730       syms->st_value += delta_;
731     }
732   }
733   return true;
734 }
735 
PatchTextSection()736 bool PatchOat::PatchTextSection() {
737   Elf32_Shdr* patches_sec = oat_file_->FindSectionByName(".oat_patches");
738   if (patches_sec == nullptr) {
739     LOG(ERROR) << ".oat_patches section not found. Aborting patch";
740     return false;
741   }
742   DCHECK(CheckOatFile()) << "Oat file invalid";
743   CHECK_EQ(patches_sec->sh_type, SHT_OAT_PATCH) << "Unexpected type of .oat_patches";
744   uintptr_t* patches = reinterpret_cast<uintptr_t*>(oat_file_->Begin() + patches_sec->sh_offset);
745   uintptr_t* patches_end = patches + (patches_sec->sh_size/sizeof(uintptr_t));
746   Elf32_Shdr* oat_text_sec = oat_file_->FindSectionByName(".text");
747   CHECK(oat_text_sec != nullptr);
748   byte* to_patch = oat_file_->Begin() + oat_text_sec->sh_offset;
749   uintptr_t to_patch_end = reinterpret_cast<uintptr_t>(to_patch) + oat_text_sec->sh_size;
750 
751   for (; patches < patches_end; patches++) {
752     CHECK_LT(*patches, oat_text_sec->sh_size) << "Bad Patch";
753     uint32_t* patch_loc = reinterpret_cast<uint32_t*>(to_patch + *patches);
754     CHECK_LT(reinterpret_cast<uintptr_t>(patch_loc), to_patch_end);
755     *patch_loc += delta_;
756   }
757 
758   return true;
759 }
760 
761 static int orig_argc;
762 static char** orig_argv;
763 
CommandLine()764 static std::string CommandLine() {
765   std::vector<std::string> command;
766   for (int i = 0; i < orig_argc; ++i) {
767     command.push_back(orig_argv[i]);
768   }
769   return Join(command, ' ');
770 }
771 
UsageErrorV(const char * fmt,va_list ap)772 static void UsageErrorV(const char* fmt, va_list ap) {
773   std::string error;
774   StringAppendV(&error, fmt, ap);
775   LOG(ERROR) << error;
776 }
777 
UsageError(const char * fmt,...)778 static void UsageError(const char* fmt, ...) {
779   va_list ap;
780   va_start(ap, fmt);
781   UsageErrorV(fmt, ap);
782   va_end(ap);
783 }
784 
Usage(const char * fmt,...)785 static void Usage(const char *fmt, ...) {
786   va_list ap;
787   va_start(ap, fmt);
788   UsageErrorV(fmt, ap);
789   va_end(ap);
790 
791   UsageError("Command: %s", CommandLine().c_str());
792   UsageError("Usage: patchoat [options]...");
793   UsageError("");
794   UsageError("  --instruction-set=<isa>: Specifies the instruction set the patched code is");
795   UsageError("      compiled for. Required if you use --input-oat-location");
796   UsageError("");
797   UsageError("  --input-oat-file=<file.oat>: Specifies the exact filename of the oat file to be");
798   UsageError("      patched.");
799   UsageError("");
800   UsageError("  --input-oat-fd=<file-descriptor>: Specifies the file-descriptor of the oat file");
801   UsageError("      to be patched.");
802   UsageError("");
803   UsageError("  --input-oat-location=<file.oat>: Specifies the 'location' to read the patched");
804   UsageError("      oat file from. If used one must also supply the --instruction-set");
805   UsageError("");
806   UsageError("  --input-image-location=<file.art>: Specifies the 'location' of the image file to");
807   UsageError("      be patched. If --instruction-set is not given it will use the instruction set");
808   UsageError("      extracted from the --input-oat-file.");
809   UsageError("");
810   UsageError("  --output-oat-file=<file.oat>: Specifies the exact file to write the patched oat");
811   UsageError("      file to.");
812   UsageError("");
813   UsageError("  --output-oat-fd=<file-descriptor>: Specifies the file-descriptor to write the");
814   UsageError("      the patched oat file to.");
815   UsageError("");
816   UsageError("  --output-image-file=<file.art>: Specifies the exact file to write the patched");
817   UsageError("      image file to.");
818   UsageError("");
819   UsageError("  --output-image-fd=<file-descriptor>: Specifies the file-descriptor to write the");
820   UsageError("      the patched image file to.");
821   UsageError("");
822   UsageError("  --orig-base-offset=<original-base-offset>: Specify the base offset the input file");
823   UsageError("      was compiled with. This is needed if one is specifying a --base-offset");
824   UsageError("");
825   UsageError("  --base-offset=<new-base-offset>: Specify the base offset we will repatch the");
826   UsageError("      given files to use. This requires that --orig-base-offset is also given.");
827   UsageError("");
828   UsageError("  --base-offset-delta=<delta>: Specify the amount to change the old base-offset by.");
829   UsageError("      This value may be negative.");
830   UsageError("");
831   UsageError("  --patched-image-file=<file.art>: Use the same patch delta as was used to patch");
832   UsageError("      the given image file.");
833   UsageError("");
834   UsageError("  --patched-image-location=<file.art>: Use the same patch delta as was used to");
835   UsageError("      patch the given image location. If used one must also specify the");
836   UsageError("      --instruction-set flag. It will search for this image in the same way that");
837   UsageError("      is done when loading one.");
838   UsageError("");
839   UsageError("  --lock-output: Obtain a flock on output oat file before starting.");
840   UsageError("");
841   UsageError("  --no-lock-output: Do not attempt to obtain a flock on output oat file.");
842   UsageError("");
843   UsageError("  --dump-timings: dump out patch timing information");
844   UsageError("");
845   UsageError("  --no-dump-timings: do not dump out patch timing information");
846   UsageError("");
847 
848   exit(EXIT_FAILURE);
849 }
850 
ReadBaseDelta(const char * name,off_t * delta,std::string * error_msg)851 static bool ReadBaseDelta(const char* name, off_t* delta, std::string* error_msg) {
852   CHECK(name != nullptr);
853   CHECK(delta != nullptr);
854   std::unique_ptr<File> file;
855   if (OS::FileExists(name)) {
856     file.reset(OS::OpenFileForReading(name));
857     if (file.get() == nullptr) {
858       *error_msg = "Failed to open file %s for reading";
859       return false;
860     }
861   } else {
862     *error_msg = "File %s does not exist";
863     return false;
864   }
865   CHECK(file.get() != nullptr);
866   ImageHeader hdr;
867   if (sizeof(hdr) != file->Read(reinterpret_cast<char*>(&hdr), sizeof(hdr), 0)) {
868     *error_msg = "Failed to read file %s";
869     return false;
870   }
871   if (!hdr.IsValid()) {
872     *error_msg = "%s does not contain a valid image header.";
873     return false;
874   }
875   *delta = hdr.GetPatchDelta();
876   return true;
877 }
878 
CreateOrOpen(const char * name,bool * created)879 static File* CreateOrOpen(const char* name, bool* created) {
880   if (OS::FileExists(name)) {
881     *created = false;
882     return OS::OpenFileReadWrite(name);
883   } else {
884     *created = true;
885     std::unique_ptr<File> f(OS::CreateEmptyFile(name));
886     if (f.get() != nullptr) {
887       if (fchmod(f->Fd(), 0644) != 0) {
888         PLOG(ERROR) << "Unable to make " << name << " world readable";
889         unlink(name);
890         return nullptr;
891       }
892     }
893     return f.release();
894   }
895 }
896 
897 // Either try to close the file (close=true), or erase it.
FinishFile(File * file,bool close)898 static bool FinishFile(File* file, bool close) {
899   if (close) {
900     if (file->FlushCloseOrErase() != 0) {
901       PLOG(ERROR) << "Failed to flush and close file.";
902       return false;
903     }
904     return true;
905   } else {
906     file->Erase();
907     return false;
908   }
909 }
910 
patchoat(int argc,char ** argv)911 static int patchoat(int argc, char **argv) {
912   InitLogging(argv);
913   MemMap::Init();
914   const bool debug = kIsDebugBuild;
915   orig_argc = argc;
916   orig_argv = argv;
917   TimingLogger timings("patcher", false, false);
918 
919   InitLogging(argv);
920 
921   // Skip over the command name.
922   argv++;
923   argc--;
924 
925   if (argc == 0) {
926     Usage("No arguments specified");
927   }
928 
929   timings.StartTiming("Patchoat");
930 
931   // cmd line args
932   bool isa_set = false;
933   InstructionSet isa = kNone;
934   std::string input_oat_filename;
935   std::string input_oat_location;
936   int input_oat_fd = -1;
937   bool have_input_oat = false;
938   std::string input_image_location;
939   std::string output_oat_filename;
940   int output_oat_fd = -1;
941   bool have_output_oat = false;
942   std::string output_image_filename;
943   int output_image_fd = -1;
944   bool have_output_image = false;
945   uintptr_t base_offset = 0;
946   bool base_offset_set = false;
947   uintptr_t orig_base_offset = 0;
948   bool orig_base_offset_set = false;
949   off_t base_delta = 0;
950   bool base_delta_set = false;
951   std::string patched_image_filename;
952   std::string patched_image_location;
953   bool dump_timings = kIsDebugBuild;
954   bool lock_output = true;
955 
956   for (int i = 0; i < argc; i++) {
957     const StringPiece option(argv[i]);
958     const bool log_options = false;
959     if (log_options) {
960       LOG(INFO) << "patchoat: option[" << i << "]=" << argv[i];
961     }
962     if (option.starts_with("--instruction-set=")) {
963       isa_set = true;
964       const char* isa_str = option.substr(strlen("--instruction-set=")).data();
965       isa = GetInstructionSetFromString(isa_str);
966       if (isa == kNone) {
967         Usage("Unknown or invalid instruction set %s", isa_str);
968       }
969     } else if (option.starts_with("--input-oat-location=")) {
970       if (have_input_oat) {
971         Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used.");
972       }
973       have_input_oat = true;
974       input_oat_location = option.substr(strlen("--input-oat-location=")).data();
975     } else if (option.starts_with("--input-oat-file=")) {
976       if (have_input_oat) {
977         Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used.");
978       }
979       have_input_oat = true;
980       input_oat_filename = option.substr(strlen("--input-oat-file=")).data();
981     } else if (option.starts_with("--input-oat-fd=")) {
982       if (have_input_oat) {
983         Usage("Only one of --input-oat-file, --input-oat-location and --input-oat-fd may be used.");
984       }
985       have_input_oat = true;
986       const char* oat_fd_str = option.substr(strlen("--input-oat-fd=")).data();
987       if (!ParseInt(oat_fd_str, &input_oat_fd)) {
988         Usage("Failed to parse --input-oat-fd argument '%s' as an integer", oat_fd_str);
989       }
990       if (input_oat_fd < 0) {
991         Usage("--input-oat-fd pass a negative value %d", input_oat_fd);
992       }
993     } else if (option.starts_with("--input-image-location=")) {
994       input_image_location = option.substr(strlen("--input-image-location=")).data();
995     } else if (option.starts_with("--output-oat-file=")) {
996       if (have_output_oat) {
997         Usage("Only one of --output-oat-file, and --output-oat-fd may be used.");
998       }
999       have_output_oat = true;
1000       output_oat_filename = option.substr(strlen("--output-oat-file=")).data();
1001     } else if (option.starts_with("--output-oat-fd=")) {
1002       if (have_output_oat) {
1003         Usage("Only one of --output-oat-file, --output-oat-fd may be used.");
1004       }
1005       have_output_oat = true;
1006       const char* oat_fd_str = option.substr(strlen("--output-oat-fd=")).data();
1007       if (!ParseInt(oat_fd_str, &output_oat_fd)) {
1008         Usage("Failed to parse --output-oat-fd argument '%s' as an integer", oat_fd_str);
1009       }
1010       if (output_oat_fd < 0) {
1011         Usage("--output-oat-fd pass a negative value %d", output_oat_fd);
1012       }
1013     } else if (option.starts_with("--output-image-file=")) {
1014       if (have_output_image) {
1015         Usage("Only one of --output-image-file, and --output-image-fd may be used.");
1016       }
1017       have_output_image = true;
1018       output_image_filename = option.substr(strlen("--output-image-file=")).data();
1019     } else if (option.starts_with("--output-image-fd=")) {
1020       if (have_output_image) {
1021         Usage("Only one of --output-image-file, and --output-image-fd may be used.");
1022       }
1023       have_output_image = true;
1024       const char* image_fd_str = option.substr(strlen("--output-image-fd=")).data();
1025       if (!ParseInt(image_fd_str, &output_image_fd)) {
1026         Usage("Failed to parse --output-image-fd argument '%s' as an integer", image_fd_str);
1027       }
1028       if (output_image_fd < 0) {
1029         Usage("--output-image-fd pass a negative value %d", output_image_fd);
1030       }
1031     } else if (option.starts_with("--orig-base-offset=")) {
1032       const char* orig_base_offset_str = option.substr(strlen("--orig-base-offset=")).data();
1033       orig_base_offset_set = true;
1034       if (!ParseUint(orig_base_offset_str, &orig_base_offset)) {
1035         Usage("Failed to parse --orig-base-offset argument '%s' as an uintptr_t",
1036               orig_base_offset_str);
1037       }
1038     } else if (option.starts_with("--base-offset=")) {
1039       const char* base_offset_str = option.substr(strlen("--base-offset=")).data();
1040       base_offset_set = true;
1041       if (!ParseUint(base_offset_str, &base_offset)) {
1042         Usage("Failed to parse --base-offset argument '%s' as an uintptr_t", base_offset_str);
1043       }
1044     } else if (option.starts_with("--base-offset-delta=")) {
1045       const char* base_delta_str = option.substr(strlen("--base-offset-delta=")).data();
1046       base_delta_set = true;
1047       if (!ParseInt(base_delta_str, &base_delta)) {
1048         Usage("Failed to parse --base-offset-delta argument '%s' as an off_t", base_delta_str);
1049       }
1050     } else if (option.starts_with("--patched-image-location=")) {
1051       patched_image_location = option.substr(strlen("--patched-image-location=")).data();
1052     } else if (option.starts_with("--patched-image-file=")) {
1053       patched_image_filename = option.substr(strlen("--patched-image-file=")).data();
1054     } else if (option == "--lock-output") {
1055       lock_output = true;
1056     } else if (option == "--no-lock-output") {
1057       lock_output = false;
1058     } else if (option == "--dump-timings") {
1059       dump_timings = true;
1060     } else if (option == "--no-dump-timings") {
1061       dump_timings = false;
1062     } else {
1063       Usage("Unknown argument %s", option.data());
1064     }
1065   }
1066 
1067   {
1068     // Only 1 of these may be set.
1069     uint32_t cnt = 0;
1070     cnt += (base_delta_set) ? 1 : 0;
1071     cnt += (base_offset_set && orig_base_offset_set) ? 1 : 0;
1072     cnt += (!patched_image_filename.empty()) ? 1 : 0;
1073     cnt += (!patched_image_location.empty()) ? 1 : 0;
1074     if (cnt > 1) {
1075       Usage("Only one of --base-offset/--orig-base-offset, --base-offset-delta, "
1076             "--patched-image-filename or --patched-image-location may be used.");
1077     } else if (cnt == 0) {
1078       Usage("Must specify --base-offset-delta, --base-offset and --orig-base-offset, "
1079             "--patched-image-location or --patched-image-file");
1080     }
1081   }
1082 
1083   if (have_input_oat != have_output_oat) {
1084     Usage("Either both input and output oat must be supplied or niether must be.");
1085   }
1086 
1087   if ((!input_image_location.empty()) != have_output_image) {
1088     Usage("Either both input and output image must be supplied or niether must be.");
1089   }
1090 
1091   // We know we have both the input and output so rename for clarity.
1092   bool have_image_files = have_output_image;
1093   bool have_oat_files = have_output_oat;
1094 
1095   if (!have_oat_files && !have_image_files) {
1096     Usage("Must be patching either an oat or an image file or both.");
1097   }
1098 
1099   if (!have_oat_files && !isa_set) {
1100     Usage("Must include ISA if patching an image file without an oat file.");
1101   }
1102 
1103   if (!input_oat_location.empty()) {
1104     if (!isa_set) {
1105       Usage("specifying a location requires specifying an instruction set");
1106     }
1107     if (!LocationToFilename(input_oat_location, isa, &input_oat_filename)) {
1108       Usage("Unable to find filename for input oat location %s", input_oat_location.c_str());
1109     }
1110     if (debug) {
1111       LOG(INFO) << "Using input-oat-file " << input_oat_filename;
1112     }
1113   }
1114   if (!patched_image_location.empty()) {
1115     if (!isa_set) {
1116       Usage("specifying a location requires specifying an instruction set");
1117     }
1118     std::string system_filename;
1119     bool has_system = false;
1120     std::string cache_filename;
1121     bool has_cache = false;
1122     bool has_android_data_unused = false;
1123     bool is_global_cache = false;
1124     if (!gc::space::ImageSpace::FindImageFilename(patched_image_location.c_str(), isa,
1125                                                   &system_filename, &has_system, &cache_filename,
1126                                                   &has_android_data_unused, &has_cache,
1127                                                   &is_global_cache)) {
1128       Usage("Unable to determine image file for location %s", patched_image_location.c_str());
1129     }
1130     if (has_cache) {
1131       patched_image_filename = cache_filename;
1132     } else if (has_system) {
1133       LOG(WARNING) << "Only image file found was in /system for image location "
1134                    << patched_image_location;
1135       patched_image_filename = system_filename;
1136     } else {
1137       Usage("Unable to determine image file for location %s", patched_image_location.c_str());
1138     }
1139     if (debug) {
1140       LOG(INFO) << "Using patched-image-file " << patched_image_filename;
1141     }
1142   }
1143 
1144   if (!base_delta_set) {
1145     if (orig_base_offset_set && base_offset_set) {
1146       base_delta_set = true;
1147       base_delta = base_offset - orig_base_offset;
1148     } else if (!patched_image_filename.empty()) {
1149       base_delta_set = true;
1150       std::string error_msg;
1151       if (!ReadBaseDelta(patched_image_filename.c_str(), &base_delta, &error_msg)) {
1152         Usage(error_msg.c_str(), patched_image_filename.c_str());
1153       }
1154     } else {
1155       if (base_offset_set) {
1156         Usage("Unable to determine original base offset.");
1157       } else {
1158         Usage("Must supply a desired new offset or delta.");
1159       }
1160     }
1161   }
1162 
1163   if (!IsAligned<kPageSize>(base_delta)) {
1164     Usage("Base offset/delta must be alligned to a pagesize (0x%08x) boundary.", kPageSize);
1165   }
1166 
1167   // Do we need to cleanup output files if we fail?
1168   bool new_image_out = false;
1169   bool new_oat_out = false;
1170 
1171   std::unique_ptr<File> input_oat;
1172   std::unique_ptr<File> output_oat;
1173   std::unique_ptr<File> output_image;
1174 
1175   if (have_image_files) {
1176     CHECK(!input_image_location.empty());
1177 
1178     if (output_image_fd != -1) {
1179       if (output_image_filename.empty()) {
1180         output_image_filename = "output-image-file";
1181       }
1182       output_image.reset(new File(output_image_fd, output_image_filename, true));
1183     } else {
1184       CHECK(!output_image_filename.empty());
1185       output_image.reset(CreateOrOpen(output_image_filename.c_str(), &new_image_out));
1186     }
1187   } else {
1188     CHECK(output_image_filename.empty() && output_image_fd == -1 && input_image_location.empty());
1189   }
1190 
1191   if (have_oat_files) {
1192     if (input_oat_fd != -1) {
1193       if (input_oat_filename.empty()) {
1194         input_oat_filename = "input-oat-file";
1195       }
1196       input_oat.reset(new File(input_oat_fd, input_oat_filename, false));
1197       if (input_oat == nullptr) {
1198         // Unlikely, but ensure exhaustive logging in non-0 exit code case
1199         LOG(ERROR) << "Failed to open input oat file by its FD" << input_oat_fd;
1200       }
1201     } else {
1202       CHECK(!input_oat_filename.empty());
1203       input_oat.reset(OS::OpenFileForReading(input_oat_filename.c_str()));
1204       if (input_oat == nullptr) {
1205         int err = errno;
1206         LOG(ERROR) << "Failed to open input oat file " << input_oat_filename
1207                    << ": " << strerror(err) << "(" << err << ")";
1208       }
1209     }
1210 
1211     if (output_oat_fd != -1) {
1212       if (output_oat_filename.empty()) {
1213         output_oat_filename = "output-oat-file";
1214       }
1215       output_oat.reset(new File(output_oat_fd, output_oat_filename, true));
1216       if (output_oat == nullptr) {
1217         // Unlikely, but ensure exhaustive logging in non-0 exit code case
1218         LOG(ERROR) << "Failed to open output oat file by its FD" << output_oat_fd;
1219       }
1220     } else {
1221       CHECK(!output_oat_filename.empty());
1222       output_oat.reset(CreateOrOpen(output_oat_filename.c_str(), &new_oat_out));
1223       if (output_oat == nullptr) {
1224         int err = errno;
1225         LOG(ERROR) << "Failed to open output oat file " << output_oat_filename
1226                    << ": " << strerror(err) << "(" << err << ")";
1227       }
1228     }
1229   }
1230 
1231   // TODO: get rid of this.
1232   auto cleanup = [&output_image_filename, &output_oat_filename,
1233                   &new_oat_out, &new_image_out, &timings, &dump_timings](bool success) {
1234     timings.EndTiming();
1235     if (!success) {
1236       if (new_oat_out) {
1237         CHECK(!output_oat_filename.empty());
1238         unlink(output_oat_filename.c_str());
1239       }
1240       if (new_image_out) {
1241         CHECK(!output_image_filename.empty());
1242         unlink(output_image_filename.c_str());
1243       }
1244     }
1245     if (dump_timings) {
1246       LOG(INFO) << Dumpable<TimingLogger>(timings);
1247     }
1248 
1249     if (kIsDebugBuild) {
1250       LOG(INFO) << "Cleaning up.. success? " << success;
1251     }
1252   };
1253 
1254   if (have_oat_files && (input_oat.get() == nullptr || output_oat.get() == nullptr)) {
1255     LOG(ERROR) << "Failed to open input/output oat files";
1256     cleanup(false);
1257     return EXIT_FAILURE;
1258   } else if (have_image_files && output_image.get() == nullptr) {
1259     LOG(ERROR) << "Failed to open output image file";
1260     cleanup(false);
1261     return EXIT_FAILURE;
1262   }
1263 
1264   if (debug) {
1265     LOG(INFO) << "moving offset by " << base_delta
1266               << " (0x" << std::hex << base_delta << ") bytes or "
1267               << std::dec << (base_delta/kPageSize) << " pages.";
1268   }
1269 
1270   // TODO: is it going to be promatic to unlink a file that was flock-ed?
1271   ScopedFlock output_oat_lock;
1272   if (lock_output) {
1273     std::string error_msg;
1274     if (have_oat_files && !output_oat_lock.Init(output_oat.get(), &error_msg)) {
1275       LOG(ERROR) << "Unable to lock output oat " << output_image->GetPath() << ": " << error_msg;
1276       cleanup(false);
1277       return EXIT_FAILURE;
1278     }
1279   }
1280 
1281   bool ret;
1282   if (have_image_files && have_oat_files) {
1283     TimingLogger::ScopedTiming pt("patch image and oat", &timings);
1284     ret = PatchOat::Patch(input_oat.get(), input_image_location, base_delta,
1285                           output_oat.get(), output_image.get(), isa, &timings,
1286                           output_oat_fd >= 0,  // was it opened from FD?
1287                           new_oat_out);
1288     // The order here doesn't matter. If the first one is successfully saved and the second one
1289     // erased, ImageSpace will still detect a problem and not use the files.
1290     ret = ret && FinishFile(output_image.get(), ret);
1291     ret = ret && FinishFile(output_oat.get(), ret);
1292   } else if (have_oat_files) {
1293     TimingLogger::ScopedTiming pt("patch oat", &timings);
1294     ret = PatchOat::Patch(input_oat.get(), base_delta, output_oat.get(), &timings,
1295                           output_oat_fd >= 0,  // was it opened from FD?
1296                           new_oat_out);
1297     ret = ret && FinishFile(output_oat.get(), ret);
1298   } else if (have_image_files) {
1299     TimingLogger::ScopedTiming pt("patch image", &timings);
1300     ret = PatchOat::Patch(input_image_location, base_delta, output_image.get(), isa, &timings);
1301     ret = ret && FinishFile(output_image.get(), ret);
1302   } else {
1303     CHECK(false);
1304     ret = true;
1305   }
1306 
1307   if (kIsDebugBuild) {
1308     LOG(INFO) << "Exiting with return ... " << ret;
1309   }
1310   cleanup(ret);
1311   return (ret) ? EXIT_SUCCESS : EXIT_FAILURE;
1312 }
1313 
1314 }  // namespace art
1315 
main(int argc,char ** argv)1316 int main(int argc, char **argv) {
1317   return art::patchoat(argc, argv);
1318 }
1319