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