image_writer.cc revision 468532ea115657709bc32ee498e701a4c71762d4
1/* 2 * Copyright (C) 2011 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 17#include "image_writer.h" 18 19#include <sys/stat.h> 20 21#include <vector> 22 23#include "base/logging.h" 24#include "base/unix_file/fd_file.h" 25#include "class_linker.h" 26#include "compiled_method.h" 27#include "dex_file-inl.h" 28#include "driver/compiler_driver.h" 29#include "elf_writer.h" 30#include "gc/accounting/card_table-inl.h" 31#include "gc/accounting/heap_bitmap.h" 32#include "gc/heap.h" 33#include "gc/space/large_object_space.h" 34#include "gc/space/space-inl.h" 35#include "globals.h" 36#include "image.h" 37#include "intern_table.h" 38#include "mirror/array-inl.h" 39#include "mirror/class-inl.h" 40#include "mirror/class_loader.h" 41#include "mirror/dex_cache-inl.h" 42#include "mirror/field-inl.h" 43#include "mirror/abstract_method-inl.h" 44#include "mirror/object-inl.h" 45#include "mirror/object_array-inl.h" 46#include "oat.h" 47#include "oat_file.h" 48#include "object_utils.h" 49#include "runtime.h" 50#include "scoped_thread_state_change.h" 51#include "sirt_ref.h" 52#include "UniquePtr.h" 53#include "utils.h" 54 55using ::art::mirror::AbstractMethod; 56using ::art::mirror::Class; 57using ::art::mirror::DexCache; 58using ::art::mirror::EntryPointFromInterpreter; 59using ::art::mirror::Field; 60using ::art::mirror::Object; 61using ::art::mirror::ObjectArray; 62using ::art::mirror::String; 63 64namespace art { 65 66bool ImageWriter::Write(const std::string& image_filename, 67 uintptr_t image_begin, 68 const std::string& oat_filename, 69 const std::string& oat_location) { 70 CHECK(!image_filename.empty()); 71 72 CHECK_NE(image_begin, 0U); 73 image_begin_ = reinterpret_cast<byte*>(image_begin); 74 75 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 76 const std::vector<DexCache*>& all_dex_caches = class_linker->GetDexCaches(); 77 for (size_t i = 0; i < all_dex_caches.size(); i++) { 78 DexCache* dex_cache = all_dex_caches[i]; 79 dex_caches_.insert(dex_cache); 80 } 81 82 UniquePtr<File> oat_file(OS::OpenFile(oat_filename.c_str(), true, false)); 83 if (oat_file.get() == NULL) { 84 LOG(ERROR) << "Failed to open oat file " << oat_filename << " for " << oat_location; 85 return false; 86 } 87 oat_file_ = OatFile::OpenWritable(oat_file.get(), oat_location); 88 if (oat_file_ == NULL) { 89 LOG(ERROR) << "Failed to open writable oat file " << oat_filename << " for " << oat_location; 90 return false; 91 } 92 class_linker->RegisterOatFile(*oat_file_); 93 94 interpreter_to_interpreter_bridge_offset_ = 95 oat_file_->GetOatHeader().GetInterpreterToInterpreterBridgeOffset(); 96 interpreter_to_compiled_code_bridge_offset_ = 97 oat_file_->GetOatHeader().GetInterpreterToCompiledCodeBridgeOffset(); 98 99 jni_dlsym_lookup_offset_ = oat_file_->GetOatHeader().GetJniDlsymLookupOffset(); 100 101 portable_resolution_trampoline_offset_ = 102 oat_file_->GetOatHeader().GetPortableResolutionTrampolineOffset(); 103 portable_to_interpreter_bridge_offset_ = 104 oat_file_->GetOatHeader().GetPortableToInterpreterBridgeOffset(); 105 106 quick_resolution_trampoline_offset_ = 107 oat_file_->GetOatHeader().GetQuickResolutionTrampolineOffset(); 108 quick_to_interpreter_bridge_offset_ = 109 oat_file_->GetOatHeader().GetQuickToInterpreterBridgeOffset(); 110 { 111 Thread::Current()->TransitionFromSuspendedToRunnable(); 112 PruneNonImageClasses(); // Remove junk 113 ComputeLazyFieldsForImageClasses(); // Add useful information 114 ComputeEagerResolvedStrings(); 115 Thread::Current()->TransitionFromRunnableToSuspended(kNative); 116 } 117 gc::Heap* heap = Runtime::Current()->GetHeap(); 118 heap->CollectGarbage(false); // Remove garbage. 119 // Trim size of alloc spaces. 120 const std::vector<gc::space::ContinuousSpace*>& spaces = heap->GetContinuousSpaces(); 121 // TODO: C++0x auto 122 typedef std::vector<gc::space::ContinuousSpace*>::const_iterator It; 123 for (It it = spaces.begin(), end = spaces.end(); it != end; ++it) { 124 gc::space::ContinuousSpace* space = *it; 125 if (space->IsDlMallocSpace()) { 126 space->AsDlMallocSpace()->Trim(); 127 } 128 } 129 130 if (!AllocMemory()) { 131 return false; 132 } 133#ifndef NDEBUG 134 { // NOLINT(whitespace/braces) 135 ScopedObjectAccess soa(Thread::Current()); 136 CheckNonImageClassesRemoved(); 137 } 138#endif 139 Thread::Current()->TransitionFromSuspendedToRunnable(); 140 size_t oat_loaded_size = 0; 141 size_t oat_data_offset = 0; 142 ElfWriter::GetOatElfInformation(oat_file.get(), oat_loaded_size, oat_data_offset); 143 CalculateNewObjectOffsets(oat_loaded_size, oat_data_offset); 144 CopyAndFixupObjects(); 145 PatchOatCodeAndMethods(); 146 Thread::Current()->TransitionFromRunnableToSuspended(kNative); 147 148 UniquePtr<File> image_file(OS::OpenFile(image_filename.c_str(), true)); 149 if (image_file.get() == NULL) { 150 LOG(ERROR) << "Failed to open image file " << image_filename; 151 return false; 152 } 153 if (fchmod(image_file->Fd(), 0644) != 0) { 154 PLOG(ERROR) << "Failed to make image file world readable: " << image_filename; 155 return EXIT_FAILURE; 156 } 157 bool success = image_file->WriteFully(image_->Begin(), image_end_); 158 if (!success) { 159 PLOG(ERROR) << "Failed to write image file " << image_filename; 160 return false; 161 } 162 return true; 163} 164 165bool ImageWriter::AllocMemory() { 166 gc::Heap* heap = Runtime::Current()->GetHeap(); 167 const std::vector<gc::space::ContinuousSpace*>& spaces = heap->GetContinuousSpaces(); 168 size_t size = 0; 169 // TODO: C++0x auto 170 typedef std::vector<gc::space::ContinuousSpace*>::const_iterator It; 171 for (It it = spaces.begin(), end = spaces.end(); it != end; ++it) { 172 gc::space::ContinuousSpace* space = *it; 173 if (space->IsDlMallocSpace()) { 174 size += space->Size(); 175 } 176 } 177 178 int prot = PROT_READ | PROT_WRITE; 179 size_t length = RoundUp(size, kPageSize); 180 image_.reset(MemMap::MapAnonymous("image writer image", NULL, length, prot)); 181 if (image_.get() == NULL) { 182 LOG(ERROR) << "Failed to allocate memory for image file generation"; 183 return false; 184 } 185 return true; 186} 187 188void ImageWriter::ComputeLazyFieldsForImageClasses() { 189 Runtime* runtime = Runtime::Current(); 190 ClassLinker* class_linker = runtime->GetClassLinker(); 191 class_linker->VisitClassesWithoutClassesLock(ComputeLazyFieldsForClassesVisitor, NULL); 192} 193 194bool ImageWriter::ComputeLazyFieldsForClassesVisitor(Class* c, void* /*arg*/) { 195 c->ComputeName(); 196 return true; 197} 198 199void ImageWriter::ComputeEagerResolvedStringsCallback(Object* obj, void* arg) { 200 if (!obj->GetClass()->IsStringClass()) { 201 return; 202 } 203 String* string = obj->AsString(); 204 const uint16_t* utf16_string = string->GetCharArray()->GetData() + string->GetOffset(); 205 ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg); 206 typedef Set::const_iterator CacheIt; // TODO: C++0x auto 207 for (CacheIt it = writer->dex_caches_.begin(), end = writer->dex_caches_.end(); it != end; ++it) { 208 DexCache* dex_cache = *it; 209 const DexFile& dex_file = *dex_cache->GetDexFile(); 210 const DexFile::StringId* string_id = dex_file.FindStringId(utf16_string); 211 if (string_id != NULL) { 212 // This string occurs in this dex file, assign the dex cache entry. 213 uint32_t string_idx = dex_file.GetIndexForStringId(*string_id); 214 if (dex_cache->GetResolvedString(string_idx) == NULL) { 215 dex_cache->SetResolvedString(string_idx, string); 216 } 217 } 218 } 219} 220 221void ImageWriter::ComputeEagerResolvedStrings() 222 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 223 // TODO: Check image spaces only? 224 gc::Heap* heap = Runtime::Current()->GetHeap(); 225 WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); 226 heap->FlushAllocStack(); 227 heap->GetLiveBitmap()->Walk(ComputeEagerResolvedStringsCallback, this); 228} 229 230bool ImageWriter::IsImageClass(const Class* klass) { 231 return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptor()); 232} 233 234struct NonImageClasses { 235 ImageWriter* image_writer; 236 std::set<std::string>* non_image_classes; 237}; 238 239void ImageWriter::PruneNonImageClasses() { 240 if (compiler_driver_.GetImageClasses() == NULL) { 241 return; 242 } 243 Runtime* runtime = Runtime::Current(); 244 ClassLinker* class_linker = runtime->GetClassLinker(); 245 246 // Make a list of classes we would like to prune. 247 std::set<std::string> non_image_classes; 248 NonImageClasses context; 249 context.image_writer = this; 250 context.non_image_classes = &non_image_classes; 251 class_linker->VisitClasses(NonImageClassesVisitor, &context); 252 253 // Remove the undesired classes from the class roots. 254 typedef std::set<std::string>::const_iterator ClassIt; // TODO: C++0x auto 255 for (ClassIt it = non_image_classes.begin(), end = non_image_classes.end(); it != end; ++it) { 256 class_linker->RemoveClass((*it).c_str(), NULL); 257 } 258 259 // Clear references to removed classes from the DexCaches. 260 AbstractMethod* resolution_method = runtime->GetResolutionMethod(); 261 typedef Set::const_iterator CacheIt; // TODO: C++0x auto 262 for (CacheIt it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it) { 263 DexCache* dex_cache = *it; 264 for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) { 265 Class* klass = dex_cache->GetResolvedType(i); 266 if (klass != NULL && !IsImageClass(klass)) { 267 dex_cache->SetResolvedType(i, NULL); 268 dex_cache->GetInitializedStaticStorage()->Set(i, NULL); 269 } 270 } 271 for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) { 272 AbstractMethod* method = dex_cache->GetResolvedMethod(i); 273 if (method != NULL && !IsImageClass(method->GetDeclaringClass())) { 274 dex_cache->SetResolvedMethod(i, resolution_method); 275 } 276 } 277 for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) { 278 Field* field = dex_cache->GetResolvedField(i); 279 if (field != NULL && !IsImageClass(field->GetDeclaringClass())) { 280 dex_cache->SetResolvedField(i, NULL); 281 } 282 } 283 } 284} 285 286bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) { 287 NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg); 288 if (!context->image_writer->IsImageClass(klass)) { 289 context->non_image_classes->insert(ClassHelper(klass).GetDescriptor()); 290 } 291 return true; 292} 293 294void ImageWriter::CheckNonImageClassesRemoved() 295 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 296 if (compiler_driver_.GetImageClasses() == NULL) { 297 return; 298 } 299 300 gc::Heap* heap = Runtime::Current()->GetHeap(); 301 Thread* self = Thread::Current(); 302 { 303 WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); 304 heap->FlushAllocStack(); 305 } 306 307 ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); 308 heap->GetLiveBitmap()->Walk(CheckNonImageClassesRemovedCallback, this); 309} 310 311void ImageWriter::CheckNonImageClassesRemovedCallback(Object* obj, void* arg) { 312 ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); 313 if (!obj->IsClass()) { 314 return; 315 } 316 Class* klass = obj->AsClass(); 317 if (!image_writer->IsImageClass(klass)) { 318 image_writer->DumpImageClasses(); 319 CHECK(image_writer->IsImageClass(klass)) << ClassHelper(klass).GetDescriptor() 320 << " " << PrettyDescriptor(klass); 321 } 322} 323 324void ImageWriter::DumpImageClasses() { 325 CompilerDriver::DescriptorSet* image_classes = compiler_driver_.GetImageClasses(); 326 CHECK(image_classes != NULL); 327 typedef std::set<std::string>::const_iterator It; // TODO: C++0x auto 328 for (It it = image_classes->begin(), end = image_classes->end(); it != end; ++it) { 329 LOG(INFO) << " " << *it; 330 } 331} 332 333void ImageWriter::CalculateNewObjectOffsetsCallback(Object* obj, void* arg) { 334 DCHECK(obj != NULL); 335 DCHECK(arg != NULL); 336 ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); 337 338 // if it is a string, we want to intern it if its not interned. 339 if (obj->GetClass()->IsStringClass()) { 340 // we must be an interned string that was forward referenced and already assigned 341 if (image_writer->IsImageOffsetAssigned(obj)) { 342 DCHECK_EQ(obj, obj->AsString()->Intern()); 343 return; 344 } 345 SirtRef<String> interned(Thread::Current(), obj->AsString()->Intern()); 346 if (obj != interned.get()) { 347 if (!image_writer->IsImageOffsetAssigned(interned.get())) { 348 // interned obj is after us, allocate its location early 349 image_writer->AssignImageOffset(interned.get()); 350 } 351 // point those looking for this object to the interned version. 352 image_writer->SetImageOffset(obj, image_writer->GetImageOffset(interned.get())); 353 return; 354 } 355 // else (obj == interned), nothing to do but fall through to the normal case 356 } 357 358 image_writer->AssignImageOffset(obj); 359} 360 361ObjectArray<Object>* ImageWriter::CreateImageRoots() const { 362 Runtime* runtime = Runtime::Current(); 363 ClassLinker* class_linker = runtime->GetClassLinker(); 364 Class* object_array_class = class_linker->FindSystemClass("[Ljava/lang/Object;"); 365 Thread* self = Thread::Current(); 366 367 // build an Object[] of all the DexCaches used in the source_space_ 368 ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(self, object_array_class, 369 dex_caches_.size()); 370 int i = 0; 371 typedef Set::const_iterator It; // TODO: C++0x auto 372 for (It it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it, ++i) { 373 dex_caches->Set(i, *it); 374 } 375 376 // build an Object[] of the roots needed to restore the runtime 377 SirtRef<ObjectArray<Object> > 378 image_roots(self, 379 ObjectArray<Object>::Alloc(self, object_array_class, 380 ImageHeader::kImageRootsMax)); 381 image_roots->Set(ImageHeader::kResolutionMethod, runtime->GetResolutionMethod()); 382 image_roots->Set(ImageHeader::kCalleeSaveMethod, 383 runtime->GetCalleeSaveMethod(Runtime::kSaveAll)); 384 image_roots->Set(ImageHeader::kRefsOnlySaveMethod, 385 runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)); 386 image_roots->Set(ImageHeader::kRefsAndArgsSaveMethod, 387 runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)); 388 image_roots->Set(ImageHeader::kOatLocation, 389 String::AllocFromModifiedUtf8(self, oat_file_->GetLocation().c_str())); 390 image_roots->Set(ImageHeader::kDexCaches, 391 dex_caches); 392 image_roots->Set(ImageHeader::kClassRoots, 393 class_linker->GetClassRoots()); 394 for (int i = 0; i < ImageHeader::kImageRootsMax; i++) { 395 CHECK(image_roots->Get(i) != NULL); 396 } 397 return image_roots.get(); 398} 399 400void ImageWriter::CalculateNewObjectOffsets(size_t oat_loaded_size, size_t oat_data_offset) { 401 CHECK_NE(0U, oat_loaded_size); 402 Thread* self = Thread::Current(); 403 SirtRef<ObjectArray<Object> > image_roots(self, CreateImageRoots()); 404 405 gc::Heap* heap = Runtime::Current()->GetHeap(); 406 const std::vector<gc::space::ContinuousSpace*>& spaces = heap->GetContinuousSpaces(); 407 DCHECK(!spaces.empty()); 408 DCHECK_EQ(0U, image_end_); 409 410 // leave space for the header, but do not write it yet, we need to 411 // know where image_roots is going to end up 412 image_end_ += RoundUp(sizeof(ImageHeader), 8); // 64-bit-alignment 413 414 { 415 WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); 416 heap->FlushAllocStack(); 417 // TODO: Image spaces only? 418 // TODO: Add InOrderWalk to heap bitmap. 419 const char* old = self->StartAssertNoThreadSuspension("ImageWriter"); 420 DCHECK(heap->GetLargeObjectsSpace()->GetLiveObjects()->IsEmpty()); 421 // TODO: C++0x auto 422 typedef std::vector<gc::space::ContinuousSpace*>::const_iterator It; 423 for (It it = spaces.begin(), end = spaces.end(); it != end; ++it) { 424 gc::space::ContinuousSpace* space = *it; 425 space->GetLiveBitmap()->InOrderWalk(CalculateNewObjectOffsetsCallback, this); 426 DCHECK_LT(image_end_, image_->Size()); 427 } 428 self->EndAssertNoThreadSuspension(old); 429 } 430 431 const byte* oat_file_begin = image_begin_ + RoundUp(image_end_, kPageSize); 432 const byte* oat_file_end = oat_file_begin + oat_loaded_size; 433 oat_data_begin_ = oat_file_begin + oat_data_offset; 434 const byte* oat_data_end = oat_data_begin_ + oat_file_->Size(); 435 436 // return to write header at start of image with future location of image_roots 437 ImageHeader image_header(reinterpret_cast<uint32_t>(image_begin_), 438 reinterpret_cast<uint32_t>(GetImageAddress(image_roots.get())), 439 oat_file_->GetOatHeader().GetChecksum(), 440 reinterpret_cast<uint32_t>(oat_file_begin), 441 reinterpret_cast<uint32_t>(oat_data_begin_), 442 reinterpret_cast<uint32_t>(oat_data_end), 443 reinterpret_cast<uint32_t>(oat_file_end)); 444 memcpy(image_->Begin(), &image_header, sizeof(image_header)); 445 446 // Note that image_end_ is left at end of used space 447} 448 449void ImageWriter::CopyAndFixupObjects() 450 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 451 Thread* self = Thread::Current(); 452 const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter"); 453 gc::Heap* heap = Runtime::Current()->GetHeap(); 454 // TODO: heap validation can't handle this fix up pass 455 heap->DisableObjectValidation(); 456 // TODO: Image spaces only? 457 WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); 458 heap->FlushAllocStack(); 459 heap->GetLiveBitmap()->Walk(CopyAndFixupObjectsCallback, this); 460 self->EndAssertNoThreadSuspension(old_cause); 461} 462 463void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void* arg) { 464 DCHECK(object != NULL); 465 DCHECK(arg != NULL); 466 const Object* obj = object; 467 ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); 468 469 // see GetLocalAddress for similar computation 470 size_t offset = image_writer->GetImageOffset(obj); 471 byte* dst = image_writer->image_->Begin() + offset; 472 const byte* src = reinterpret_cast<const byte*>(obj); 473 size_t n = obj->SizeOf(); 474 DCHECK_LT(offset + n, image_writer->image_->Size()); 475 memcpy(dst, src, n); 476 Object* copy = reinterpret_cast<Object*>(dst); 477 copy->SetField32(Object::MonitorOffset(), 0, false); // We may have inflated the lock during compilation. 478 image_writer->FixupObject(obj, copy); 479} 480 481void ImageWriter::FixupObject(const Object* orig, Object* copy) { 482 DCHECK(orig != NULL); 483 DCHECK(copy != NULL); 484 copy->SetClass(down_cast<Class*>(GetImageAddress(orig->GetClass()))); 485 // TODO: special case init of pointers to malloc data (or removal of these pointers) 486 if (orig->IsClass()) { 487 FixupClass(orig->AsClass(), down_cast<Class*>(copy)); 488 } else if (orig->IsObjectArray()) { 489 FixupObjectArray(orig->AsObjectArray<Object>(), down_cast<ObjectArray<Object>*>(copy)); 490 } else if (orig->IsMethod()) { 491 FixupMethod(orig->AsMethod(), down_cast<AbstractMethod*>(copy)); 492 } else { 493 FixupInstanceFields(orig, copy); 494 } 495} 496 497void ImageWriter::FixupClass(const Class* orig, Class* copy) { 498 FixupInstanceFields(orig, copy); 499 FixupStaticFields(orig, copy); 500} 501 502void ImageWriter::FixupMethod(const AbstractMethod* orig, AbstractMethod* copy) { 503 FixupInstanceFields(orig, copy); 504 505 // OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to 506 // oat_begin_ 507 508 // The resolution method has a special trampoline to call. 509 if (UNLIKELY(orig == Runtime::Current()->GetResolutionMethod())) { 510#if defined(ART_USE_PORTABLE_COMPILER) 511 copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_resolution_trampoline_offset_)); 512#else 513 copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_resolution_trampoline_offset_)); 514#endif 515 } else { 516 // We assume all methods have code. If they don't currently then we set them to the use the 517 // resolution trampoline. Abstract methods never have code and so we need to make sure their 518 // use results in an AbstractMethodError. We use the interpreter to achieve this. 519 if (UNLIKELY(orig->IsAbstract())) { 520#if defined(ART_USE_PORTABLE_COMPILER) 521 copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_to_interpreter_bridge_offset_)); 522#else 523 copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_to_interpreter_bridge_offset_)); 524#endif 525 copy->SetEntryPointFromInterpreter(reinterpret_cast<EntryPointFromInterpreter*> 526 (GetOatAddress(interpreter_to_interpreter_bridge_offset_))); 527 } else { 528 copy->SetEntryPointFromInterpreter(reinterpret_cast<EntryPointFromInterpreter*> 529 (GetOatAddress(interpreter_to_compiled_code_bridge_offset_))); 530 // Use original code if it exists. Otherwise, set the code pointer to the resolution 531 // trampoline. 532 const byte* code = GetOatAddress(orig->GetOatCodeOffset()); 533 if (code != NULL) { 534 copy->SetEntryPointFromCompiledCode(code); 535 } else { 536#if defined(ART_USE_PORTABLE_COMPILER) 537 copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_resolution_trampoline_offset_)); 538#else 539 copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_resolution_trampoline_offset_)); 540#endif 541 } 542 if (orig->IsNative()) { 543 // The native method's pointer is set to a stub to lookup via dlsym. 544 // Note this is not the code_ pointer, that is handled above. 545 copy->SetNativeMethod(GetOatAddress(jni_dlsym_lookup_offset_)); 546 } else { 547 // Normal (non-abstract non-native) methods have various tables to relocate. 548 uint32_t mapping_table_off = orig->GetOatMappingTableOffset(); 549 const byte* mapping_table = GetOatAddress(mapping_table_off); 550 copy->SetMappingTable(reinterpret_cast<const uint32_t*>(mapping_table)); 551 552 uint32_t vmap_table_offset = orig->GetOatVmapTableOffset(); 553 const byte* vmap_table = GetOatAddress(vmap_table_offset); 554 copy->SetVmapTable(reinterpret_cast<const uint16_t*>(vmap_table)); 555 556 uint32_t native_gc_map_offset = orig->GetOatNativeGcMapOffset(); 557 const byte* native_gc_map = GetOatAddress(native_gc_map_offset); 558 copy->SetNativeGcMap(reinterpret_cast<const uint8_t*>(native_gc_map)); 559 } 560 } 561 } 562} 563 564void ImageWriter::FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy) { 565 for (int32_t i = 0; i < orig->GetLength(); ++i) { 566 const Object* element = orig->Get(i); 567 copy->SetPtrWithoutChecks(i, GetImageAddress(element)); 568 } 569} 570 571void ImageWriter::FixupInstanceFields(const Object* orig, Object* copy) { 572 DCHECK(orig != NULL); 573 DCHECK(copy != NULL); 574 Class* klass = orig->GetClass(); 575 DCHECK(klass != NULL); 576 FixupFields(orig, 577 copy, 578 klass->GetReferenceInstanceOffsets(), 579 false); 580} 581 582void ImageWriter::FixupStaticFields(const Class* orig, Class* copy) { 583 DCHECK(orig != NULL); 584 DCHECK(copy != NULL); 585 FixupFields(orig, 586 copy, 587 orig->GetReferenceStaticOffsets(), 588 true); 589} 590 591void ImageWriter::FixupFields(const Object* orig, 592 Object* copy, 593 uint32_t ref_offsets, 594 bool is_static) { 595 if (ref_offsets != CLASS_WALK_SUPER) { 596 // Found a reference offset bitmap. Fixup the specified offsets. 597 while (ref_offsets != 0) { 598 size_t right_shift = CLZ(ref_offsets); 599 MemberOffset byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift); 600 const Object* ref = orig->GetFieldObject<const Object*>(byte_offset, false); 601 // Use SetFieldPtr to avoid card marking since we are writing to the image. 602 copy->SetFieldPtr(byte_offset, GetImageAddress(ref), false); 603 ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift); 604 } 605 } else { 606 // There is no reference offset bitmap. In the non-static case, 607 // walk up the class inheritance hierarchy and find reference 608 // offsets the hard way. In the static case, just consider this 609 // class. 610 for (const Class *klass = is_static ? orig->AsClass() : orig->GetClass(); 611 klass != NULL; 612 klass = is_static ? NULL : klass->GetSuperClass()) { 613 size_t num_reference_fields = (is_static 614 ? klass->NumReferenceStaticFields() 615 : klass->NumReferenceInstanceFields()); 616 for (size_t i = 0; i < num_reference_fields; ++i) { 617 Field* field = (is_static 618 ? klass->GetStaticField(i) 619 : klass->GetInstanceField(i)); 620 MemberOffset field_offset = field->GetOffset(); 621 const Object* ref = orig->GetFieldObject<const Object*>(field_offset, false); 622 // Use SetFieldPtr to avoid card marking since we are writing to the image. 623 copy->SetFieldPtr(field_offset, GetImageAddress(ref), false); 624 } 625 } 626 } 627 if (!is_static && orig->IsReferenceInstance()) { 628 // Fix-up referent, that isn't marked as an object field, for References. 629 Field* field = orig->GetClass()->FindInstanceField("referent", "Ljava/lang/Object;"); 630 MemberOffset field_offset = field->GetOffset(); 631 const Object* ref = orig->GetFieldObject<const Object*>(field_offset, false); 632 // Use SetFieldPtr to avoid card marking since we are writing to the image. 633 copy->SetFieldPtr(field_offset, GetImageAddress(ref), false); 634 } 635} 636 637static AbstractMethod* GetTargetMethod(const CompilerDriver::PatchInformation* patch) 638 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 639 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 640 DexCache* dex_cache = class_linker->FindDexCache(patch->GetDexFile()); 641 AbstractMethod* method = class_linker->ResolveMethod(patch->GetDexFile(), 642 patch->GetTargetMethodIdx(), 643 dex_cache, 644 NULL, 645 NULL, 646 patch->GetTargetInvokeType()); 647 CHECK(method != NULL) 648 << patch->GetDexFile().GetLocation() << " " << patch->GetTargetMethodIdx(); 649 CHECK(!method->IsRuntimeMethod()) 650 << patch->GetDexFile().GetLocation() << " " << patch->GetTargetMethodIdx(); 651 CHECK(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx()) == method) 652 << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx() << " " 653 << PrettyMethod(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx())) << " " 654 << PrettyMethod(method); 655 return method; 656} 657 658void ImageWriter::PatchOatCodeAndMethods() { 659 Thread* self = Thread::Current(); 660 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 661 const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter"); 662 663 typedef std::vector<const CompilerDriver::PatchInformation*> Patches; 664 const Patches& code_to_patch = compiler_driver_.GetCodeToPatch(); 665 for (size_t i = 0; i < code_to_patch.size(); i++) { 666 const CompilerDriver::PatchInformation* patch = code_to_patch[i]; 667 AbstractMethod* target = GetTargetMethod(patch); 668 uint32_t code = reinterpret_cast<uint32_t>(class_linker->GetOatCodeFor(target)); 669 uint32_t code_base = reinterpret_cast<uint32_t>(&oat_file_->GetOatHeader()); 670 uint32_t code_offset = code - code_base; 671 SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetOatAddress(code_offset))); 672 } 673 674 const Patches& methods_to_patch = compiler_driver_.GetMethodsToPatch(); 675 for (size_t i = 0; i < methods_to_patch.size(); i++) { 676 const CompilerDriver::PatchInformation* patch = methods_to_patch[i]; 677 AbstractMethod* target = GetTargetMethod(patch); 678 SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetImageAddress(target))); 679 } 680 681 // Update the image header with the new checksum after patching 682 ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); 683 image_header->SetOatChecksum(oat_file_->GetOatHeader().GetChecksum()); 684 self->EndAssertNoThreadSuspension(old_cause); 685} 686 687void ImageWriter::SetPatchLocation(const CompilerDriver::PatchInformation* patch, uint32_t value) { 688 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 689 const void* oat_code = class_linker->GetOatCodeFor(patch->GetDexFile(), 690 patch->GetReferrerMethodIdx()); 691 OatHeader& oat_header = const_cast<OatHeader&>(oat_file_->GetOatHeader()); 692 // TODO: make this Thumb2 specific 693 uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uint32_t>(oat_code) & ~0x1); 694 uint32_t* patch_location = reinterpret_cast<uint32_t*>(base + patch->GetLiteralOffset()); 695#ifndef NDEBUG 696 const DexFile::MethodId& id = patch->GetDexFile().GetMethodId(patch->GetTargetMethodIdx()); 697 uint32_t expected = reinterpret_cast<uint32_t>(&id); 698 uint32_t actual = *patch_location; 699 CHECK(actual == expected || actual == value) << std::hex 700 << "actual=" << actual 701 << "expected=" << expected 702 << "value=" << value; 703#endif 704 *patch_location = value; 705 oat_header.UpdateChecksum(patch_location, sizeof(value)); 706} 707 708} // namespace art 709