patchoat.cc revision 6cfbdbc359ec5414d3e49f70d28f8c0e65b98d63
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_file.h" 39#include "elf_file_impl.h" 40#include "elf_utils.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/method.h" 47#include "mirror/object-inl.h" 48#include "mirror/object-refvisitor-inl.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 58namespace art { 59 60static 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 70static 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. 87static 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 100static 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 122bool 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 303bool 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 324bool 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 339PatchOat::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 366bool 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 386class PatchOat::PatchOatArtFieldVisitor : public ArtFieldVisitor { 387 public: 388 explicit PatchOatArtFieldVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {} 389 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 400void PatchOat::PatchArtFields(const ImageHeader* image_header) { 401 PatchOatArtFieldVisitor visitor(this); 402 image_header->VisitPackedArtFields(&visitor, heap_->Begin()); 403} 404 405class PatchOat::PatchOatArtMethodVisitor : public ArtMethodVisitor { 406 public: 407 explicit PatchOatArtMethodVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {} 408 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 418void 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 424void 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 435void 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 446class PatchOat::FixupRootVisitor : public RootVisitor { 447 public: 448 explicit FixupRootVisitor(const PatchOat* patch_oat) : patch_oat_(patch_oat) { 449 } 450 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 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 470void PatchOat::PatchInternedStrings(const ImageHeader* image_header) { 471 const auto& section = image_header->GetInternedStringsSection(); 472 if (section.Size() == 0) { 473 return; 474 } 475 InternTable temp_table; 476 // Note that we require that ReadFromMemory does not make an internal copy of the elements. 477 // This also relies on visit roots not doing any verification which could fail after we update 478 // the roots to be the image addresses. 479 temp_table.AddTableFromMemory(image_->Begin() + section.Offset()); 480 FixupRootVisitor visitor(this); 481 temp_table.VisitRoots(&visitor, kVisitRootFlagAllRoots); 482} 483 484void PatchOat::PatchClassTable(const ImageHeader* image_header) { 485 const auto& section = image_header->GetClassTableSection(); 486 if (section.Size() == 0) { 487 return; 488 } 489 // Note that we require that ReadFromMemory does not make an internal copy of the elements. 490 // This also relies on visit roots not doing any verification which could fail after we update 491 // the roots to be the image addresses. 492 WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); 493 ClassTable temp_table; 494 temp_table.ReadFromMemory(image_->Begin() + section.Offset()); 495 FixupRootVisitor visitor(this); 496 temp_table.VisitRoots(UnbufferedRootVisitor(&visitor, RootInfo(kRootUnknown))); 497} 498 499 500class PatchOat::RelocatedPointerVisitor { 501 public: 502 explicit RelocatedPointerVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {} 503 504 template <typename T> 505 T* operator()(T* ptr, void** dest_addr ATTRIBUTE_UNUSED = 0) const { 506 return patch_oat_->RelocatedAddressOfPointer(ptr); 507 } 508 509 private: 510 PatchOat* const patch_oat_; 511}; 512 513void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots) { 514 auto* dex_caches = down_cast<mirror::ObjectArray<mirror::DexCache>*>( 515 img_roots->Get(ImageHeader::kDexCaches)); 516 const PointerSize pointer_size = InstructionSetPointerSize(isa_); 517 for (size_t i = 0, count = dex_caches->GetLength(); i < count; ++i) { 518 auto* orig_dex_cache = dex_caches->GetWithoutChecks(i); 519 auto* copy_dex_cache = RelocatedCopyOf(orig_dex_cache); 520 // Though the DexCache array fields are usually treated as native pointers, we set the full 521 // 64-bit values here, clearing the top 32 bits for 32-bit targets. The zero-extension is 522 // done by casting to the unsigned type uintptr_t before casting to int64_t, i.e. 523 // static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + offset))). 524 mirror::StringDexCacheType* orig_strings = orig_dex_cache->GetStrings(); 525 mirror::StringDexCacheType* relocated_strings = RelocatedAddressOfPointer(orig_strings); 526 copy_dex_cache->SetField64<false>( 527 mirror::DexCache::StringsOffset(), 528 static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_strings))); 529 if (orig_strings != nullptr) { 530 orig_dex_cache->FixupStrings(RelocatedCopyOf(orig_strings), RelocatedPointerVisitor(this)); 531 } 532 mirror::TypeDexCacheType* orig_types = orig_dex_cache->GetResolvedTypes(); 533 mirror::TypeDexCacheType* relocated_types = RelocatedAddressOfPointer(orig_types); 534 copy_dex_cache->SetField64<false>( 535 mirror::DexCache::ResolvedTypesOffset(), 536 static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_types))); 537 if (orig_types != nullptr) { 538 orig_dex_cache->FixupResolvedTypes(RelocatedCopyOf(orig_types), 539 RelocatedPointerVisitor(this)); 540 } 541 mirror::MethodDexCacheType* orig_methods = orig_dex_cache->GetResolvedMethods(); 542 mirror::MethodDexCacheType* relocated_methods = RelocatedAddressOfPointer(orig_methods); 543 copy_dex_cache->SetField64<false>( 544 mirror::DexCache::ResolvedMethodsOffset(), 545 static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_methods))); 546 if (orig_methods != nullptr) { 547 mirror::MethodDexCacheType* copy_methods = RelocatedCopyOf(orig_methods); 548 for (size_t j = 0, num = orig_dex_cache->NumResolvedMethods(); j != num; ++j) { 549 mirror::MethodDexCachePair orig = 550 mirror::DexCache::GetNativePairPtrSize(orig_methods, j, pointer_size); 551 mirror::MethodDexCachePair copy(RelocatedAddressOfPointer(orig.object), orig.index); 552 mirror::DexCache::SetNativePairPtrSize(copy_methods, j, copy, pointer_size); 553 } 554 } 555 mirror::FieldDexCacheType* orig_fields = orig_dex_cache->GetResolvedFields(); 556 mirror::FieldDexCacheType* relocated_fields = RelocatedAddressOfPointer(orig_fields); 557 copy_dex_cache->SetField64<false>( 558 mirror::DexCache::ResolvedFieldsOffset(), 559 static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_fields))); 560 if (orig_fields != nullptr) { 561 mirror::FieldDexCacheType* copy_fields = RelocatedCopyOf(orig_fields); 562 for (size_t j = 0, num = orig_dex_cache->NumResolvedFields(); j != num; ++j) { 563 mirror::FieldDexCachePair orig = 564 mirror::DexCache::GetNativePairPtrSize(orig_fields, j, pointer_size); 565 mirror::FieldDexCachePair copy(RelocatedAddressOfPointer(orig.object), orig.index); 566 mirror::DexCache::SetNativePairPtrSize(copy_fields, j, copy, pointer_size); 567 } 568 } 569 mirror::MethodTypeDexCacheType* orig_method_types = orig_dex_cache->GetResolvedMethodTypes(); 570 mirror::MethodTypeDexCacheType* relocated_method_types = 571 RelocatedAddressOfPointer(orig_method_types); 572 copy_dex_cache->SetField64<false>( 573 mirror::DexCache::ResolvedMethodTypesOffset(), 574 static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_method_types))); 575 if (orig_method_types != nullptr) { 576 orig_dex_cache->FixupResolvedMethodTypes(RelocatedCopyOf(orig_method_types), 577 RelocatedPointerVisitor(this)); 578 } 579 580 GcRoot<mirror::CallSite>* orig_call_sites = orig_dex_cache->GetResolvedCallSites(); 581 GcRoot<mirror::CallSite>* relocated_call_sites = RelocatedAddressOfPointer(orig_call_sites); 582 copy_dex_cache->SetField64<false>( 583 mirror::DexCache::ResolvedCallSitesOffset(), 584 static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_call_sites))); 585 if (orig_call_sites != nullptr) { 586 orig_dex_cache->FixupResolvedCallSites(RelocatedCopyOf(orig_call_sites), 587 RelocatedPointerVisitor(this)); 588 } 589 } 590} 591 592bool PatchOat::PatchImage(bool primary_image) { 593 ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); 594 CHECK_GT(image_->Size(), sizeof(ImageHeader)); 595 // These are the roots from the original file. 596 auto* img_roots = image_header->GetImageRoots(); 597 image_header->RelocateImage(delta_); 598 599 PatchArtFields(image_header); 600 PatchArtMethods(image_header); 601 PatchImTables(image_header); 602 PatchImtConflictTables(image_header); 603 PatchInternedStrings(image_header); 604 PatchClassTable(image_header); 605 // Patch dex file int/long arrays which point to ArtFields. 606 PatchDexFileArrays(img_roots); 607 608 if (primary_image) { 609 VisitObject(img_roots); 610 } 611 612 if (!image_header->IsValid()) { 613 LOG(ERROR) << "relocation renders image header invalid"; 614 return false; 615 } 616 617 { 618 TimingLogger::ScopedTiming t("Walk Bitmap", timings_); 619 // Walk the bitmap. 620 WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); 621 auto visitor = [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) { 622 VisitObject(obj); 623 }; 624 bitmap_->Walk(visitor); 625 } 626 return true; 627} 628 629 630void PatchOat::PatchVisitor::operator() (ObjPtr<mirror::Object> obj, 631 MemberOffset off, 632 bool is_static_unused ATTRIBUTE_UNUSED) const { 633 mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off); 634 mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent); 635 copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); 636} 637 638void PatchOat::PatchVisitor::operator() (ObjPtr<mirror::Class> cls ATTRIBUTE_UNUSED, 639 ObjPtr<mirror::Reference> ref) const { 640 MemberOffset off = mirror::Reference::ReferentOffset(); 641 mirror::Object* referent = ref->GetReferent(); 642 DCHECK(referent == nullptr || 643 Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(referent)) << referent; 644 mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent); 645 copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); 646} 647 648// Called by PatchImage. 649void PatchOat::VisitObject(mirror::Object* object) { 650 mirror::Object* copy = RelocatedCopyOf(object); 651 CHECK(copy != nullptr); 652 if (kUseBakerReadBarrier) { 653 object->AssertReadBarrierState(); 654 } 655 PatchOat::PatchVisitor visitor(this, copy); 656 object->VisitReferences<kVerifyNone>(visitor, visitor); 657 if (object->IsClass<kVerifyNone>()) { 658 const PointerSize pointer_size = InstructionSetPointerSize(isa_); 659 mirror::Class* klass = object->AsClass(); 660 mirror::Class* copy_klass = down_cast<mirror::Class*>(copy); 661 RelocatedPointerVisitor native_visitor(this); 662 klass->FixupNativePointers(copy_klass, pointer_size, native_visitor); 663 auto* vtable = klass->GetVTable(); 664 if (vtable != nullptr) { 665 vtable->Fixup(RelocatedCopyOfFollowImages(vtable), pointer_size, native_visitor); 666 } 667 mirror::IfTable* iftable = klass->GetIfTable(); 668 for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) { 669 if (iftable->GetMethodArrayCount(i) > 0) { 670 auto* method_array = iftable->GetMethodArray(i); 671 CHECK(method_array != nullptr); 672 method_array->Fixup(RelocatedCopyOfFollowImages(method_array), 673 pointer_size, 674 native_visitor); 675 } 676 } 677 } else if (object->GetClass() == mirror::Method::StaticClass() || 678 object->GetClass() == mirror::Constructor::StaticClass()) { 679 // Need to go update the ArtMethod. 680 auto* dest = down_cast<mirror::Executable*>(copy); 681 auto* src = down_cast<mirror::Executable*>(object); 682 dest->SetArtMethod(RelocatedAddressOfPointer(src->GetArtMethod())); 683 } 684} 685 686void PatchOat::FixupMethod(ArtMethod* object, ArtMethod* copy) { 687 const PointerSize pointer_size = InstructionSetPointerSize(isa_); 688 copy->CopyFrom(object, pointer_size); 689 // Just update the entry points if it looks like we should. 690 // TODO: sanity check all the pointers' values 691 copy->SetDeclaringClass(RelocatedAddressOfPointer(object->GetDeclaringClass())); 692 copy->SetEntryPointFromQuickCompiledCodePtrSize(RelocatedAddressOfPointer( 693 object->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size)), pointer_size); 694 // No special handling for IMT conflict table since all pointers are moved by the same offset. 695 copy->SetDataPtrSize(RelocatedAddressOfPointer( 696 object->GetDataPtrSize(pointer_size)), pointer_size); 697} 698 699static int orig_argc; 700static char** orig_argv; 701 702static std::string CommandLine() { 703 std::vector<std::string> command; 704 for (int i = 0; i < orig_argc; ++i) { 705 command.push_back(orig_argv[i]); 706 } 707 return android::base::Join(command, ' '); 708} 709 710static void UsageErrorV(const char* fmt, va_list ap) { 711 std::string error; 712 android::base::StringAppendV(&error, fmt, ap); 713 LOG(ERROR) << error; 714} 715 716static void UsageError(const char* fmt, ...) { 717 va_list ap; 718 va_start(ap, fmt); 719 UsageErrorV(fmt, ap); 720 va_end(ap); 721} 722 723NO_RETURN static void Usage(const char *fmt, ...) { 724 va_list ap; 725 va_start(ap, fmt); 726 UsageErrorV(fmt, ap); 727 va_end(ap); 728 729 UsageError("Command: %s", CommandLine().c_str()); 730 UsageError("Usage: patchoat [options]..."); 731 UsageError(""); 732 UsageError(" --instruction-set=<isa>: Specifies the instruction set the patched code is"); 733 UsageError(" compiled for (required)."); 734 UsageError(""); 735 UsageError(" --input-image-location=<file.art>: Specifies the 'location' of the image file to"); 736 UsageError(" be patched."); 737 UsageError(""); 738 UsageError(" --output-image-file=<file.art>: Specifies the exact file to write the patched"); 739 UsageError(" image file to."); 740 UsageError(""); 741 UsageError(" --base-offset-delta=<delta>: Specify the amount to change the old base-offset by."); 742 UsageError(" This value may be negative."); 743 UsageError(""); 744 UsageError(" --dump-timings: dump out patch timing information"); 745 UsageError(""); 746 UsageError(" --no-dump-timings: do not dump out patch timing information"); 747 UsageError(""); 748 749 exit(EXIT_FAILURE); 750} 751 752static int patchoat_image(TimingLogger& timings, 753 InstructionSet isa, 754 const std::string& input_image_location, 755 const std::string& output_image_filename, 756 off_t base_delta, 757 bool base_delta_set, 758 bool debug) { 759 CHECK(!input_image_location.empty()); 760 if (output_image_filename.empty()) { 761 Usage("Image patching requires --output-image-file"); 762 } 763 764 if (!base_delta_set) { 765 Usage("Must supply a desired new offset or delta."); 766 } 767 768 if (!IsAligned<kPageSize>(base_delta)) { 769 Usage("Base offset/delta must be aligned to a pagesize (0x%08x) boundary.", kPageSize); 770 } 771 772 if (debug) { 773 LOG(INFO) << "moving offset by " << base_delta 774 << " (0x" << std::hex << base_delta << ") bytes or " 775 << std::dec << (base_delta/kPageSize) << " pages."; 776 } 777 778 TimingLogger::ScopedTiming pt("patch image and oat", &timings); 779 780 std::string output_directory = 781 output_image_filename.substr(0, output_image_filename.find_last_of('/')); 782 bool ret = PatchOat::Patch(input_image_location, base_delta, output_directory, isa, &timings); 783 784 if (kIsDebugBuild) { 785 LOG(INFO) << "Exiting with return ... " << ret; 786 } 787 return ret ? EXIT_SUCCESS : EXIT_FAILURE; 788} 789 790static int patchoat(int argc, char **argv) { 791 InitLogging(argv, Runtime::Abort); 792 MemMap::Init(); 793 const bool debug = kIsDebugBuild; 794 orig_argc = argc; 795 orig_argv = argv; 796 TimingLogger timings("patcher", false, false); 797 798 // Skip over the command name. 799 argv++; 800 argc--; 801 802 if (argc == 0) { 803 Usage("No arguments specified"); 804 } 805 806 timings.StartTiming("Patchoat"); 807 808 // cmd line args 809 bool isa_set = false; 810 InstructionSet isa = kNone; 811 std::string input_image_location; 812 std::string output_image_filename; 813 off_t base_delta = 0; 814 bool base_delta_set = false; 815 bool dump_timings = kIsDebugBuild; 816 817 for (int i = 0; i < argc; ++i) { 818 const StringPiece option(argv[i]); 819 const bool log_options = false; 820 if (log_options) { 821 LOG(INFO) << "patchoat: option[" << i << "]=" << argv[i]; 822 } 823 if (option.starts_with("--instruction-set=")) { 824 isa_set = true; 825 const char* isa_str = option.substr(strlen("--instruction-set=")).data(); 826 isa = GetInstructionSetFromString(isa_str); 827 if (isa == kNone) { 828 Usage("Unknown or invalid instruction set %s", isa_str); 829 } 830 } else if (option.starts_with("--input-image-location=")) { 831 input_image_location = option.substr(strlen("--input-image-location=")).data(); 832 } else if (option.starts_with("--output-image-file=")) { 833 output_image_filename = option.substr(strlen("--output-image-file=")).data(); 834 } else if (option.starts_with("--base-offset-delta=")) { 835 const char* base_delta_str = option.substr(strlen("--base-offset-delta=")).data(); 836 base_delta_set = true; 837 if (!ParseInt(base_delta_str, &base_delta)) { 838 Usage("Failed to parse --base-offset-delta argument '%s' as an off_t", base_delta_str); 839 } 840 } else if (option == "--dump-timings") { 841 dump_timings = true; 842 } else if (option == "--no-dump-timings") { 843 dump_timings = false; 844 } else { 845 Usage("Unknown argument %s", option.data()); 846 } 847 } 848 849 // The instruction set is mandatory. This simplifies things... 850 if (!isa_set) { 851 Usage("Instruction set must be set."); 852 } 853 854 int ret = patchoat_image(timings, 855 isa, 856 input_image_location, 857 output_image_filename, 858 base_delta, 859 base_delta_set, 860 debug); 861 862 timings.EndTiming(); 863 if (dump_timings) { 864 LOG(INFO) << Dumpable<TimingLogger>(timings); 865 } 866 867 return ret; 868} 869 870} // namespace art 871 872int main(int argc, char **argv) { 873 return art::patchoat(argc, argv); 874} 875