diff options
-rw-r--r-- | compiler/elf_writer_test.cc | 2 | ||||
-rw-r--r-- | compiler/image_writer.cc | 9 | ||||
-rw-r--r-- | patchoat/patchoat.cc | 9 | ||||
-rw-r--r-- | runtime/base/hash_set.h | 2 | ||||
-rw-r--r-- | runtime/class_linker.cc | 273 | ||||
-rw-r--r-- | runtime/class_linker.h | 16 | ||||
-rw-r--r-- | runtime/elf_file.cc | 277 | ||||
-rw-r--r-- | runtime/elf_file.h | 4 | ||||
-rw-r--r-- | runtime/elf_file_impl.h | 16 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_dexcache_entrypoints.cc | 4 | ||||
-rw-r--r-- | runtime/intern_table.cc | 59 | ||||
-rw-r--r-- | runtime/intern_table.h | 3 | ||||
-rw-r--r-- | runtime/oat_file.cc | 2 | ||||
-rw-r--r-- | runtime/runtime.cc | 6 |
14 files changed, 212 insertions, 470 deletions
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc index b58004976e..6f48779258 100644 --- a/compiler/elf_writer_test.cc +++ b/compiler/elf_writer_test.cc @@ -94,7 +94,7 @@ TEST_F(ElfWriterTest, dlsym) { /*low_4gb*/false, &error_msg)); CHECK(ef.get() != nullptr) << error_msg; - CHECK(ef->Load(false, /*low_4gb*/false, &error_msg)) << error_msg; + CHECK(ef->Load(file.get(), false, /*low_4gb*/false, &error_msg)) << error_msg; EXPECT_EQ(dl_oatdata, ef->FindDynamicSymbolAddress("oatdata")); EXPECT_EQ(dl_oatexec, ef->FindDynamicSymbolAddress("oatexec")); EXPECT_EQ(dl_oatlastword, ef->FindDynamicSymbolAddress("oatlastword")); diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 13c73dcf42..83c7332151 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -1492,10 +1492,15 @@ void ImageWriter::CalculateNewObjectOffsets() { // Calculate how big the intern table will be after being serialized. InternTable* const intern_table = image_info.intern_table_.get(); CHECK_EQ(intern_table->WeakSize(), 0u) << " should have strong interned all the strings"; - image_info.intern_table_bytes_ = intern_table->WriteToMemory(nullptr); + if (intern_table->StrongSize() != 0u) { + image_info.intern_table_bytes_ = intern_table->WriteToMemory(nullptr); + } // Calculate the size of the class table. ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); - image_info.class_table_bytes_ += image_info.class_table_->WriteToMemory(nullptr); + DCHECK_EQ(image_info.class_table_->NumZygoteClasses(), 0u); + if (image_info.class_table_->NumNonZygoteClasses() != 0u) { + image_info.class_table_bytes_ += image_info.class_table_->WriteToMemory(nullptr); + } } // Calculate bin slot offsets. diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index f3eb663cb8..c79bf92866 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -442,7 +442,7 @@ PatchOat::MaybePic PatchOat::IsOatPic(const ElfFile* oat_in) { return ERROR_OAT_FILE; } - const std::string& file_path = oat_in->GetFile().GetPath(); + const std::string& file_path = oat_in->GetFilePath(); const OatHeader* oat_header = GetOatHeader(oat_in); if (oat_header == nullptr) { @@ -846,7 +846,7 @@ bool PatchOat::PatchOatHeader(ElfFileImpl* oat_file) { } OatHeader* oat_header = reinterpret_cast<OatHeader*>(oat_file->Begin() + rodata_sec->sh_offset); if (!oat_header->IsValid()) { - LOG(ERROR) << "Elf file " << oat_file->GetFile().GetPath() << " has an invalid oat header"; + LOG(ERROR) << "Elf file " << oat_file->GetFilePath() << " has an invalid oat header"; return false; } oat_header->RelocateOat(delta_); @@ -854,10 +854,11 @@ bool PatchOat::PatchOatHeader(ElfFileImpl* oat_file) { } bool PatchOat::PatchElf() { - if (oat_file_->Is64Bit()) + if (oat_file_->Is64Bit()) { return PatchElf<ElfFileImpl64>(oat_file_->GetImpl64()); - else + } else { return PatchElf<ElfFileImpl32>(oat_file_->GetImpl32()); + } } template <typename ElfFileImpl> diff --git a/runtime/base/hash_set.h b/runtime/base/hash_set.h index 12d3be75d1..f24a8625b4 100644 --- a/runtime/base/hash_set.h +++ b/runtime/base/hash_set.h @@ -296,7 +296,7 @@ class HashSet { return const_iterator(this, NumBuckets()); } - bool Empty() { + bool Empty() const { return Size() == 0; } diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index eb2316b0c2..239cdaea69 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -316,7 +316,6 @@ static void ShuffleForward(size_t* current_field_idx, ClassLinker::ClassLinker(InternTable* intern_table) // dex_lock_ is recursive as it may be used in stack dumping. : dex_lock_("ClassLinker dex lock", kDexLock), - dex_cache_boot_image_class_lookup_required_(false), failed_dex_cache_class_lookups_(0), class_roots_(nullptr), array_iftable_(nullptr), @@ -969,7 +968,6 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) { return false; } } - dex_cache_boot_image_class_lookup_required_ = true; std::vector<const OatFile*> oat_files = runtime->GetOatFileManager().RegisterImageOatFiles(spaces); DCHECK(!oat_files.empty()); @@ -1256,7 +1254,6 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches( // Add image classes into the class table for the class loader, and fixup the dex caches and // class loader fields. WriterMutexLock mu(self, *Locks::classlinker_classes_lock_); - ClassTable* table = InsertClassTableForClassLoader(class_loader.Get()); // Dex cache array fixup is all or nothing, we must reject app images that have mixed since we // rely on clobering the dex cache arrays in the image to forward to bss. size_t num_dex_caches_with_bss_arrays = 0; @@ -1392,103 +1389,42 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches( StackHandleScope<1> hs3(self); RegisterDexFileLocked(*dex_file, hs3.NewHandle(dex_cache)); } - GcRoot<mirror::Class>* const types = dex_cache->GetResolvedTypes(); - const size_t num_types = dex_cache->NumResolvedTypes(); - if (new_class_set == nullptr) { - for (int32_t j = 0; j < static_cast<int32_t>(num_types); j++) { - // The image space is not yet added to the heap, avoid read barriers. - mirror::Class* klass = types[j].Read(); - // There may also be boot image classes, - if (space->HasAddress(klass)) { - DCHECK_NE(klass->GetStatus(), mirror::Class::kStatusError); - // Update the class loader from the one in the image class loader to the one that loaded - // the app image. - klass->SetClassLoader(class_loader.Get()); - // The resolved type could be from another dex cache, go through the dex cache just in - // case. May be null for array classes. - if (klass->GetDexCacheStrings() != nullptr) { - DCHECK(!klass->IsArrayClass()); - klass->SetDexCacheStrings(klass->GetDexCache()->GetStrings()); - } - // If there are multiple dex caches, there may be the same class multiple times - // in different dex caches. Check for this since inserting will add duplicates - // otherwise. - if (num_dex_caches > 1) { - mirror::Class* existing = table->LookupByDescriptor(klass); - if (existing != nullptr) { - DCHECK_EQ(existing, klass) << PrettyClass(klass); - } else { - table->Insert(klass); - } - } else { - table->Insert(klass); - } - // Double checked VLOG to avoid overhead. - if (VLOG_IS_ON(image)) { - VLOG(image) << PrettyClass(klass) << " " << klass->GetStatus(); - if (!klass->IsArrayClass()) { - VLOG(image) << "From " << klass->GetDexCache()->GetDexFile()->GetBaseLocation(); - } - VLOG(image) << "Direct methods"; - for (ArtMethod& m : klass->GetDirectMethods(kRuntimePointerSize)) { - VLOG(image) << PrettyMethod(&m); - } - VLOG(image) << "Virtual methods"; - for (ArtMethod& m : klass->GetVirtualMethods(kRuntimePointerSize)) { - VLOG(image) << PrettyMethod(&m); - } - } - } else { - DCHECK(klass == nullptr || heap->ObjectIsInBootImageSpace(klass)) - << klass << " " << PrettyClass(klass); - } - } - } if (kIsDebugBuild) { + CHECK(new_class_set != nullptr); + GcRoot<mirror::Class>* const types = dex_cache->GetResolvedTypes(); + const size_t num_types = dex_cache->NumResolvedTypes(); for (int32_t j = 0; j < static_cast<int32_t>(num_types); j++) { // The image space is not yet added to the heap, avoid read barriers. mirror::Class* klass = types[j].Read(); if (space->HasAddress(klass)) { DCHECK_NE(klass->GetStatus(), mirror::Class::kStatusError); - if (kIsDebugBuild) { - if (new_class_set != nullptr) { - auto it = new_class_set->Find(GcRoot<mirror::Class>(klass)); - DCHECK(it != new_class_set->end()); - DCHECK_EQ(it->Read(), klass); - mirror::Class* super_class = klass->GetSuperClass(); - if (super_class != nullptr && !heap->ObjectIsInBootImageSpace(super_class)) { - auto it2 = new_class_set->Find(GcRoot<mirror::Class>(super_class)); - DCHECK(it2 != new_class_set->end()); - DCHECK_EQ(it2->Read(), super_class); - } - } else { - DCHECK_EQ(table->LookupByDescriptor(klass), klass); - mirror::Class* super_class = klass->GetSuperClass(); - if (super_class != nullptr && !heap->ObjectIsInBootImageSpace(super_class)) { - CHECK_EQ(table->LookupByDescriptor(super_class), super_class); - } - } + auto it = new_class_set->Find(GcRoot<mirror::Class>(klass)); + DCHECK(it != new_class_set->end()); + DCHECK_EQ(it->Read(), klass); + mirror::Class* super_class = klass->GetSuperClass(); + if (super_class != nullptr && !heap->ObjectIsInBootImageSpace(super_class)) { + auto it2 = new_class_set->Find(GcRoot<mirror::Class>(super_class)); + DCHECK(it2 != new_class_set->end()); + DCHECK_EQ(it2->Read(), super_class); } - if (kIsDebugBuild) { - for (ArtMethod& m : klass->GetDirectMethods(kRuntimePointerSize)) { - const void* code = m.GetEntryPointFromQuickCompiledCode(); - const void* oat_code = m.IsInvokable() ? GetQuickOatCodeFor(&m) : code; - if (!IsQuickResolutionStub(code) && - !IsQuickGenericJniStub(code) && - !IsQuickToInterpreterBridge(code) && - !m.IsNative()) { - DCHECK_EQ(code, oat_code) << PrettyMethod(&m); - } + for (ArtMethod& m : klass->GetDirectMethods(kRuntimePointerSize)) { + const void* code = m.GetEntryPointFromQuickCompiledCode(); + const void* oat_code = m.IsInvokable() ? GetQuickOatCodeFor(&m) : code; + if (!IsQuickResolutionStub(code) && + !IsQuickGenericJniStub(code) && + !IsQuickToInterpreterBridge(code) && + !m.IsNative()) { + DCHECK_EQ(code, oat_code) << PrettyMethod(&m); } - for (ArtMethod& m : klass->GetVirtualMethods(kRuntimePointerSize)) { - const void* code = m.GetEntryPointFromQuickCompiledCode(); - const void* oat_code = m.IsInvokable() ? GetQuickOatCodeFor(&m) : code; - if (!IsQuickResolutionStub(code) && - !IsQuickGenericJniStub(code) && - !IsQuickToInterpreterBridge(code) && - !m.IsNative()) { - DCHECK_EQ(code, oat_code) << PrettyMethod(&m); - } + } + for (ArtMethod& m : klass->GetVirtualMethods(kRuntimePointerSize)) { + const void* code = m.GetEntryPointFromQuickCompiledCode(); + const void* oat_code = m.IsInvokable() ? GetQuickOatCodeFor(&m) : code; + if (!IsQuickResolutionStub(code) && + !IsQuickGenericJniStub(code) && + !IsQuickToInterpreterBridge(code) && + !m.IsNative()) { + DCHECK_EQ(code, oat_code) << PrettyMethod(&m); } } } @@ -1805,9 +1741,6 @@ bool ClassLinker::AddImageSpace( temp_set = ClassTable::ClassSet(space->Begin() + class_table_section.Offset(), /*make copy*/false, &read_count); - if (!app_image) { - dex_cache_boot_image_class_lookup_required_ = false; - } VLOG(image) << "Adding class table classes took " << PrettyDuration(NanoTime() - start_time2); } if (app_image) { @@ -1815,7 +1748,7 @@ bool ClassLinker::AddImageSpace( if (!UpdateAppImageClassLoadersAndDexCaches(space, class_loader, dex_caches, - added_class_table ? &temp_set : nullptr, + &temp_set, /*out*/&forward_dex_cache_arrays, /*out*/error_msg)) { return false; @@ -1825,10 +1758,8 @@ bool ClassLinker::AddImageSpace( UpdateClassLoaderAndResolvedStringsVisitor visitor(space, class_loader.Get(), forward_dex_cache_arrays); - if (added_class_table) { - for (GcRoot<mirror::Class>& root : temp_set) { - visitor(root.Read()); - } + for (GcRoot<mirror::Class>& root : temp_set) { + visitor(root.Read()); } // forward_dex_cache_arrays is true iff we copied all of the dex cache arrays into the .bss. // In this case, madvise away the dex cache arrays section of the image to reduce RAM usage and @@ -1962,9 +1893,6 @@ void ClassLinker::VisitClassesInternal(ClassVisitor* visitor) { } void ClassLinker::VisitClasses(ClassVisitor* visitor) { - if (dex_cache_boot_image_class_lookup_required_) { - AddBootImageClassesToClassTable(); - } Thread* const self = Thread::Current(); ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); // Not safe to have thread suspension when we are holding a lock. @@ -3608,17 +3536,6 @@ mirror::Class* ClassLinker::InsertClass(const char* descriptor, mirror::Class* k if (existing != nullptr) { return existing; } - if (kIsDebugBuild && - !klass->IsTemp() && - class_loader == nullptr && - dex_cache_boot_image_class_lookup_required_) { - // Check a class loaded with the system class loader matches one in the image if the class - // is in the image. - existing = LookupClassFromBootImage(descriptor); - if (existing != nullptr) { - CHECK_EQ(klass, existing); - } - } VerifyObject(klass); class_table->InsertWithHash(klass, hash); if (class_loader != nullptr) { @@ -3658,90 +3575,15 @@ mirror::Class* ClassLinker::LookupClass(Thread* self, const char* descriptor, size_t hash, mirror::ClassLoader* class_loader) { - { - ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); - ClassTable* const class_table = ClassTableForClassLoader(class_loader); - if (class_table != nullptr) { - mirror::Class* result = class_table->Lookup(descriptor, hash); - if (result != nullptr) { - return result; - } - } - } - if (class_loader != nullptr || !dex_cache_boot_image_class_lookup_required_) { - return nullptr; - } - // Lookup failed but need to search dex_caches_. - mirror::Class* result = LookupClassFromBootImage(descriptor); - if (result != nullptr) { - result = InsertClass(descriptor, result, hash); - } else { - // Searching the image dex files/caches failed, we don't want to get into this situation - // often as map searches are faster, so after kMaxFailedDexCacheLookups move all image - // classes into the class table. - constexpr uint32_t kMaxFailedDexCacheLookups = 1000; - if (++failed_dex_cache_class_lookups_ > kMaxFailedDexCacheLookups) { - AddBootImageClassesToClassTable(); - } - } - return result; -} - -static std::vector<mirror::ObjectArray<mirror::DexCache>*> GetImageDexCaches( - std::vector<gc::space::ImageSpace*> image_spaces) REQUIRES_SHARED(Locks::mutator_lock_) { - CHECK(!image_spaces.empty()); - std::vector<mirror::ObjectArray<mirror::DexCache>*> dex_caches_vector; - for (gc::space::ImageSpace* image_space : image_spaces) { - mirror::Object* root = image_space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); - DCHECK(root != nullptr); - dex_caches_vector.push_back(root->AsObjectArray<mirror::DexCache>()); - } - return dex_caches_vector; -} - -void ClassLinker::AddBootImageClassesToClassTable() { - if (dex_cache_boot_image_class_lookup_required_) { - AddImageClassesToClassTable(Runtime::Current()->GetHeap()->GetBootImageSpaces(), - /*class_loader*/nullptr); - dex_cache_boot_image_class_lookup_required_ = false; - } -} - -void ClassLinker::AddImageClassesToClassTable(std::vector<gc::space::ImageSpace*> image_spaces, - mirror::ClassLoader* class_loader) { - Thread* self = Thread::Current(); - WriterMutexLock mu(self, *Locks::classlinker_classes_lock_); - ScopedAssertNoThreadSuspension ants("Moving image classes to class table"); - - ClassTable* const class_table = InsertClassTableForClassLoader(class_loader); - - std::string temp; - std::vector<mirror::ObjectArray<mirror::DexCache>*> dex_caches_vector = - GetImageDexCaches(image_spaces); - for (mirror::ObjectArray<mirror::DexCache>* dex_caches : dex_caches_vector) { - for (int32_t i = 0; i < dex_caches->GetLength(); i++) { - mirror::DexCache* dex_cache = dex_caches->Get(i); - GcRoot<mirror::Class>* types = dex_cache->GetResolvedTypes(); - for (int32_t j = 0, num_types = dex_cache->NumResolvedTypes(); j < num_types; j++) { - mirror::Class* klass = types[j].Read(); - if (klass != nullptr) { - DCHECK_EQ(klass->GetClassLoader(), class_loader); - const char* descriptor = klass->GetDescriptor(&temp); - size_t hash = ComputeModifiedUtf8Hash(descriptor); - mirror::Class* existing = class_table->Lookup(descriptor, hash); - if (existing != nullptr) { - CHECK_EQ(existing, klass) << PrettyClassAndClassLoader(existing) << " != " - << PrettyClassAndClassLoader(klass); - } else { - class_table->Insert(klass); - if (log_new_class_table_roots_) { - new_class_roots_.push_back(GcRoot<mirror::Class>(klass)); - } - } - } - } + ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); + ClassTable* const class_table = ClassTableForClassLoader(class_loader); + if (class_table != nullptr) { + mirror::Class* result = class_table->Lookup(descriptor, hash); + if (result != nullptr) { + return result; } } + return nullptr; } class MoveClassTableToPreZygoteVisitor : public ClassLoaderVisitor { @@ -3765,28 +3607,6 @@ void ClassLinker::MoveClassTableToPreZygote() { VisitClassLoaders(&visitor); } -mirror::Class* ClassLinker::LookupClassFromBootImage(const char* descriptor) { - ScopedAssertNoThreadSuspension ants("Image class lookup"); - std::vector<mirror::ObjectArray<mirror::DexCache>*> dex_caches_vector = - GetImageDexCaches(Runtime::Current()->GetHeap()->GetBootImageSpaces()); - for (mirror::ObjectArray<mirror::DexCache>* dex_caches : dex_caches_vector) { - for (int32_t i = 0; i < dex_caches->GetLength(); ++i) { - mirror::DexCache* dex_cache = dex_caches->Get(i); - const DexFile* dex_file = dex_cache->GetDexFile(); - // Try binary searching the type index by descriptor. - const DexFile::TypeId* type_id = dex_file->FindTypeId(descriptor); - if (type_id != nullptr) { - uint16_t type_idx = dex_file->GetIndexForTypeId(*type_id); - mirror::Class* klass = dex_cache->GetResolvedType(type_idx); - if (klass != nullptr) { - return klass; - } - } - } - } - return nullptr; -} - // Look up classes by hash and descriptor and put all matching ones in the result array. class LookupClassesVisitor : public ClassLoaderVisitor { public: @@ -3812,9 +3632,6 @@ class LookupClassesVisitor : public ClassLoaderVisitor { void ClassLinker::LookupClasses(const char* descriptor, std::vector<mirror::Class*>& result) { result.clear(); - if (dex_cache_boot_image_class_lookup_required_) { - AddBootImageClassesToClassTable(); - } Thread* const self = Thread::Current(); ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); const size_t hash = ComputeModifiedUtf8Hash(descriptor); @@ -5217,14 +5034,6 @@ bool ClassLinker::LinkClass(Thread* self, Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader); } CHECK_EQ(existing, klass.Get()); - if (kIsDebugBuild && class_loader == nullptr && dex_cache_boot_image_class_lookup_required_) { - // Check a class loaded with the system class loader matches one in the image if the class - // is in the image. - mirror::Class* const image_class = LookupClassFromBootImage(descriptor); - if (image_class != nullptr) { - CHECK_EQ(klass.Get(), existing) << descriptor; - } - } if (log_new_class_table_roots_) { new_class_roots_.push_back(GcRoot<mirror::Class>(h_new_class.Get())); } @@ -8093,9 +7902,6 @@ void ClassLinker::SetEntryPointsToInterpreter(ArtMethod* method) const { void ClassLinker::DumpForSigQuit(std::ostream& os) { ScopedObjectAccess soa(Thread::Current()); - if (dex_cache_boot_image_class_lookup_required_) { - AddBootImageClassesToClassTable(); - } ReaderMutexLock mu(soa.Self(), *Locks::classlinker_classes_lock_); os << "Zygote loaded classes=" << NumZygoteClasses() << " post zygote classes=" << NumNonZygoteClasses() << "\n"; @@ -8131,9 +7937,6 @@ size_t ClassLinker::NumNonZygoteClasses() const { } size_t ClassLinker::NumLoadedClasses() { - if (dex_cache_boot_image_class_lookup_required_) { - AddBootImageClassesToClassTable(); - } ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); // Only return non zygote classes since these are the ones which apps which care about. return NumNonZygoteClasses(); diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 43ffc8ed20..70cc768686 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -561,17 +561,6 @@ class ClassLinker { return class_roots; } - // Move all of the boot image classes into the class table for faster lookups. - void AddBootImageClassesToClassTable() - REQUIRES(!Locks::classlinker_classes_lock_) - REQUIRES_SHARED(Locks::mutator_lock_); - - // Add image classes to the class table. - void AddImageClassesToClassTable(std::vector<gc::space::ImageSpace*> image_spaces, - mirror::ClassLoader* class_loader) - REQUIRES(!Locks::classlinker_classes_lock_) - REQUIRES_SHARED(Locks::mutator_lock_); - // Move the class table to the pre-zygote table to reduce memory usage. This works by ensuring // that no more classes are ever added to the pre zygote table which makes it that the pages // always remain shared dirty instead of private dirty. @@ -1050,9 +1039,6 @@ class ClassLinker { void EnsureSkipAccessChecksMethods(Handle<mirror::Class> c) REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Class* LookupClassFromBootImage(const char* descriptor) - REQUIRES_SHARED(Locks::mutator_lock_); - // Register a class loader and create its class table and allocator. Should not be called if // these are already created. void RegisterClassLoader(mirror::ClassLoader* class_loader) @@ -1157,8 +1143,6 @@ class ClassLinker { // New class roots, only used by CMS since the GC needs to mark these in the pause. std::vector<GcRoot<mirror::Class>> new_class_roots_ GUARDED_BY(Locks::classlinker_classes_lock_); - // Do we need to search dex caches to find boot image classes? - bool dex_cache_boot_image_class_lookup_required_; // Number of times we've searched dex caches for a class. After a certain number of misses we move // the classes into the class_table_ to avoid dex cache based searches. Atomic<uint32_t> failed_dex_cache_class_lookups_; diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc index 096f003de3..2ea7bb6778 100644 --- a/runtime/elf_file.cc +++ b/runtime/elf_file.cc @@ -36,8 +36,7 @@ template <typename ElfTypes> ElfFileImpl<ElfTypes>::ElfFileImpl(File* file, bool writable, bool program_header_only, uint8_t* requested_base) - : file_(file), - writable_(writable), + : writable_(writable), program_header_only_(program_header_only), header_(nullptr), base_address_(nullptr), @@ -74,7 +73,7 @@ ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file, prot = PROT_READ; flags = MAP_PRIVATE; } - if (!elf_file->Setup(prot, flags, low_4gb, error_msg)) { + if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) { return nullptr; } return elf_file.release(); @@ -89,39 +88,44 @@ ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file, std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(new ElfFileImpl<ElfTypes> (file, (prot & PROT_WRITE) == PROT_WRITE, /*program_header_only*/false, /*requested_base*/nullptr)); - if (!elf_file->Setup(prot, flags, low_4gb, error_msg)) { + if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) { return nullptr; } return elf_file.release(); } template <typename ElfTypes> -bool ElfFileImpl<ElfTypes>::Setup(int prot, int flags, bool low_4gb, std::string* error_msg) { - int64_t temp_file_length = file_->GetLength(); +bool ElfFileImpl<ElfTypes>::Setup(File* file, + int prot, + int flags, + bool low_4gb, + std::string* error_msg) { + int64_t temp_file_length = file->GetLength(); if (temp_file_length < 0) { errno = -temp_file_length; *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s", - file_->GetPath().c_str(), file_->Fd(), strerror(errno)); + file->GetPath().c_str(), file->Fd(), strerror(errno)); return false; } size_t file_length = static_cast<size_t>(temp_file_length); if (file_length < sizeof(Elf_Ehdr)) { *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF header of " "%zd bytes: '%s'", file_length, sizeof(Elf_Ehdr), - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (program_header_only_) { // first just map ELF header to get program header size information size_t elf_header_size = sizeof(Elf_Ehdr); - if (!SetMap(MemMap::MapFile(elf_header_size, + if (!SetMap(file, + MemMap::MapFile(elf_header_size, prot, flags, - file_->Fd(), + file->Fd(), 0, low_4gb, - file_->GetPath().c_str(), + file->GetPath().c_str(), error_msg), error_msg)) { return false; @@ -131,16 +135,17 @@ bool ElfFileImpl<ElfTypes>::Setup(int prot, int flags, bool low_4gb, std::string if (file_length < program_header_size) { *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF program " "header of %zd bytes: '%s'", file_length, - sizeof(Elf_Ehdr), file_->GetPath().c_str()); + sizeof(Elf_Ehdr), file->GetPath().c_str()); return false; } - if (!SetMap(MemMap::MapFile(program_header_size, + if (!SetMap(file, + MemMap::MapFile(program_header_size, prot, flags, - file_->Fd(), + file->Fd(), 0, low_4gb, - file_->GetPath().c_str(), + file->GetPath().c_str(), error_msg), error_msg)) { *error_msg = StringPrintf("Failed to map ELF program headers: %s", error_msg->c_str()); @@ -148,13 +153,14 @@ bool ElfFileImpl<ElfTypes>::Setup(int prot, int flags, bool low_4gb, std::string } } else { // otherwise map entire file - if (!SetMap(MemMap::MapFile(file_->GetLength(), + if (!SetMap(file, + MemMap::MapFile(file->GetLength(), prot, flags, - file_->Fd(), + file->Fd(), 0, low_4gb, - file_->GetPath().c_str(), + file->GetPath().c_str(), error_msg), error_msg)) { *error_msg = StringPrintf("Failed to map ELF file: %s", error_msg->c_str()); @@ -178,7 +184,7 @@ bool ElfFileImpl<ElfTypes>::Setup(int prot, int flags, bool low_4gb, std::string Elf_Shdr* shstrtab_section_header = GetSectionNameStringSection(); if (shstrtab_section_header == nullptr) { *error_msg = StringPrintf("Failed to find shstrtab section header in ELF file: '%s'", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } @@ -186,7 +192,7 @@ bool ElfFileImpl<ElfTypes>::Setup(int prot, int flags, bool low_4gb, std::string dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC); if (dynamic_program_header_ == nullptr) { *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } @@ -200,7 +206,7 @@ bool ElfFileImpl<ElfTypes>::Setup(int prot, int flags, bool low_4gb, std::string Elf_Shdr* section_header = GetSectionHeader(i); if (section_header == nullptr) { *error_msg = StringPrintf("Failed to find section header for section %d in ELF file: '%s'", - i, file_->GetPath().c_str()); + i, file->GetPath().c_str()); return false; } switch (section_header->sh_type) { @@ -245,7 +251,7 @@ bool ElfFileImpl<ElfTypes>::Setup(int prot, int flags, bool low_4gb, std::string if (reinterpret_cast<uint8_t*>(dynamic_section_start_) != Begin() + section_header->sh_offset) { LOG(WARNING) << "Failed to find matching SHT_DYNAMIC for PT_DYNAMIC in " - << file_->GetPath() << ": " << std::hex + << file->GetPath() << ": " << std::hex << reinterpret_cast<void*>(dynamic_section_start_) << " != " << reinterpret_cast<void*>(Begin() + section_header->sh_offset); return false; @@ -263,7 +269,7 @@ bool ElfFileImpl<ElfTypes>::Setup(int prot, int flags, bool low_4gb, std::string } // Check for the existence of some sections. - if (!CheckSectionsExist(error_msg)) { + if (!CheckSectionsExist(file, error_msg)) { return false; } } @@ -283,7 +289,7 @@ bool ElfFileImpl<ElfTypes>::CheckAndSet(Elf32_Off offset, const char* label, uint8_t** target, std::string* error_msg) { if (Begin() + offset >= End()) { *error_msg = StringPrintf("Offset %d is out of range for %s in ELF file: '%s'", offset, label, - file_->GetPath().c_str()); + file_path_.c_str()); return false; } *target = Begin() + offset; @@ -324,11 +330,11 @@ bool ElfFileImpl<ElfTypes>::CheckSectionsLinked(const uint8_t* source, } template <typename ElfTypes> -bool ElfFileImpl<ElfTypes>::CheckSectionsExist(std::string* error_msg) const { + bool ElfFileImpl<ElfTypes>::CheckSectionsExist(File* file, std::string* error_msg) const { if (!program_header_only_) { // If in full mode, need section headers. if (section_headers_start_ == nullptr) { - *error_msg = StringPrintf("No section headers in ELF file: '%s'", file_->GetPath().c_str()); + *error_msg = StringPrintf("No section headers in ELF file: '%s'", file->GetPath().c_str()); return false; } } @@ -336,14 +342,14 @@ bool ElfFileImpl<ElfTypes>::CheckSectionsExist(std::string* error_msg) const { // This is redundant, but defensive. if (dynamic_program_header_ == nullptr) { *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } // Need a dynamic section. This is redundant, but defensive. if (dynamic_section_start_ == nullptr) { *error_msg = StringPrintf("Failed to find dynamic section in ELF file: '%s'", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } @@ -352,7 +358,7 @@ bool ElfFileImpl<ElfTypes>::CheckSectionsExist(std::string* error_msg) const { if (symtab_section_start_ != nullptr) { // When there's a symtab, there should be a strtab. if (strtab_section_start_ == nullptr) { - *error_msg = StringPrintf("No strtab for symtab in ELF file: '%s'", file_->GetPath().c_str()); + *error_msg = StringPrintf("No strtab for symtab in ELF file: '%s'", file->GetPath().c_str()); return false; } @@ -360,25 +366,25 @@ bool ElfFileImpl<ElfTypes>::CheckSectionsExist(std::string* error_msg) const { if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(symtab_section_start_), reinterpret_cast<const uint8_t*>(strtab_section_start_))) { *error_msg = StringPrintf("Symtab is not linked to the strtab in ELF file: '%s'", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } } // We always need a dynstr & dynsym. if (dynstr_section_start_ == nullptr) { - *error_msg = StringPrintf("No dynstr in ELF file: '%s'", file_->GetPath().c_str()); + *error_msg = StringPrintf("No dynstr in ELF file: '%s'", file->GetPath().c_str()); return false; } if (dynsym_section_start_ == nullptr) { - *error_msg = StringPrintf("No dynsym in ELF file: '%s'", file_->GetPath().c_str()); + *error_msg = StringPrintf("No dynsym in ELF file: '%s'", file->GetPath().c_str()); return false; } // Need a hash section for dynamic symbol lookup. if (hash_section_start_ == nullptr) { *error_msg = StringPrintf("Failed to find hash section in ELF file: '%s'", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } @@ -386,7 +392,7 @@ bool ElfFileImpl<ElfTypes>::CheckSectionsExist(std::string* error_msg) const { if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(hash_section_start_), reinterpret_cast<const uint8_t*>(dynsym_section_start_))) { *error_msg = StringPrintf("Hash section is not linked to the dynstr in ELF file: '%s'", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } @@ -397,9 +403,9 @@ bool ElfFileImpl<ElfTypes>::CheckSectionsExist(std::string* error_msg) const { // It might not be mapped, but we can compare against the file size. int64_t offset = static_cast<int64_t>(GetHeader().e_shoff + (GetHeader().e_shstrndx * GetHeader().e_shentsize)); - if (offset >= file_->GetLength()) { + if (offset >= file->GetLength()) { *error_msg = StringPrintf("Shstrtab is not in the mapped ELF file: '%s'", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } } @@ -408,15 +414,15 @@ bool ElfFileImpl<ElfTypes>::CheckSectionsExist(std::string* error_msg) const { } template <typename ElfTypes> -bool ElfFileImpl<ElfTypes>::SetMap(MemMap* map, std::string* error_msg) { +bool ElfFileImpl<ElfTypes>::SetMap(File* file, MemMap* map, std::string* error_msg) { if (map == nullptr) { // MemMap::Open should have already set an error. DCHECK(!error_msg->empty()); return false; } map_.reset(map); - CHECK(map_.get() != nullptr) << file_->GetPath(); - CHECK(map_->Begin() != nullptr) << file_->GetPath(); + CHECK(map_.get() != nullptr) << file->GetPath(); + CHECK(map_->Begin() != nullptr) << file->GetPath(); header_ = reinterpret_cast<Elf_Ehdr*>(map_->Begin()); if ((ELFMAG0 != header_->e_ident[EI_MAG0]) @@ -425,7 +431,7 @@ bool ElfFileImpl<ElfTypes>::SetMap(MemMap* map, std::string* error_msg) { || (ELFMAG3 != header_->e_ident[EI_MAG3])) { *error_msg = StringPrintf("Failed to find ELF magic value %d %d %d %d in %s, found %d %d %d %d", ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, - file_->GetPath().c_str(), + file->GetPath().c_str(), header_->e_ident[EI_MAG0], header_->e_ident[EI_MAG1], header_->e_ident[EI_MAG2], @@ -436,90 +442,90 @@ bool ElfFileImpl<ElfTypes>::SetMap(MemMap* map, std::string* error_msg) { if (elf_class != header_->e_ident[EI_CLASS]) { *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d in %s, found %d", elf_class, - file_->GetPath().c_str(), + file->GetPath().c_str(), header_->e_ident[EI_CLASS]); return false; } if (ELFDATA2LSB != header_->e_ident[EI_DATA]) { *error_msg = StringPrintf("Failed to find expected EI_DATA value %d in %s, found %d", ELFDATA2LSB, - file_->GetPath().c_str(), + file->GetPath().c_str(), header_->e_ident[EI_CLASS]); return false; } if (EV_CURRENT != header_->e_ident[EI_VERSION]) { *error_msg = StringPrintf("Failed to find expected EI_VERSION value %d in %s, found %d", EV_CURRENT, - file_->GetPath().c_str(), + file->GetPath().c_str(), header_->e_ident[EI_CLASS]); return false; } if (ET_DYN != header_->e_type) { *error_msg = StringPrintf("Failed to find expected e_type value %d in %s, found %d", ET_DYN, - file_->GetPath().c_str(), + file->GetPath().c_str(), header_->e_type); return false; } if (EV_CURRENT != header_->e_version) { *error_msg = StringPrintf("Failed to find expected e_version value %d in %s, found %d", EV_CURRENT, - file_->GetPath().c_str(), + file->GetPath().c_str(), header_->e_version); return false; } if (0 != header_->e_entry) { *error_msg = StringPrintf("Failed to find expected e_entry value %d in %s, found %d", 0, - file_->GetPath().c_str(), + file->GetPath().c_str(), static_cast<int32_t>(header_->e_entry)); return false; } if (0 == header_->e_phoff) { *error_msg = StringPrintf("Failed to find non-zero e_phoff value in %s", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (0 == header_->e_shoff) { *error_msg = StringPrintf("Failed to find non-zero e_shoff value in %s", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (0 == header_->e_ehsize) { *error_msg = StringPrintf("Failed to find non-zero e_ehsize value in %s", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (0 == header_->e_phentsize) { *error_msg = StringPrintf("Failed to find non-zero e_phentsize value in %s", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (0 == header_->e_phnum) { *error_msg = StringPrintf("Failed to find non-zero e_phnum value in %s", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (0 == header_->e_shentsize) { *error_msg = StringPrintf("Failed to find non-zero e_shentsize value in %s", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (0 == header_->e_shnum) { *error_msg = StringPrintf("Failed to find non-zero e_shnum value in %s", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (0 == header_->e_shstrndx) { *error_msg = StringPrintf("Failed to find non-zero e_shstrndx value in %s", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (header_->e_shstrndx >= header_->e_shnum) { *error_msg = StringPrintf("Failed to find e_shnum value %d less than %d in %s", header_->e_shstrndx, header_->e_shnum, - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } @@ -528,14 +534,14 @@ bool ElfFileImpl<ElfTypes>::SetMap(MemMap* map, std::string* error_msg) { *error_msg = StringPrintf("Failed to find e_phoff value %" PRIu64 " less than %zd in %s", static_cast<uint64_t>(header_->e_phoff), Size(), - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (header_->e_shoff >= Size()) { *error_msg = StringPrintf("Failed to find e_shoff value %" PRIu64 " less than %zd in %s", static_cast<uint64_t>(header_->e_shoff), Size(), - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } } @@ -577,7 +583,7 @@ typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::GetDynamicSectionStart() const { template <typename ElfTypes> typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbolSectionStart( Elf_Word section_type) const { - CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type; + CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; switch (section_type) { case SHT_SYMTAB: { return symtab_section_start_; @@ -597,7 +603,7 @@ typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbolSectionStart( template <typename ElfTypes> const char* ElfFileImpl<ElfTypes>::GetStringSectionStart( Elf_Word section_type) const { - CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type; + CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; switch (section_type) { case SHT_SYMTAB: { return strtab_section_start_; @@ -615,7 +621,7 @@ const char* ElfFileImpl<ElfTypes>::GetStringSectionStart( template <typename ElfTypes> const char* ElfFileImpl<ElfTypes>::GetString(Elf_Word section_type, Elf_Word i) const { - CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type; + CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; if (i == 0) { return nullptr; } @@ -673,7 +679,7 @@ typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetProgramHeaderNum() const { template <typename ElfTypes> typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::GetProgramHeader(Elf_Word i) const { - CHECK_LT(i, GetProgramHeaderNum()) << file_->GetPath(); // Sanity check for caller. + CHECK_LT(i, GetProgramHeaderNum()) << file_path_; // Sanity check for caller. uint8_t* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize); if (program_header >= End()) { return nullptr; // Failure condition. @@ -701,7 +707,7 @@ template <typename ElfTypes> typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionHeader(Elf_Word i) const { // Can only access arbitrary sections when we have the whole file, not just program header. // Even if we Load(), it doesn't bring in all the sections. - CHECK(!program_header_only_) << file_->GetPath(); + CHECK(!program_header_only_) << file_path_; if (i >= GetSectionHeaderNum()) { return nullptr; // Failure condition. } @@ -716,7 +722,7 @@ template <typename ElfTypes> typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByType(Elf_Word type) const { // Can only access arbitrary sections when we have the whole file, not just program header. // We could change this to switch on known types if they were detected during loading. - CHECK(!program_header_only_) << file_->GetPath(); + CHECK(!program_header_only_) << file_path_; for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) { Elf_Shdr* section_header = GetSectionHeader(i); if (section_header->sh_type == type) { @@ -802,8 +808,8 @@ bool ElfFileImpl<ElfTypes>::IsSymbolSectionType(Elf_Word section_type) { template <typename ElfTypes> typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSymbolNum(Elf_Shdr& section_header) const { CHECK(IsSymbolSectionType(section_header.sh_type)) - << file_->GetPath() << " " << section_header.sh_type; - CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath(); + << file_path_ << " " << section_header.sh_type; + CHECK_NE(0U, section_header.sh_entsize) << file_path_; return section_header.sh_size / section_header.sh_entsize; } @@ -819,7 +825,7 @@ typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbol(Elf_Word section_type, template <typename ElfTypes> typename ElfFileImpl<ElfTypes>::SymbolTable** ElfFileImpl<ElfTypes>::GetSymbolTable(Elf_Word section_type) { - CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type; + CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; switch (section_type) { case SHT_SYMTAB: { return &symtab_symbol_table_; @@ -837,8 +843,8 @@ ElfFileImpl<ElfTypes>::GetSymbolTable(Elf_Word section_type) { template <typename ElfTypes> typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindSymbolByName( Elf_Word section_type, const std::string& symbol_name, bool build_map) { - CHECK(!program_header_only_) << file_->GetPath(); - CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type; + CHECK(!program_header_only_) << file_path_; + CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; SymbolTable** symbol_table = GetSymbolTable(section_type); if (*symbol_table != nullptr || build_map) { @@ -928,7 +934,7 @@ typename ElfTypes::Addr ElfFileImpl<ElfTypes>::FindSymbolAddress( template <typename ElfTypes> const char* ElfFileImpl<ElfTypes>::GetString(Elf_Shdr& string_section, Elf_Word i) const { - CHECK(!program_header_only_) << file_->GetPath(); + CHECK(!program_header_only_) << file_path_; // TODO: remove this static_cast from enum when using -std=gnu++0x if (static_cast<Elf_Word>(SHT_STRTAB) != string_section.sh_type) { return nullptr; // Failure condition. @@ -954,7 +960,7 @@ typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetDynamicNum() const { template <typename ElfTypes> typename ElfTypes::Dyn& ElfFileImpl<ElfTypes>::GetDynamic(Elf_Word i) const { - CHECK_LT(i, GetDynamicNum()) << file_->GetPath(); + CHECK_LT(i, GetDynamicNum()) << file_path_; return *(GetDynamicSectionStart() + i); } @@ -981,40 +987,40 @@ typename ElfTypes::Word ElfFileImpl<ElfTypes>::FindDynamicValueByType(Elf_Sword template <typename ElfTypes> typename ElfTypes::Rel* ElfFileImpl<ElfTypes>::GetRelSectionStart(Elf_Shdr& section_header) const { - CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type; + CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type; return reinterpret_cast<Elf_Rel*>(Begin() + section_header.sh_offset); } template <typename ElfTypes> typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelNum(Elf_Shdr& section_header) const { - CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type; - CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath(); + CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type; + CHECK_NE(0U, section_header.sh_entsize) << file_path_; return section_header.sh_size / section_header.sh_entsize; } template <typename ElfTypes> typename ElfTypes::Rel& ElfFileImpl<ElfTypes>::GetRel(Elf_Shdr& section_header, Elf_Word i) const { - CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type; - CHECK_LT(i, GetRelNum(section_header)) << file_->GetPath(); + CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type; + CHECK_LT(i, GetRelNum(section_header)) << file_path_; return *(GetRelSectionStart(section_header) + i); } template <typename ElfTypes> typename ElfTypes::Rela* ElfFileImpl<ElfTypes>::GetRelaSectionStart(Elf_Shdr& section_header) const { - CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type; + CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type; return reinterpret_cast<Elf_Rela*>(Begin() + section_header.sh_offset); } template <typename ElfTypes> typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelaNum(Elf_Shdr& section_header) const { - CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type; + CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type; return section_header.sh_size / section_header.sh_entsize; } template <typename ElfTypes> typename ElfTypes::Rela& ElfFileImpl<ElfTypes>::GetRela(Elf_Shdr& section_header, Elf_Word i) const { - CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type; - CHECK_LT(i, GetRelaNum(section_header)) << file_->GetPath(); + CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type; + CHECK_LT(i, GetRelaNum(section_header)) << file_path_; return *(GetRelaSectionStart(section_header) + i); } @@ -1037,7 +1043,7 @@ bool ElfFileImpl<ElfTypes>::GetLoadedSize(size_t* size, std::string* error_msg) std::ostringstream oss; oss << "Program header #" << i << " has overflow in p_vaddr+p_memsz: 0x" << std::hex << program_header->p_vaddr << "+0x" << program_header->p_memsz << "=0x" << end_vaddr - << " in ELF file \"" << file_->GetPath() << "\""; + << " in ELF file \"" << file_path_ << "\""; *error_msg = oss.str(); *size = static_cast<size_t>(-1); return false; @@ -1048,13 +1054,13 @@ bool ElfFileImpl<ElfTypes>::GetLoadedSize(size_t* size, std::string* error_msg) } min_vaddr = RoundDown(min_vaddr, kPageSize); max_vaddr = RoundUp(max_vaddr, kPageSize); - CHECK_LT(min_vaddr, max_vaddr) << file_->GetPath(); + CHECK_LT(min_vaddr, max_vaddr) << file_path_; Elf_Addr loaded_size = max_vaddr - min_vaddr; // Check that the loaded_size fits in size_t. if (UNLIKELY(loaded_size > std::numeric_limits<size_t>::max())) { std::ostringstream oss; oss << "Loaded size is 0x" << std::hex << loaded_size << " but maximum size_t is 0x" - << std::numeric_limits<size_t>::max() << " for ELF file \"" << file_->GetPath() << "\""; + << std::numeric_limits<size_t>::max() << " for ELF file \"" << file_path_ << "\""; *error_msg = oss.str(); *size = static_cast<size_t>(-1); return false; @@ -1064,8 +1070,11 @@ bool ElfFileImpl<ElfTypes>::GetLoadedSize(size_t* size, std::string* error_msg) } template <typename ElfTypes> -bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* error_msg) { - CHECK(program_header_only_) << file_->GetPath(); +bool ElfFileImpl<ElfTypes>::Load(File* file, + bool executable, + bool low_4gb, + std::string* error_msg) { + CHECK(program_header_only_) << file->GetPath(); if (executable) { InstructionSet elf_ISA = GetInstructionSetFromELF(GetHeader().e_machine, GetHeader().e_flags); @@ -1082,7 +1091,7 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err Elf_Phdr* program_header = GetProgramHeader(i); if (program_header == nullptr) { *error_msg = StringPrintf("No program header for entry %d in ELF file %s.", - i, file_->GetPath().c_str()); + i, file->GetPath().c_str()); return false; } @@ -1106,11 +1115,11 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err // non-zero, the segments require the specific address specified, // which either was specified in the file because we already set // base_address_ after the first zero segment). - int64_t temp_file_length = file_->GetLength(); + int64_t temp_file_length = file->GetLength(); if (temp_file_length < 0) { errno = -temp_file_length; *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s", - file_->GetPath().c_str(), file_->Fd(), strerror(errno)); + file->GetPath().c_str(), file->Fd(), strerror(errno)); return false; } size_t file_length = static_cast<size_t>(temp_file_length); @@ -1122,7 +1131,7 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err reserve_base_override = requested_base_; } std::string reservation_name("ElfFile reservation for "); - reservation_name += file_->GetPath(); + reservation_name += file->GetPath(); size_t loaded_size; if (!GetLoadedSize(&loaded_size, error_msg)) { DCHECK(!error_msg->empty()); @@ -1178,7 +1187,7 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err *error_msg = StringPrintf("Invalid p_filesz > p_memsz (%" PRIu64 " > %" PRIu64 "): %s", static_cast<uint64_t>(program_header->p_filesz), static_cast<uint64_t>(program_header->p_memsz), - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (program_header->p_filesz < program_header->p_memsz && @@ -1187,14 +1196,14 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err " < %" PRIu64 "): %s", static_cast<uint64_t>(program_header->p_filesz), static_cast<uint64_t>(program_header->p_memsz), - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (file_length < (program_header->p_offset + program_header->p_filesz)) { *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment " "%d of %" PRIu64 " bytes: '%s'", file_length, i, static_cast<uint64_t>(program_header->p_offset + program_header->p_filesz), - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } if (program_header->p_filesz != 0u) { @@ -1203,28 +1212,28 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err program_header->p_filesz, prot, flags, - file_->Fd(), + file->Fd(), program_header->p_offset, /*low4_gb*/false, /*reuse*/true, // implies MAP_FIXED - file_->GetPath().c_str(), + file->GetPath().c_str(), error_msg)); if (segment.get() == nullptr) { *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s", - i, file_->GetPath().c_str(), error_msg->c_str()); + i, file->GetPath().c_str(), error_msg->c_str()); return false; } if (segment->Begin() != p_vaddr) { *error_msg = StringPrintf("Failed to map ELF file segment %d from %s at expected address %p, " "instead mapped to %p", - i, file_->GetPath().c_str(), p_vaddr, segment->Begin()); + i, file->GetPath().c_str(), p_vaddr, segment->Begin()); return false; } segments_.push_back(segment.release()); } if (program_header->p_filesz < program_header->p_memsz) { std::string name = StringPrintf("Zero-initialized segment %" PRIu64 " of ELF file %s", - static_cast<uint64_t>(i), file_->GetPath().c_str()); + static_cast<uint64_t>(i), file->GetPath().c_str()); std::unique_ptr<MemMap> segment( MemMap::MapAnonymous(name.c_str(), p_vaddr + program_header->p_filesz, @@ -1232,13 +1241,13 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err prot, false, true /* reuse */, error_msg)); if (segment == nullptr) { *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s: %s", - i, file_->GetPath().c_str(), error_msg->c_str()); + i, file->GetPath().c_str(), error_msg->c_str()); return false; } if (segment->Begin() != p_vaddr) { *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s " "at expected address %p, instead mapped to %p", - i, file_->GetPath().c_str(), p_vaddr, segment->Begin()); + i, file->GetPath().c_str(), p_vaddr, segment->Begin()); return false; } segments_.push_back(segment.release()); @@ -1249,7 +1258,7 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err uint8_t* dsptr = base_address_ + GetDynamicProgramHeader().p_vaddr; if ((dsptr < Begin() || dsptr >= End()) && !ValidPointer(dsptr)) { *error_msg = StringPrintf("dynamic section address invalid in ELF file %s", - file_->GetPath().c_str()); + file->GetPath().c_str()); return false; } dynamic_section_start_ = reinterpret_cast<Elf_Dyn*>(dsptr); @@ -1261,7 +1270,7 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err case DT_HASH: { if (!ValidPointer(d_ptr)) { *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s", - d_ptr, file_->GetPath().c_str()); + d_ptr, file->GetPath().c_str()); return false; } hash_section_start_ = reinterpret_cast<Elf_Word*>(d_ptr); @@ -1270,7 +1279,7 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err case DT_STRTAB: { if (!ValidPointer(d_ptr)) { *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s", - d_ptr, file_->GetPath().c_str()); + d_ptr, file->GetPath().c_str()); return false; } dynstr_section_start_ = reinterpret_cast<char*>(d_ptr); @@ -1279,7 +1288,7 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err case DT_SYMTAB: { if (!ValidPointer(d_ptr)) { *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s", - d_ptr, file_->GetPath().c_str()); + d_ptr, file->GetPath().c_str()); return false; } dynsym_section_start_ = reinterpret_cast<Elf_Sym*>(d_ptr); @@ -1289,7 +1298,7 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err if (GetDynamicNum() != i+1) { *error_msg = StringPrintf("DT_NULL found after %d .dynamic entries, " "expected %d as implied by size of PT_DYNAMIC segment in %s", - i + 1, GetDynamicNum(), file_->GetPath().c_str()); + i + 1, GetDynamicNum(), file->GetPath().c_str()); return false; } break; @@ -1298,7 +1307,7 @@ bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* err } // Check for the existence of some sections. - if (!CheckSectionsExist(error_msg)) { + if (!CheckSectionsExist(file, error_msg)) { return false; } @@ -1392,7 +1401,7 @@ void ElfFileImpl<ElfTypes>::ApplyOatPatches( } template <typename ElfTypes> -bool ElfFileImpl<ElfTypes>::Strip(std::string* error_msg) { +bool ElfFileImpl<ElfTypes>::Strip(File* file, std::string* error_msg) { // ELF files produced by MCLinker look roughly like this // // +------------+ @@ -1484,10 +1493,10 @@ bool ElfFileImpl<ElfTypes>::Strip(std::string* error_msg) { GetHeader().e_shnum = section_headers.size(); GetHeader().e_shoff = shoff; - int result = ftruncate(file_->Fd(), offset); + int result = ftruncate(file->Fd(), offset); if (result != 0) { *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s", - file_->GetPath().c_str(), strerror(errno)); + file->GetPath().c_str(), strerror(errno)); return false; } return true; @@ -1498,32 +1507,32 @@ static const bool DEBUG_FIXUP = false; template <typename ElfTypes> bool ElfFileImpl<ElfTypes>::Fixup(Elf_Addr base_address) { if (!FixupDynamic(base_address)) { - LOG(WARNING) << "Failed to fixup .dynamic in " << file_->GetPath(); + LOG(WARNING) << "Failed to fixup .dynamic in " << file_path_; return false; } if (!FixupSectionHeaders(base_address)) { - LOG(WARNING) << "Failed to fixup section headers in " << file_->GetPath(); + LOG(WARNING) << "Failed to fixup section headers in " << file_path_; return false; } if (!FixupProgramHeaders(base_address)) { - LOG(WARNING) << "Failed to fixup program headers in " << file_->GetPath(); + LOG(WARNING) << "Failed to fixup program headers in " << file_path_; return false; } if (!FixupSymbols(base_address, true)) { - LOG(WARNING) << "Failed to fixup .dynsym in " << file_->GetPath(); + LOG(WARNING) << "Failed to fixup .dynsym in " << file_path_; return false; } if (!FixupSymbols(base_address, false)) { - LOG(WARNING) << "Failed to fixup .symtab in " << file_->GetPath(); + LOG(WARNING) << "Failed to fixup .symtab in " << file_path_; return false; } if (!FixupRelocations(base_address)) { - LOG(WARNING) << "Failed to fixup .rel.dyn in " << file_->GetPath(); + LOG(WARNING) << "Failed to fixup .rel.dyn in " << file_path_; return false; } static_assert(sizeof(Elf_Off) >= sizeof(base_address), "Potentially losing precision."); if (!FixupDebugSections(static_cast<Elf_Off>(base_address))) { - LOG(WARNING) << "Failed to fixup debug sections in " << file_->GetPath(); + LOG(WARNING) << "Failed to fixup debug sections in " << file_path_; return false; } return true; @@ -1538,7 +1547,7 @@ bool ElfFileImpl<ElfTypes>::FixupDynamic(Elf_Addr base_address) { Elf_Addr d_ptr = elf_dyn.d_un.d_ptr; if (DEBUG_FIXUP) { LOG(INFO) << StringPrintf("In %s moving Elf_Dyn[%d] from 0x%" PRIx64 " to 0x%" PRIx64, - GetFile().GetPath().c_str(), i, + file_path_.c_str(), i, static_cast<uint64_t>(d_ptr), static_cast<uint64_t>(d_ptr + base_address)); } @@ -1560,7 +1569,7 @@ bool ElfFileImpl<ElfTypes>::FixupSectionHeaders(Elf_Addr base_address) { } if (DEBUG_FIXUP) { LOG(INFO) << StringPrintf("In %s moving Elf_Shdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64, - GetFile().GetPath().c_str(), i, + file_path_.c_str(), i, static_cast<uint64_t>(sh->sh_addr), static_cast<uint64_t>(sh->sh_addr + base_address)); } @@ -1575,19 +1584,19 @@ bool ElfFileImpl<ElfTypes>::FixupProgramHeaders(Elf_Addr base_address) { for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) { Elf_Phdr* ph = GetProgramHeader(i); CHECK(ph != nullptr); - CHECK_EQ(ph->p_vaddr, ph->p_paddr) << GetFile().GetPath() << " i=" << i; + CHECK_EQ(ph->p_vaddr, ph->p_paddr) << file_path_ << " i=" << i; CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1)))) - << GetFile().GetPath() << " i=" << i; + << file_path_ << " i=" << i; if (DEBUG_FIXUP) { LOG(INFO) << StringPrintf("In %s moving Elf_Phdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64, - GetFile().GetPath().c_str(), i, + file_path_.c_str(), i, static_cast<uint64_t>(ph->p_vaddr), static_cast<uint64_t>(ph->p_vaddr + base_address)); } ph->p_vaddr += base_address; ph->p_paddr += base_address; CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1)))) - << GetFile().GetPath() << " i=" << i; + << file_path_ << " i=" << i; } return true; } @@ -1599,7 +1608,7 @@ bool ElfFileImpl<ElfTypes>::FixupSymbols(Elf_Addr base_address, bool dynamic) { Elf_Shdr* symbol_section = FindSectionByType(section_type); if (symbol_section == nullptr) { // file is missing optional .symtab - CHECK(!dynamic) << GetFile().GetPath(); + CHECK(!dynamic) << file_path_; return true; } for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) { @@ -1608,7 +1617,7 @@ bool ElfFileImpl<ElfTypes>::FixupSymbols(Elf_Addr base_address, bool dynamic) { if (symbol->st_value != 0) { if (DEBUG_FIXUP) { LOG(INFO) << StringPrintf("In %s moving Elf_Sym[%d] from 0x%" PRIx64 " to 0x%" PRIx64, - GetFile().GetPath().c_str(), i, + file_path_.c_str(), i, static_cast<uint64_t>(symbol->st_value), static_cast<uint64_t>(symbol->st_value + base_address)); } @@ -1628,7 +1637,7 @@ bool ElfFileImpl<ElfTypes>::FixupRelocations(Elf_Addr base_address) { Elf_Rel& rel = GetRel(*sh, j); if (DEBUG_FIXUP) { LOG(INFO) << StringPrintf("In %s moving Elf_Rel[%d] from 0x%" PRIx64 " to 0x%" PRIx64, - GetFile().GetPath().c_str(), j, + file_path_.c_str(), j, static_cast<uint64_t>(rel.r_offset), static_cast<uint64_t>(rel.r_offset + base_address)); } @@ -1639,7 +1648,7 @@ bool ElfFileImpl<ElfTypes>::FixupRelocations(Elf_Addr base_address) { Elf_Rela& rela = GetRela(*sh, j); if (DEBUG_FIXUP) { LOG(INFO) << StringPrintf("In %s moving Elf_Rela[%d] from 0x%" PRIx64 " to 0x%" PRIx64, - GetFile().GetPath().c_str(), j, + file_path_.c_str(), j, static_cast<uint64_t>(rela.r_offset), static_cast<uint64_t>(rela.r_offset + base_address)); } @@ -1695,8 +1704,9 @@ ElfFile* ElfFile::Open(File* file, low_4gb, error_msg, requested_base); - if (elf_file_impl == nullptr) + if (elf_file_impl == nullptr) { return nullptr; + } return new ElfFile(elf_file_impl); } else if (header[EI_CLASS] == ELFCLASS32) { ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, @@ -1775,8 +1785,8 @@ ElfFile* ElfFile::Open(File* file, int mmap_prot, int mmap_flags, std::string* e return elf32_->func(__VA_ARGS__); \ } -bool ElfFile::Load(bool executable, bool low_4gb, std::string* error_msg) { - DELEGATE_TO_IMPL(Load, executable, low_4gb, error_msg); +bool ElfFile::Load(File* file, bool executable, bool low_4gb, std::string* error_msg) { + DELEGATE_TO_IMPL(Load, file, executable, low_4gb, error_msg); } const uint8_t* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const { @@ -1795,8 +1805,8 @@ uint8_t* ElfFile::End() const { DELEGATE_TO_IMPL(End); } -const File& ElfFile::GetFile() const { - DELEGATE_TO_IMPL(GetFile); +const std::string& ElfFile::GetFilePath() const { + DELEGATE_TO_IMPL(GetFilePath); } bool ElfFile::GetSectionOffsetAndSize(const char* section_name, uint64_t* offset, @@ -1854,10 +1864,11 @@ bool ElfFile::Strip(File* file, std::string* error_msg) { return false; } - if (elf_file->elf64_.get() != nullptr) - return elf_file->elf64_->Strip(error_msg); - else - return elf_file->elf32_->Strip(error_msg); + if (elf_file->elf64_.get() != nullptr) { + return elf_file->elf64_->Strip(file, error_msg); + } else { + return elf_file->elf32_->Strip(file, error_msg); + } } bool ElfFile::Fixup(uint64_t base_address) { diff --git a/runtime/elf_file.h b/runtime/elf_file.h index c3616f7290..b1c9395fb5 100644 --- a/runtime/elf_file.h +++ b/runtime/elf_file.h @@ -53,7 +53,7 @@ class ElfFile { ~ElfFile(); // Load segments into memory based on PT_LOAD program headers - bool Load(bool executable, bool low_4gb, std::string* error_msg); + bool Load(File* file, bool executable, bool low_4gb, std::string* error_msg); const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name) const; @@ -65,7 +65,7 @@ class ElfFile { // The end of the memory map address range for this ELF file. uint8_t* End() const; - const File& GetFile() const; + const std::string& GetFilePath() const; bool GetSectionOffsetAndSize(const char* section_name, uint64_t* offset, uint64_t* size) const; diff --git a/runtime/elf_file_impl.h b/runtime/elf_file_impl.h index 1cdbedc057..04c224387b 100644 --- a/runtime/elf_file_impl.h +++ b/runtime/elf_file_impl.h @@ -61,8 +61,8 @@ class ElfFileImpl { std::string* error_msg); ~ElfFileImpl(); - const File& GetFile() const { - return *file_; + const std::string& GetFilePath() const { + return file_path_; } uint8_t* Begin() const { @@ -119,7 +119,7 @@ class ElfFileImpl { // Load segments into memory based on PT_LOAD program headers. // executable is true at run time, false at compile time. - bool Load(bool executable, bool low_4gb, std::string* error_msg); + bool Load(File* file, bool executable, bool low_4gb, std::string* error_msg); bool Fixup(Elf_Addr base_address); bool FixupDynamic(Elf_Addr base_address); @@ -132,14 +132,14 @@ class ElfFileImpl { static void ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta, uint8_t* to_patch, const uint8_t* to_patch_end); - bool Strip(std::string* error_msg); + bool Strip(File* file, std::string* error_msg); private: ElfFileImpl(File* file, bool writable, bool program_header_only, uint8_t* requested_base); - bool Setup(int prot, int flags, bool low_4gb, std::string* error_msg); + bool Setup(File* file, int prot, int flags, bool low_4gb, std::string* error_msg); - bool SetMap(MemMap* map, std::string* error_msg); + bool SetMap(File* file, MemMap* map, std::string* error_msg); uint8_t* GetProgramHeadersStart() const; uint8_t* GetSectionHeadersStart() const; @@ -163,7 +163,7 @@ class ElfFileImpl { const Elf_Sym* FindDynamicSymbol(const std::string& symbol_name) const; // Check that certain sections and their dependencies exist. - bool CheckSectionsExist(std::string* error_msg) const; + bool CheckSectionsExist(File* file, std::string* error_msg) const; // Check that the link of the first section links to the second section. bool CheckSectionsLinked(const uint8_t* source, const uint8_t* target) const; @@ -191,7 +191,7 @@ class ElfFileImpl { // Lookup a string by section type. Returns null for special 0 offset. const char* GetString(Elf_Word section_type, Elf_Word) const; - const File* const file_; + const std::string file_path_; const bool writable_; const bool program_header_only_; diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc index 4311d19216..2a3a6bfa06 100644 --- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc @@ -63,12 +63,14 @@ extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx, Thread* auto* caller = GetCalleeSaveMethodCaller(self, Runtime::kSaveRefsOnly); mirror::String* result = ResolveStringFromCode(caller, string_idx); if (LIKELY(result != nullptr)) { - // For AOT code, we need a write barrier for the dex cache that holds the GC roots in the .bss. + // For AOT code, we need a write barrier for the class loader that holds + // the GC roots in the .bss. const DexFile* dex_file = caller->GetDexFile(); if (dex_file != nullptr && dex_file->GetOatDexFile() != nullptr && !dex_file->GetOatDexFile()->GetOatFile()->GetBssGcRoots().empty()) { mirror::ClassLoader* class_loader = caller->GetDeclaringClass()->GetClassLoader(); + DCHECK(class_loader != nullptr); // We do not use .bss GC roots for boot image. // Note that we emit the barrier before the compiled code stores the string as GC root. // This is OK as there is no suspend point point in between. Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader); diff --git a/runtime/intern_table.cc b/runtime/intern_table.cc index be061be1ed..a61a1878af 100644 --- a/runtime/intern_table.cc +++ b/runtime/intern_table.cc @@ -33,8 +33,7 @@ namespace art { InternTable::InternTable() - : images_added_to_intern_table_(false), - log_new_roots_(false), + : log_new_roots_(false), weak_intern_condition_("New intern condition", *Locks::intern_table_lock_), weak_root_state_(gc::kWeakRootStateNormal) { } @@ -181,57 +180,8 @@ void InternTable::AddImagesStringsToTable(const std::vector<gc::space::ImageSpac const ImageSection& section = header->GetImageSection(ImageHeader::kSectionInternedStrings); if (section.Size() > 0) { AddTableFromMemoryLocked(image_space->Begin() + section.Offset()); - } else { - // TODO: Delete this logic? - mirror::Object* root = header->GetImageRoot(ImageHeader::kDexCaches); - mirror::ObjectArray<mirror::DexCache>* dex_caches = root->AsObjectArray<mirror::DexCache>(); - for (int32_t i = 0; i < dex_caches->GetLength(); ++i) { - mirror::DexCache* dex_cache = dex_caches->Get(i); - const size_t num_strings = dex_cache->NumStrings(); - for (size_t j = 0; j < num_strings; ++j) { - mirror::String* image_string = dex_cache->GetResolvedString(j); - if (image_string != nullptr) { - mirror::String* found = LookupStrongLocked(image_string); - if (found == nullptr) { - InsertStrong(image_string); - } else { - DCHECK_EQ(found, image_string); - } - } - } - } - } - } - images_added_to_intern_table_ = true; -} - -mirror::String* InternTable::LookupStringFromImage(mirror::String* s) { - DCHECK(!images_added_to_intern_table_); - const std::vector<gc::space::ImageSpace*>& image_spaces = - Runtime::Current()->GetHeap()->GetBootImageSpaces(); - if (image_spaces.empty()) { - return nullptr; // No image present. - } - const std::string utf8 = s->ToModifiedUtf8(); - for (gc::space::ImageSpace* image_space : image_spaces) { - mirror::Object* root = image_space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); - mirror::ObjectArray<mirror::DexCache>* dex_caches = root->AsObjectArray<mirror::DexCache>(); - for (int32_t i = 0; i < dex_caches->GetLength(); ++i) { - mirror::DexCache* dex_cache = dex_caches->Get(i); - const DexFile* dex_file = dex_cache->GetDexFile(); - // Binary search the dex file for the string index. - const DexFile::StringId* string_id = dex_file->FindStringId(utf8.c_str()); - if (string_id != nullptr) { - uint32_t string_idx = dex_file->GetIndexForStringId(*string_id); - // GetResolvedString() contains a RB. - mirror::String* image_string = dex_cache->GetResolvedString(string_idx); - if (image_string != nullptr) { - return image_string; - } - } } } - return nullptr; } void InternTable::BroadcastForNewInterns() { @@ -303,13 +253,6 @@ mirror::String* InternTable::Insert(mirror::String* s, bool is_strong, bool hold } return weak; } - // Check the image for a match. - if (!images_added_to_intern_table_) { - mirror::String* const image_string = LookupStringFromImage(s); - if (image_string != nullptr) { - return is_strong ? InsertStrong(image_string) : InsertWeak(image_string); - } - } // No match in the strong table or the weak table. Insert into the strong / weak table. return is_strong ? InsertStrong(s) : InsertWeak(s); } diff --git a/runtime/intern_table.h b/runtime/intern_table.h index 184fbdc539..30ff55d33d 100644 --- a/runtime/intern_table.h +++ b/runtime/intern_table.h @@ -238,8 +238,6 @@ class InternTable { REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_); // Transaction rollback access. - mirror::String* LookupStringFromImage(mirror::String* s) - REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_); mirror::String* InsertStrongFromTransaction(mirror::String* s) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_); mirror::String* InsertWeakFromTransaction(mirror::String* s) @@ -260,7 +258,6 @@ class InternTable { void WaitUntilAccessible(Thread* self) REQUIRES(Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_); - bool images_added_to_intern_table_ GUARDED_BY(Locks::intern_table_lock_); bool log_new_roots_ GUARDED_BY(Locks::intern_table_lock_); ConditionVariable weak_intern_condition_ GUARDED_BY(Locks::intern_table_lock_); // Since this contains (strong) roots, they need a read barrier to diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index f164a92c92..c14b6169fb 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -959,7 +959,7 @@ bool ElfOatFile::ElfFileOpen(File* file, DCHECK(!error_msg->empty()); return false; } - bool loaded = elf_file_->Load(executable, low_4gb, error_msg); + bool loaded = elf_file_->Load(file, executable, low_4gb, error_msg); DCHECK(loaded || !error_msg->empty()); return loaded; } diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 9c0d2db873..baa4046334 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -829,7 +829,7 @@ static bool OpenDexFilesFromImage(const std::string& image_location, if (file.get() == nullptr) { return false; } - std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file.release(), + std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file.get(), false /* writable */, false /* program_header_only */, false /* low_4gb */, @@ -1165,10 +1165,6 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { ScopedTrace trace2("AddImageStringsToTable"); GetInternTable()->AddImagesStringsToTable(heap_->GetBootImageSpaces()); } - { - ScopedTrace trace2("MoveImageClassesToClassTable"); - GetClassLinker()->AddBootImageClassesToClassTable(); - } } else { std::vector<std::string> dex_filenames; Split(boot_class_path_string_, ':', &dex_filenames); |