• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "android-base/stringprintf.h"
28 #include "android-base/strings.h"
29 
30 #include "art_field-inl.h"
31 #include "art_method-inl.h"
32 #include "base/dumpable.h"
33 #include "base/memory_tool.h"
34 #include "base/scoped_flock.h"
35 #include "base/stringpiece.h"
36 #include "base/unix_file/fd_file.h"
37 #include "base/unix_file/random_access_file_utils.h"
38 #include "elf_utils.h"
39 #include "elf_file.h"
40 #include "elf_file_impl.h"
41 #include "gc/space/image_space.h"
42 #include "image-inl.h"
43 #include "intern_table.h"
44 #include "mirror/dex_cache.h"
45 #include "mirror/executable.h"
46 #include "mirror/object-inl.h"
47 #include "mirror/object-refvisitor-inl.h"
48 #include "mirror/method.h"
49 #include "mirror/reference.h"
50 #include "noop_compiler_callbacks.h"
51 #include "offsets.h"
52 #include "os.h"
53 #include "runtime.h"
54 #include "scoped_thread_state_change-inl.h"
55 #include "thread.h"
56 #include "utils.h"
57 
58 namespace art {
59 
GetOatHeader(const ElfFile * elf_file)60 static const OatHeader* GetOatHeader(const ElfFile* elf_file) {
61   uint64_t off = 0;
62   if (!elf_file->GetSectionOffsetAndSize(".rodata", &off, nullptr)) {
63     return nullptr;
64   }
65 
66   OatHeader* oat_header = reinterpret_cast<OatHeader*>(elf_file->Begin() + off);
67   return oat_header;
68 }
69 
CreateOrOpen(const char * name)70 static File* CreateOrOpen(const char* name) {
71   if (OS::FileExists(name)) {
72     return OS::OpenFileReadWrite(name);
73   } else {
74     std::unique_ptr<File> f(OS::CreateEmptyFile(name));
75     if (f.get() != nullptr) {
76       if (fchmod(f->Fd(), 0644) != 0) {
77         PLOG(ERROR) << "Unable to make " << name << " world readable";
78         unlink(name);
79         return nullptr;
80       }
81     }
82     return f.release();
83   }
84 }
85 
86 // Either try to close the file (close=true), or erase it.
FinishFile(File * file,bool close)87 static bool FinishFile(File* file, bool close) {
88   if (close) {
89     if (file->FlushCloseOrErase() != 0) {
90       PLOG(ERROR) << "Failed to flush and close file.";
91       return false;
92     }
93     return true;
94   } else {
95     file->Erase();
96     return false;
97   }
98 }
99 
SymlinkFile(const std::string & input_filename,const std::string & output_filename)100 static bool SymlinkFile(const std::string& input_filename, const std::string& output_filename) {
101   if (input_filename == output_filename) {
102     // Input and output are the same, nothing to do.
103     return true;
104   }
105 
106   // Unlink the original filename, since we are overwriting it.
107   unlink(output_filename.c_str());
108 
109   // Create a symlink from the source file to the target path.
110   if (symlink(input_filename.c_str(), output_filename.c_str()) < 0) {
111     PLOG(ERROR) << "Failed to create symlink " << output_filename << " -> " << input_filename;
112     return false;
113   }
114 
115   if (kIsDebugBuild) {
116     LOG(INFO) << "Created symlink " << output_filename << " -> " << input_filename;
117   }
118 
119   return true;
120 }
121 
Patch(const std::string & image_location,off_t delta,const std::string & output_directory,InstructionSet isa,TimingLogger * timings)122 bool PatchOat::Patch(const std::string& image_location,
123                      off_t delta,
124                      const std::string& output_directory,
125                      InstructionSet isa,
126                      TimingLogger* timings) {
127   CHECK(Runtime::Current() == nullptr);
128   CHECK(!image_location.empty()) << "image file must have a filename.";
129 
130   TimingLogger::ScopedTiming t("Runtime Setup", timings);
131 
132   CHECK_NE(isa, kNone);
133   const char* isa_name = GetInstructionSetString(isa);
134 
135   // Set up the runtime
136   RuntimeOptions options;
137   NoopCompilerCallbacks callbacks;
138   options.push_back(std::make_pair("compilercallbacks", &callbacks));
139   std::string img = "-Ximage:" + image_location;
140   options.push_back(std::make_pair(img.c_str(), nullptr));
141   options.push_back(std::make_pair("imageinstructionset", reinterpret_cast<const void*>(isa_name)));
142   options.push_back(std::make_pair("-Xno-sig-chain", nullptr));
143   if (!Runtime::Create(options, false)) {
144     LOG(ERROR) << "Unable to initialize runtime";
145     return false;
146   }
147   std::unique_ptr<Runtime> runtime(Runtime::Current());
148 
149   // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
150   // give it away now and then switch to a more manageable ScopedObjectAccess.
151   Thread::Current()->TransitionFromRunnableToSuspended(kNative);
152   ScopedObjectAccess soa(Thread::Current());
153 
154   t.NewTiming("Image Patching setup");
155   std::vector<gc::space::ImageSpace*> spaces = Runtime::Current()->GetHeap()->GetBootImageSpaces();
156   std::map<gc::space::ImageSpace*, std::unique_ptr<File>> space_to_file_map;
157   std::map<gc::space::ImageSpace*, std::unique_ptr<MemMap>> space_to_memmap_map;
158   std::map<gc::space::ImageSpace*, PatchOat> space_to_patchoat_map;
159 
160   for (size_t i = 0; i < spaces.size(); ++i) {
161     gc::space::ImageSpace* space = spaces[i];
162     std::string input_image_filename = space->GetImageFilename();
163     std::unique_ptr<File> input_image(OS::OpenFileForReading(input_image_filename.c_str()));
164     if (input_image.get() == nullptr) {
165       LOG(ERROR) << "Unable to open input image file at " << input_image_filename;
166       return false;
167     }
168 
169     int64_t image_len = input_image->GetLength();
170     if (image_len < 0) {
171       LOG(ERROR) << "Error while getting image length";
172       return false;
173     }
174     ImageHeader image_header;
175     if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header),
176                                                   sizeof(image_header), 0)) {
177       LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath();
178     }
179 
180     /*bool is_image_pic = */IsImagePic(image_header, input_image->GetPath());
181     // Nothing special to do right now since the image always needs to get patched.
182     // Perhaps in some far-off future we may have images with relative addresses that are true-PIC.
183 
184     // Create the map where we will write the image patches to.
185     std::string error_msg;
186     std::unique_ptr<MemMap> image(MemMap::MapFile(image_len,
187                                                   PROT_READ | PROT_WRITE,
188                                                   MAP_PRIVATE,
189                                                   input_image->Fd(),
190                                                   0,
191                                                   /*low_4gb*/false,
192                                                   input_image->GetPath().c_str(),
193                                                   &error_msg));
194     if (image.get() == nullptr) {
195       LOG(ERROR) << "Unable to map image file " << input_image->GetPath() << " : " << error_msg;
196       return false;
197     }
198     space_to_file_map.emplace(space, std::move(input_image));
199     space_to_memmap_map.emplace(space, std::move(image));
200   }
201 
202   // Symlink PIC oat and vdex files and patch the image spaces in memory.
203   for (size_t i = 0; i < spaces.size(); ++i) {
204     gc::space::ImageSpace* space = spaces[i];
205     std::string input_image_filename = space->GetImageFilename();
206     std::string input_vdex_filename =
207         ImageHeader::GetVdexLocationFromImageLocation(input_image_filename);
208     std::string input_oat_filename =
209         ImageHeader::GetOatLocationFromImageLocation(input_image_filename);
210     std::unique_ptr<File> input_oat_file(OS::OpenFileForReading(input_oat_filename.c_str()));
211     if (input_oat_file.get() == nullptr) {
212       LOG(ERROR) << "Unable to open input oat file at " << input_oat_filename;
213       return false;
214     }
215     std::string error_msg;
216     std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat_file.get(),
217                                                PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg));
218     if (elf.get() == nullptr) {
219       LOG(ERROR) << "Unable to open oat file " << input_oat_file->GetPath() << " : " << error_msg;
220       return false;
221     }
222 
223     MaybePic is_oat_pic = IsOatPic(elf.get());
224     if (is_oat_pic >= ERROR_FIRST) {
225       // Error logged by IsOatPic
226       return false;
227     } else if (is_oat_pic == NOT_PIC) {
228       LOG(ERROR) << "patchoat cannot be used on non-PIC oat file: " << input_oat_file->GetPath();
229       return false;
230     } else {
231       CHECK(is_oat_pic == PIC);
232 
233       // Create a symlink.
234       std::string converted_image_filename = space->GetImageLocation();
235       std::replace(converted_image_filename.begin() + 1, converted_image_filename.end(), '/', '@');
236       std::string output_image_filename = output_directory +
237           (android::base::StartsWith(converted_image_filename, "/") ? "" : "/") +
238           converted_image_filename;
239       std::string output_vdex_filename =
240           ImageHeader::GetVdexLocationFromImageLocation(output_image_filename);
241       std::string output_oat_filename =
242           ImageHeader::GetOatLocationFromImageLocation(output_image_filename);
243 
244       if (!ReplaceOatFileWithSymlink(input_oat_file->GetPath(),
245                                      output_oat_filename) ||
246           !SymlinkFile(input_vdex_filename, output_vdex_filename)) {
247         // Errors already logged by above call.
248         return false;
249       }
250     }
251 
252     PatchOat& p = space_to_patchoat_map.emplace(space,
253                                                 PatchOat(
254                                                     isa,
255                                                     space_to_memmap_map.find(space)->second.get(),
256                                                     space->GetLiveBitmap(),
257                                                     space->GetMemMap(),
258                                                     delta,
259                                                     &space_to_memmap_map,
260                                                     timings)).first->second;
261 
262     t.NewTiming("Patching image");
263     if (!p.PatchImage(i == 0)) {
264       LOG(ERROR) << "Failed to patch image file " << input_image_filename;
265       return false;
266     }
267   }
268 
269   // Write the patched image spaces.
270   for (size_t i = 0; i < spaces.size(); ++i) {
271     gc::space::ImageSpace* space = spaces[i];
272 
273     t.NewTiming("Writing image");
274     std::string converted_image_filename = space->GetImageLocation();
275     std::replace(converted_image_filename.begin() + 1, converted_image_filename.end(), '/', '@');
276     std::string output_image_filename = output_directory +
277         (android::base::StartsWith(converted_image_filename, "/") ? "" : "/") +
278         converted_image_filename;
279     std::unique_ptr<File> output_image_file(CreateOrOpen(output_image_filename.c_str()));
280     if (output_image_file.get() == nullptr) {
281       LOG(ERROR) << "Failed to open output image file at " << output_image_filename;
282       return false;
283     }
284 
285     PatchOat& p = space_to_patchoat_map.find(space)->second;
286 
287     bool success = p.WriteImage(output_image_file.get());
288     success = FinishFile(output_image_file.get(), success);
289     if (!success) {
290       return false;
291     }
292   }
293 
294   if (!kIsDebugBuild && !(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) {
295     // We want to just exit on non-debug builds, not bringing the runtime down
296     // in an orderly fashion. So release the following fields.
297     runtime.release();
298   }
299 
300   return true;
301 }
302 
WriteImage(File * out)303 bool PatchOat::WriteImage(File* out) {
304   TimingLogger::ScopedTiming t("Writing image File", timings_);
305   std::string error_msg;
306 
307   // No error checking here, this is best effort. The locking may or may not
308   // succeed and we don't really care either way.
309   ScopedFlock img_flock = LockedFile::DupOf(out->Fd(), out->GetPath(),
310                                             true /* read_only_mode */, &error_msg);
311 
312   CHECK(image_ != nullptr);
313   CHECK(out != nullptr);
314   size_t expect = image_->Size();
315   if (out->WriteFully(reinterpret_cast<char*>(image_->Begin()), expect) &&
316       out->SetLength(expect) == 0) {
317     return true;
318   } else {
319     LOG(ERROR) << "Writing to image file " << out->GetPath() << " failed.";
320     return false;
321   }
322 }
323 
IsImagePic(const ImageHeader & image_header,const std::string & image_path)324 bool PatchOat::IsImagePic(const ImageHeader& image_header, const std::string& image_path) {
325   if (!image_header.CompilePic()) {
326     if (kIsDebugBuild) {
327       LOG(INFO) << "image at location " << image_path << " was *not* compiled pic";
328     }
329     return false;
330   }
331 
332   if (kIsDebugBuild) {
333     LOG(INFO) << "image at location " << image_path << " was compiled PIC";
334   }
335 
336   return true;
337 }
338 
IsOatPic(const ElfFile * oat_in)339 PatchOat::MaybePic PatchOat::IsOatPic(const ElfFile* oat_in) {
340   if (oat_in == nullptr) {
341     LOG(ERROR) << "No ELF input oat fie available";
342     return ERROR_OAT_FILE;
343   }
344 
345   const std::string& file_path = oat_in->GetFilePath();
346 
347   const OatHeader* oat_header = GetOatHeader(oat_in);
348   if (oat_header == nullptr) {
349     LOG(ERROR) << "Failed to find oat header in oat file " << file_path;
350     return ERROR_OAT_FILE;
351   }
352 
353   if (!oat_header->IsValid()) {
354     LOG(ERROR) << "Elf file " << file_path << " has an invalid oat header";
355     return ERROR_OAT_FILE;
356   }
357 
358   bool is_pic = oat_header->IsPic();
359   if (kIsDebugBuild) {
360     LOG(INFO) << "Oat file at " << file_path << " is " << (is_pic ? "PIC" : "not pic");
361   }
362 
363   return is_pic ? PIC : NOT_PIC;
364 }
365 
ReplaceOatFileWithSymlink(const std::string & input_oat_filename,const std::string & output_oat_filename)366 bool PatchOat::ReplaceOatFileWithSymlink(const std::string& input_oat_filename,
367                                          const std::string& output_oat_filename) {
368   // Delete the original file, since we won't need it.
369   unlink(output_oat_filename.c_str());
370 
371   // Create a symlink from the old oat to the new oat
372   if (symlink(input_oat_filename.c_str(), output_oat_filename.c_str()) < 0) {
373     int err = errno;
374     LOG(ERROR) << "Failed to create symlink at " << output_oat_filename
375                << " error(" << err << "): " << strerror(err);
376     return false;
377   }
378 
379   if (kIsDebugBuild) {
380     LOG(INFO) << "Created symlink " << output_oat_filename << " -> " << input_oat_filename;
381   }
382 
383   return true;
384 }
385 
386 class PatchOat::PatchOatArtFieldVisitor : public ArtFieldVisitor {
387  public:
PatchOatArtFieldVisitor(PatchOat * patch_oat)388   explicit PatchOatArtFieldVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {}
389 
Visit(ArtField * field)390   void Visit(ArtField* field) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
391     ArtField* const dest = patch_oat_->RelocatedCopyOf(field);
392     dest->SetDeclaringClass(
393         patch_oat_->RelocatedAddressOfPointer(field->GetDeclaringClass().Ptr()));
394   }
395 
396  private:
397   PatchOat* const patch_oat_;
398 };
399 
PatchArtFields(const ImageHeader * image_header)400 void PatchOat::PatchArtFields(const ImageHeader* image_header) {
401   PatchOatArtFieldVisitor visitor(this);
402   image_header->VisitPackedArtFields(&visitor, heap_->Begin());
403 }
404 
405 class PatchOat::PatchOatArtMethodVisitor : public ArtMethodVisitor {
406  public:
PatchOatArtMethodVisitor(PatchOat * patch_oat)407   explicit PatchOatArtMethodVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {}
408 
Visit(ArtMethod * method)409   void Visit(ArtMethod* method) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
410     ArtMethod* const dest = patch_oat_->RelocatedCopyOf(method);
411     patch_oat_->FixupMethod(method, dest);
412   }
413 
414  private:
415   PatchOat* const patch_oat_;
416 };
417 
PatchArtMethods(const ImageHeader * image_header)418 void PatchOat::PatchArtMethods(const ImageHeader* image_header) {
419   const PointerSize pointer_size = InstructionSetPointerSize(isa_);
420   PatchOatArtMethodVisitor visitor(this);
421   image_header->VisitPackedArtMethods(&visitor, heap_->Begin(), pointer_size);
422 }
423 
PatchImTables(const ImageHeader * image_header)424 void PatchOat::PatchImTables(const ImageHeader* image_header) {
425   const PointerSize pointer_size = InstructionSetPointerSize(isa_);
426   // We can safely walk target image since the conflict tables are independent.
427   image_header->VisitPackedImTables(
428       [this](ArtMethod* method) {
429         return RelocatedAddressOfPointer(method);
430       },
431       image_->Begin(),
432       pointer_size);
433 }
434 
PatchImtConflictTables(const ImageHeader * image_header)435 void PatchOat::PatchImtConflictTables(const ImageHeader* image_header) {
436   const PointerSize pointer_size = InstructionSetPointerSize(isa_);
437   // We can safely walk target image since the conflict tables are independent.
438   image_header->VisitPackedImtConflictTables(
439       [this](ArtMethod* method) {
440         return RelocatedAddressOfPointer(method);
441       },
442       image_->Begin(),
443       pointer_size);
444 }
445 
446 class PatchOat::FixupRootVisitor : public RootVisitor {
447  public:
FixupRootVisitor(const PatchOat * patch_oat)448   explicit FixupRootVisitor(const PatchOat* patch_oat) : patch_oat_(patch_oat) {
449   }
450 
VisitRoots(mirror::Object *** roots,size_t count,const RootInfo & info ATTRIBUTE_UNUSED)451   void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info ATTRIBUTE_UNUSED)
452       OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
453     for (size_t i = 0; i < count; ++i) {
454       *roots[i] = patch_oat_->RelocatedAddressOfPointer(*roots[i]);
455     }
456   }
457 
VisitRoots(mirror::CompressedReference<mirror::Object> ** roots,size_t count,const RootInfo & info ATTRIBUTE_UNUSED)458   void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
459                   const RootInfo& info ATTRIBUTE_UNUSED)
460       OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
461     for (size_t i = 0; i < count; ++i) {
462       roots[i]->Assign(patch_oat_->RelocatedAddressOfPointer(roots[i]->AsMirrorPtr()));
463     }
464   }
465 
466  private:
467   const PatchOat* const patch_oat_;
468 };
469 
PatchInternedStrings(const ImageHeader * image_header)470 void PatchOat::PatchInternedStrings(const ImageHeader* image_header) {
471   const auto& section = image_header->GetImageSection(ImageHeader::kSectionInternedStrings);
472   InternTable temp_table;
473   // Note that we require that ReadFromMemory does not make an internal copy of the elements.
474   // This also relies on visit roots not doing any verification which could fail after we update
475   // the roots to be the image addresses.
476   temp_table.AddTableFromMemory(image_->Begin() + section.Offset());
477   FixupRootVisitor visitor(this);
478   temp_table.VisitRoots(&visitor, kVisitRootFlagAllRoots);
479 }
480 
PatchClassTable(const ImageHeader * image_header)481 void PatchOat::PatchClassTable(const ImageHeader* image_header) {
482   const auto& section = image_header->GetImageSection(ImageHeader::kSectionClassTable);
483   if (section.Size() == 0) {
484     return;
485   }
486   // Note that we require that ReadFromMemory does not make an internal copy of the elements.
487   // This also relies on visit roots not doing any verification which could fail after we update
488   // the roots to be the image addresses.
489   WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
490   ClassTable temp_table;
491   temp_table.ReadFromMemory(image_->Begin() + section.Offset());
492   FixupRootVisitor visitor(this);
493   temp_table.VisitRoots(UnbufferedRootVisitor(&visitor, RootInfo(kRootUnknown)));
494 }
495 
496 
497 class PatchOat::RelocatedPointerVisitor {
498  public:
RelocatedPointerVisitor(PatchOat * patch_oat)499   explicit RelocatedPointerVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {}
500 
501   template <typename T>
operator ()(T * ptr,void ** dest_addr ATTRIBUTE_UNUSED=0) const502   T* operator()(T* ptr, void** dest_addr ATTRIBUTE_UNUSED = 0) const {
503     return patch_oat_->RelocatedAddressOfPointer(ptr);
504   }
505 
506  private:
507   PatchOat* const patch_oat_;
508 };
509 
PatchDexFileArrays(mirror::ObjectArray<mirror::Object> * img_roots)510 void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots) {
511   auto* dex_caches = down_cast<mirror::ObjectArray<mirror::DexCache>*>(
512       img_roots->Get(ImageHeader::kDexCaches));
513   const PointerSize pointer_size = InstructionSetPointerSize(isa_);
514   for (size_t i = 0, count = dex_caches->GetLength(); i < count; ++i) {
515     auto* orig_dex_cache = dex_caches->GetWithoutChecks(i);
516     auto* copy_dex_cache = RelocatedCopyOf(orig_dex_cache);
517     // Though the DexCache array fields are usually treated as native pointers, we set the full
518     // 64-bit values here, clearing the top 32 bits for 32-bit targets. The zero-extension is
519     // done by casting to the unsigned type uintptr_t before casting to int64_t, i.e.
520     //     static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + offset))).
521     mirror::StringDexCacheType* orig_strings = orig_dex_cache->GetStrings();
522     mirror::StringDexCacheType* relocated_strings = RelocatedAddressOfPointer(orig_strings);
523     copy_dex_cache->SetField64<false>(
524         mirror::DexCache::StringsOffset(),
525         static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_strings)));
526     if (orig_strings != nullptr) {
527       orig_dex_cache->FixupStrings(RelocatedCopyOf(orig_strings), RelocatedPointerVisitor(this));
528     }
529     mirror::TypeDexCacheType* orig_types = orig_dex_cache->GetResolvedTypes();
530     mirror::TypeDexCacheType* relocated_types = RelocatedAddressOfPointer(orig_types);
531     copy_dex_cache->SetField64<false>(
532         mirror::DexCache::ResolvedTypesOffset(),
533         static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_types)));
534     if (orig_types != nullptr) {
535       orig_dex_cache->FixupResolvedTypes(RelocatedCopyOf(orig_types),
536                                          RelocatedPointerVisitor(this));
537     }
538     mirror::MethodDexCacheType* orig_methods = orig_dex_cache->GetResolvedMethods();
539     mirror::MethodDexCacheType* relocated_methods = RelocatedAddressOfPointer(orig_methods);
540     copy_dex_cache->SetField64<false>(
541         mirror::DexCache::ResolvedMethodsOffset(),
542         static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_methods)));
543     if (orig_methods != nullptr) {
544       mirror::MethodDexCacheType* copy_methods = RelocatedCopyOf(orig_methods);
545       for (size_t j = 0, num = orig_dex_cache->NumResolvedMethods(); j != num; ++j) {
546         mirror::MethodDexCachePair orig =
547             mirror::DexCache::GetNativePairPtrSize(orig_methods, j, pointer_size);
548         mirror::MethodDexCachePair copy(RelocatedAddressOfPointer(orig.object), orig.index);
549         mirror::DexCache::SetNativePairPtrSize(copy_methods, j, copy, pointer_size);
550       }
551     }
552     mirror::FieldDexCacheType* orig_fields = orig_dex_cache->GetResolvedFields();
553     mirror::FieldDexCacheType* relocated_fields = RelocatedAddressOfPointer(orig_fields);
554     copy_dex_cache->SetField64<false>(
555         mirror::DexCache::ResolvedFieldsOffset(),
556         static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_fields)));
557     if (orig_fields != nullptr) {
558       mirror::FieldDexCacheType* copy_fields = RelocatedCopyOf(orig_fields);
559       for (size_t j = 0, num = orig_dex_cache->NumResolvedFields(); j != num; ++j) {
560         mirror::FieldDexCachePair orig =
561             mirror::DexCache::GetNativePairPtrSize(orig_fields, j, pointer_size);
562         mirror::FieldDexCachePair copy(RelocatedAddressOfPointer(orig.object), orig.index);
563         mirror::DexCache::SetNativePairPtrSize(copy_fields, j, copy, pointer_size);
564       }
565     }
566     mirror::MethodTypeDexCacheType* orig_method_types = orig_dex_cache->GetResolvedMethodTypes();
567     mirror::MethodTypeDexCacheType* relocated_method_types =
568         RelocatedAddressOfPointer(orig_method_types);
569     copy_dex_cache->SetField64<false>(
570         mirror::DexCache::ResolvedMethodTypesOffset(),
571         static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_method_types)));
572     if (orig_method_types != nullptr) {
573       orig_dex_cache->FixupResolvedMethodTypes(RelocatedCopyOf(orig_method_types),
574                                                RelocatedPointerVisitor(this));
575     }
576 
577     GcRoot<mirror::CallSite>* orig_call_sites = orig_dex_cache->GetResolvedCallSites();
578     GcRoot<mirror::CallSite>* relocated_call_sites = RelocatedAddressOfPointer(orig_call_sites);
579     copy_dex_cache->SetField64<false>(
580         mirror::DexCache::ResolvedCallSitesOffset(),
581         static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_call_sites)));
582     if (orig_call_sites != nullptr) {
583       orig_dex_cache->FixupResolvedCallSites(RelocatedCopyOf(orig_call_sites),
584                                              RelocatedPointerVisitor(this));
585     }
586   }
587 }
588 
PatchImage(bool primary_image)589 bool PatchOat::PatchImage(bool primary_image) {
590   ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
591   CHECK_GT(image_->Size(), sizeof(ImageHeader));
592   // These are the roots from the original file.
593   auto* img_roots = image_header->GetImageRoots();
594   image_header->RelocateImage(delta_);
595 
596   PatchArtFields(image_header);
597   PatchArtMethods(image_header);
598   PatchImTables(image_header);
599   PatchImtConflictTables(image_header);
600   PatchInternedStrings(image_header);
601   PatchClassTable(image_header);
602   // Patch dex file int/long arrays which point to ArtFields.
603   PatchDexFileArrays(img_roots);
604 
605   if (primary_image) {
606     VisitObject(img_roots);
607   }
608 
609   if (!image_header->IsValid()) {
610     LOG(ERROR) << "relocation renders image header invalid";
611     return false;
612   }
613 
614   {
615     TimingLogger::ScopedTiming t("Walk Bitmap", timings_);
616     // Walk the bitmap.
617     WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
618     auto visitor = [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
619       VisitObject(obj);
620     };
621     bitmap_->Walk(visitor);
622   }
623   return true;
624 }
625 
626 
operator ()(ObjPtr<mirror::Object> obj,MemberOffset off,bool is_static_unused ATTRIBUTE_UNUSED) const627 void PatchOat::PatchVisitor::operator() (ObjPtr<mirror::Object> obj,
628                                          MemberOffset off,
629                                          bool is_static_unused ATTRIBUTE_UNUSED) const {
630   mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off);
631   mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent);
632   copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object);
633 }
634 
operator ()(ObjPtr<mirror::Class> cls ATTRIBUTE_UNUSED,ObjPtr<mirror::Reference> ref) const635 void PatchOat::PatchVisitor::operator() (ObjPtr<mirror::Class> cls ATTRIBUTE_UNUSED,
636                                          ObjPtr<mirror::Reference> ref) const {
637   MemberOffset off = mirror::Reference::ReferentOffset();
638   mirror::Object* referent = ref->GetReferent();
639   DCHECK(referent == nullptr ||
640          Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(referent)) << referent;
641   mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent);
642   copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object);
643 }
644 
645 // Called by PatchImage.
VisitObject(mirror::Object * object)646 void PatchOat::VisitObject(mirror::Object* object) {
647   mirror::Object* copy = RelocatedCopyOf(object);
648   CHECK(copy != nullptr);
649   if (kUseBakerReadBarrier) {
650     object->AssertReadBarrierState();
651   }
652   PatchOat::PatchVisitor visitor(this, copy);
653   object->VisitReferences<kVerifyNone>(visitor, visitor);
654   if (object->IsClass<kVerifyNone>()) {
655     const PointerSize pointer_size = InstructionSetPointerSize(isa_);
656     mirror::Class* klass = object->AsClass();
657     mirror::Class* copy_klass = down_cast<mirror::Class*>(copy);
658     RelocatedPointerVisitor native_visitor(this);
659     klass->FixupNativePointers(copy_klass, pointer_size, native_visitor);
660     auto* vtable = klass->GetVTable();
661     if (vtable != nullptr) {
662       vtable->Fixup(RelocatedCopyOfFollowImages(vtable), pointer_size, native_visitor);
663     }
664     mirror::IfTable* iftable = klass->GetIfTable();
665     for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
666       if (iftable->GetMethodArrayCount(i) > 0) {
667         auto* method_array = iftable->GetMethodArray(i);
668         CHECK(method_array != nullptr);
669         method_array->Fixup(RelocatedCopyOfFollowImages(method_array),
670                             pointer_size,
671                             native_visitor);
672       }
673     }
674   } else if (object->GetClass() == mirror::Method::StaticClass() ||
675              object->GetClass() == mirror::Constructor::StaticClass()) {
676     // Need to go update the ArtMethod.
677     auto* dest = down_cast<mirror::Executable*>(copy);
678     auto* src = down_cast<mirror::Executable*>(object);
679     dest->SetArtMethod(RelocatedAddressOfPointer(src->GetArtMethod()));
680   }
681 }
682 
FixupMethod(ArtMethod * object,ArtMethod * copy)683 void PatchOat::FixupMethod(ArtMethod* object, ArtMethod* copy) {
684   const PointerSize pointer_size = InstructionSetPointerSize(isa_);
685   copy->CopyFrom(object, pointer_size);
686   // Just update the entry points if it looks like we should.
687   // TODO: sanity check all the pointers' values
688   copy->SetDeclaringClass(RelocatedAddressOfPointer(object->GetDeclaringClass()));
689   copy->SetDexCacheResolvedMethods(
690       RelocatedAddressOfPointer(object->GetDexCacheResolvedMethods(pointer_size)), pointer_size);
691   copy->SetEntryPointFromQuickCompiledCodePtrSize(RelocatedAddressOfPointer(
692       object->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size)), pointer_size);
693   // No special handling for IMT conflict table since all pointers are moved by the same offset.
694   copy->SetDataPtrSize(RelocatedAddressOfPointer(
695       object->GetDataPtrSize(pointer_size)), pointer_size);
696 }
697 
698 static int orig_argc;
699 static char** orig_argv;
700 
CommandLine()701 static std::string CommandLine() {
702   std::vector<std::string> command;
703   for (int i = 0; i < orig_argc; ++i) {
704     command.push_back(orig_argv[i]);
705   }
706   return android::base::Join(command, ' ');
707 }
708 
UsageErrorV(const char * fmt,va_list ap)709 static void UsageErrorV(const char* fmt, va_list ap) {
710   std::string error;
711   android::base::StringAppendV(&error, fmt, ap);
712   LOG(ERROR) << error;
713 }
714 
UsageError(const char * fmt,...)715 static void UsageError(const char* fmt, ...) {
716   va_list ap;
717   va_start(ap, fmt);
718   UsageErrorV(fmt, ap);
719   va_end(ap);
720 }
721 
Usage(const char * fmt,...)722 NO_RETURN static void Usage(const char *fmt, ...) {
723   va_list ap;
724   va_start(ap, fmt);
725   UsageErrorV(fmt, ap);
726   va_end(ap);
727 
728   UsageError("Command: %s", CommandLine().c_str());
729   UsageError("Usage: patchoat [options]...");
730   UsageError("");
731   UsageError("  --instruction-set=<isa>: Specifies the instruction set the patched code is");
732   UsageError("      compiled for (required).");
733   UsageError("");
734   UsageError("  --input-image-location=<file.art>: Specifies the 'location' of the image file to");
735   UsageError("      be patched.");
736   UsageError("");
737   UsageError("  --output-image-file=<file.art>: Specifies the exact file to write the patched");
738   UsageError("      image file to.");
739   UsageError("");
740   UsageError("  --base-offset-delta=<delta>: Specify the amount to change the old base-offset by.");
741   UsageError("      This value may be negative.");
742   UsageError("");
743   UsageError("  --dump-timings: dump out patch timing information");
744   UsageError("");
745   UsageError("  --no-dump-timings: do not dump out patch timing information");
746   UsageError("");
747 
748   exit(EXIT_FAILURE);
749 }
750 
patchoat_image(TimingLogger & timings,InstructionSet isa,const std::string & input_image_location,const std::string & output_image_filename,off_t base_delta,bool base_delta_set,bool debug)751 static int patchoat_image(TimingLogger& timings,
752                           InstructionSet isa,
753                           const std::string& input_image_location,
754                           const std::string& output_image_filename,
755                           off_t base_delta,
756                           bool base_delta_set,
757                           bool debug) {
758   CHECK(!input_image_location.empty());
759   if (output_image_filename.empty()) {
760     Usage("Image patching requires --output-image-file");
761   }
762 
763   if (!base_delta_set) {
764     Usage("Must supply a desired new offset or delta.");
765   }
766 
767   if (!IsAligned<kPageSize>(base_delta)) {
768     Usage("Base offset/delta must be aligned to a pagesize (0x%08x) boundary.", kPageSize);
769   }
770 
771   if (debug) {
772     LOG(INFO) << "moving offset by " << base_delta
773         << " (0x" << std::hex << base_delta << ") bytes or "
774         << std::dec << (base_delta/kPageSize) << " pages.";
775   }
776 
777   TimingLogger::ScopedTiming pt("patch image and oat", &timings);
778 
779   std::string output_directory =
780       output_image_filename.substr(0, output_image_filename.find_last_of('/'));
781   bool ret = PatchOat::Patch(input_image_location, base_delta, output_directory, isa, &timings);
782 
783   if (kIsDebugBuild) {
784     LOG(INFO) << "Exiting with return ... " << ret;
785   }
786   return ret ? EXIT_SUCCESS : EXIT_FAILURE;
787 }
788 
patchoat(int argc,char ** argv)789 static int patchoat(int argc, char **argv) {
790   InitLogging(argv, Runtime::Abort);
791   MemMap::Init();
792   const bool debug = kIsDebugBuild;
793   orig_argc = argc;
794   orig_argv = argv;
795   TimingLogger timings("patcher", false, false);
796 
797   // Skip over the command name.
798   argv++;
799   argc--;
800 
801   if (argc == 0) {
802     Usage("No arguments specified");
803   }
804 
805   timings.StartTiming("Patchoat");
806 
807   // cmd line args
808   bool isa_set = false;
809   InstructionSet isa = kNone;
810   std::string input_image_location;
811   std::string output_image_filename;
812   off_t base_delta = 0;
813   bool base_delta_set = false;
814   bool dump_timings = kIsDebugBuild;
815 
816   for (int i = 0; i < argc; ++i) {
817     const StringPiece option(argv[i]);
818     const bool log_options = false;
819     if (log_options) {
820       LOG(INFO) << "patchoat: option[" << i << "]=" << argv[i];
821     }
822     if (option.starts_with("--instruction-set=")) {
823       isa_set = true;
824       const char* isa_str = option.substr(strlen("--instruction-set=")).data();
825       isa = GetInstructionSetFromString(isa_str);
826       if (isa == kNone) {
827         Usage("Unknown or invalid instruction set %s", isa_str);
828       }
829     } else if (option.starts_with("--input-image-location=")) {
830       input_image_location = option.substr(strlen("--input-image-location=")).data();
831     } else if (option.starts_with("--output-image-file=")) {
832       output_image_filename = option.substr(strlen("--output-image-file=")).data();
833     } else if (option.starts_with("--base-offset-delta=")) {
834       const char* base_delta_str = option.substr(strlen("--base-offset-delta=")).data();
835       base_delta_set = true;
836       if (!ParseInt(base_delta_str, &base_delta)) {
837         Usage("Failed to parse --base-offset-delta argument '%s' as an off_t", base_delta_str);
838       }
839     } else if (option == "--dump-timings") {
840       dump_timings = true;
841     } else if (option == "--no-dump-timings") {
842       dump_timings = false;
843     } else {
844       Usage("Unknown argument %s", option.data());
845     }
846   }
847 
848   // The instruction set is mandatory. This simplifies things...
849   if (!isa_set) {
850     Usage("Instruction set must be set.");
851   }
852 
853   int ret = patchoat_image(timings,
854                            isa,
855                            input_image_location,
856                            output_image_filename,
857                            base_delta,
858                            base_delta_set,
859                            debug);
860 
861   timings.EndTiming();
862   if (dump_timings) {
863     LOG(INFO) << Dumpable<TimingLogger>(timings);
864   }
865 
866   return ret;
867 }
868 
869 }  // namespace art
870 
main(int argc,char ** argv)871 int main(int argc, char **argv) {
872   return art::patchoat(argc, argv);
873 }
874