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 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 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. 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 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 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 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 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 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 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: 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 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: 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 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 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 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: 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 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 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: 499 explicit RelocatedPointerVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {} 500 501 template <typename T> 502 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 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 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 627 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 635 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. 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 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 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 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 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 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 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 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 871 int main(int argc, char **argv) { 872 return art::patchoat(argc, argv); 873 } 874