diff options
20 files changed, 157 insertions, 186 deletions
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc index 9e5cd8035c..492f9ce5c1 100644 --- a/dex2oat/linker/image_writer.cc +++ b/dex2oat/linker/image_writer.cc @@ -1067,18 +1067,12 @@ void ImageWriter::PruneAndPreloadDexCache(ObjPtr<mirror::DexCache> dex_cache, } if (method == nullptr || i < stored_index) { if (last_class != nullptr) { - const char* name = dex_file.StringDataByIdx(method_id.name_idx_); - Signature signature = dex_file.GetMethodSignature(method_id); - if (last_class->IsInterface()) { - method = last_class->FindInterfaceMethod(name, signature, target_ptr_size_); - } else { - method = last_class->FindClassMethod(name, signature, target_ptr_size_); - } - if (method != nullptr) { - // If the referenced class is in the image, the defining class must also be there. - DCHECK(KeepClass(method->GetDeclaringClass())); - dex_cache->SetResolvedMethod(i, method, target_ptr_size_); - } + // Try to resolve the method with the class linker, which will insert + // it into the dex cache if successful. + method = class_linker->FindResolvedMethod(last_class, dex_cache, class_loader, i); + // If the referenced class is in the image, the defining class must also be there. + DCHECK(method == nullptr || KeepClass(method->GetDeclaringClass())); + DCHECK(method == nullptr || dex_cache->GetResolvedMethod(i, target_ptr_size_) == method); } } else { DCHECK_EQ(i, stored_index); @@ -1112,14 +1106,10 @@ void ImageWriter::PruneAndPreloadDexCache(ObjPtr<mirror::DexCache> dex_cache, } if (field == nullptr || i < stored_index) { if (last_class != nullptr) { - const char* name = dex_file.StringDataByIdx(field_id.name_idx_); - const char* type = dex_file.StringByTypeIdx(field_id.type_idx_); - field = mirror::Class::FindField(Thread::Current(), last_class, name, type); - if (field != nullptr) { - // If the referenced class is in the image, the defining class must also be there. - DCHECK(KeepClass(field->GetDeclaringClass())); - dex_cache->SetResolvedField(i, field, target_ptr_size_); - } + field = class_linker->FindResolvedFieldJLS(last_class, dex_cache, class_loader, i); + // If the referenced class is in the image, the defining class must also be there. + DCHECK(field == nullptr || KeepClass(field->GetDeclaringClass())); + DCHECK(field == nullptr || dex_cache->GetResolvedField(i, target_ptr_size_) == field); } } else { DCHECK_EQ(i, stored_index); @@ -1208,7 +1198,9 @@ void ImageWriter::PruneNonImageClasses() { } } for (ObjPtr<mirror::DexCache> dex_cache : dex_caches) { - PruneAndPreloadDexCache(dex_cache, class_loader); + // Pass the class loader associated with the DexCache. This can either be + // the app's `class_loader` or `nullptr` if boot class loader. + PruneAndPreloadDexCache(dex_cache, IsInBootImage(dex_cache.Ptr()) ? nullptr : class_loader); } // Drop the array class cache in the ClassLinker, as these are roots holding those classes live. diff --git a/libartbase/Android.bp b/libartbase/Android.bp index 50abdd36af..c8a06ed3b0 100644 --- a/libartbase/Android.bp +++ b/libartbase/Android.bp @@ -19,11 +19,13 @@ cc_defaults { defaults: ["art_defaults"], host_supported: true, srcs: [ + "arch/instruction_set.cc", "base/allocator.cc", "base/arena_allocator.cc", "base/arena_bit_vector.cc", "base/bit_vector.cc", "base/file_magic.cc", + "base/file_utils.cc", "base/hex_dump.cc", "base/logging.cc", "base/malloc_arena_pool.cc", @@ -62,7 +64,6 @@ cc_defaults { generated_sources: ["art_libartbase_operator_srcs"], cflags: ["-DBUILDING_LIBART=1"], shared_libs: [ - "libbacktrace", "liblog", // For ashmem. "libcutils", @@ -81,6 +82,7 @@ gensrcs { cmd: "$(location generate_operator_out) art/libartbase $(in) > $(out)", tools: ["generate_operator_out"], srcs: [ + "arch/instruction_set.h", "base/allocator.h", "base/callee_save_type.h", "base/unix_file/fd_file.h", @@ -142,12 +144,14 @@ art_cc_test { "art_gtest_defaults", ], srcs: [ + "arch/instruction_set_test.cc", "base/arena_allocator_test.cc", "base/bit_field_test.cc", "base/bit_string_test.cc", "base/bit_struct_test.cc", "base/bit_utils_test.cc", "base/bit_vector_test.cc", + "base/file_utils_test.cc", "base/hash_set_test.cc", "base/hex_dump_test.cc", "base/histogram_test.cc", diff --git a/runtime/arch/instruction_set.cc b/libartbase/arch/instruction_set.cc index b848eb27fc..a187663062 100644 --- a/runtime/arch/instruction_set.cc +++ b/libartbase/arch/instruction_set.cc @@ -16,8 +16,6 @@ #include "instruction_set.h" -// Explicitly include our own elf.h to avoid Linux and other dependencies. -#include "../elf.h" #include "android-base/logging.h" #include "base/bit_utils.h" #include "base/globals.h" @@ -83,29 +81,6 @@ InstructionSet GetInstructionSetFromString(const char* isa_str) { return InstructionSet::kNone; } -InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags) { - switch (e_machine) { - case EM_ARM: - return InstructionSet::kArm; - case EM_AARCH64: - return InstructionSet::kArm64; - case EM_386: - return InstructionSet::kX86; - case EM_X86_64: - return InstructionSet::kX86_64; - case EM_MIPS: { - if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R2 || - (e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) { - return InstructionSet::kMips; - } else if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_64R6) { - return InstructionSet::kMips64; - } - break; - } - } - return InstructionSet::kNone; -} - size_t GetInstructionSetAlignment(InstructionSet isa) { switch (isa) { case InstructionSet::kArm: diff --git a/runtime/arch/instruction_set.h b/libartbase/arch/instruction_set.h index 6434005dda..06bd53a6a9 100644 --- a/runtime/arch/instruction_set.h +++ b/libartbase/arch/instruction_set.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_ARCH_INSTRUCTION_SET_H_ -#define ART_RUNTIME_ARCH_INSTRUCTION_SET_H_ +#ifndef ART_LIBARTBASE_ARCH_INSTRUCTION_SET_H_ +#define ART_LIBARTBASE_ARCH_INSTRUCTION_SET_H_ #include <iosfwd> #include <string> @@ -89,8 +89,6 @@ const char* GetInstructionSetString(InstructionSet isa); // Note: Returns kNone when the string cannot be parsed to a known value. InstructionSet GetInstructionSetFromString(const char* instruction_set); -InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags); - // Fatal logging out of line to keep the header clean of logging.h. NO_RETURN void InstructionSetAbort(InstructionSet isa); @@ -299,4 +297,4 @@ static inline TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) { } // namespace art -#endif // ART_RUNTIME_ARCH_INSTRUCTION_SET_H_ +#endif // ART_LIBARTBASE_ARCH_INSTRUCTION_SET_H_ diff --git a/runtime/arch/instruction_set_test.cc b/libartbase/arch/instruction_set_test.cc index 12a117d7a1..12a117d7a1 100644 --- a/runtime/arch/instruction_set_test.cc +++ b/libartbase/arch/instruction_set_test.cc diff --git a/runtime/base/file_utils.cc b/libartbase/base/file_utils.cc index 537216c198..9450e1e8c1 100644 --- a/runtime/base/file_utils.cc +++ b/libartbase/base/file_utils.cc @@ -47,7 +47,6 @@ #include "base/os.h" #include "base/stl_util.h" #include "base/unix_file/fd_file.h" -#include "dex/dex_file_loader.h" #if defined(__APPLE__) #include <crt_externs.h> @@ -64,6 +63,8 @@ namespace art { using android::base::StringAppendF; using android::base::StringPrintf; +static constexpr const char* kClassesDex = "classes.dex"; + bool ReadFileToString(const std::string& file_name, std::string* result) { File file(file_name, O_RDONLY, false); if (!file.IsOpened()) { @@ -224,7 +225,7 @@ bool GetDalvikCacheFilename(const char* location, const char* cache_location, !android::base::EndsWith(location, ".art") && !android::base::EndsWith(location, ".oat")) { cache_file += "/"; - cache_file += DexFileLoader::kClassesDex; + cache_file += kClassesDex; } std::replace(cache_file.begin(), cache_file.end(), '/', '@'); *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str()); diff --git a/runtime/base/file_utils.h b/libartbase/base/file_utils.h index d4f6c576c0..063393bd3b 100644 --- a/runtime/base/file_utils.h +++ b/libartbase/base/file_utils.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_BASE_FILE_UTILS_H_ -#define ART_RUNTIME_BASE_FILE_UTILS_H_ +#ifndef ART_LIBARTBASE_BASE_FILE_UTILS_H_ +#define ART_LIBARTBASE_BASE_FILE_UTILS_H_ #include <stdlib.h> @@ -46,6 +46,7 @@ std::string GetDefaultBootImageLocation(std::string* error_msg); // Returns the dalvik-cache location, with subdir appended. Returns the empty string if the cache // could not be found. std::string GetDalvikCache(const char* subdir); + // Return true if we found the dalvik cache and stored it in the dalvik_cache argument. // have_android_data will be set to true if we have an ANDROID_DATA that exists, // dalvik_cache_exists will be true if there is a dalvik-cache directory that is present. @@ -79,4 +80,4 @@ bool LocationIsOnSystemFramework(const char* location); } // namespace art -#endif // ART_RUNTIME_BASE_FILE_UTILS_H_ +#endif // ART_LIBARTBASE_BASE_FILE_UTILS_H_ diff --git a/runtime/base/file_utils_test.cc b/libartbase/base/file_utils_test.cc index e74dfe5e64..e74dfe5e64 100644 --- a/runtime/base/file_utils_test.cc +++ b/libartbase/base/file_utils_test.cc diff --git a/libartbase/base/mem_map.cc b/libartbase/base/mem_map.cc index 9a1392ceee..c455fed829 100644 --- a/libartbase/base/mem_map.cc +++ b/libartbase/base/mem_map.cc @@ -29,7 +29,6 @@ #include "android-base/stringprintf.h" #include "android-base/unique_fd.h" -#include "backtrace/BacktraceMap.h" #include "cutils/ashmem.h" #include "allocator.h" @@ -57,21 +56,6 @@ using Maps = AllocationTrackingMultiMap<void*, MemMap*, kAllocatorTagMaps>; // All the non-empty MemMaps. Use a multimap as we do a reserve-and-divide (eg ElfMap::Load()). static Maps* gMaps GUARDED_BY(MemMap::GetMemMapsLock()) = nullptr; -static std::ostream& operator<<( - std::ostream& os, - std::pair<BacktraceMap::iterator, BacktraceMap::iterator> iters) { - for (BacktraceMap::iterator it = iters.first; it != iters.second; ++it) { - const backtrace_map_t* entry = *it; - os << StringPrintf("0x%08x-0x%08x %c%c%c %s\n", - static_cast<uint32_t>(entry->start), - static_cast<uint32_t>(entry->end), - (entry->flags & PROT_READ) ? 'r' : '-', - (entry->flags & PROT_WRITE) ? 'w' : '-', - (entry->flags & PROT_EXEC) ? 'x' : '-', entry->name.c_str()); - } - return os; -} - std::ostream& operator<<(std::ostream& os, const Maps& mem_maps) { os << "MemMap:" << std::endl; for (auto it = mem_maps.begin(); it != mem_maps.end(); ++it) { @@ -149,8 +133,6 @@ bool MemMap::ContainedWithinExistingMap(uint8_t* ptr, size_t size, std::string* uintptr_t begin = reinterpret_cast<uintptr_t>(ptr); uintptr_t end = begin + size; - // There is a suspicion that BacktraceMap::Create is occasionally missing maps. TODO: Investigate - // further. { std::lock_guard<std::mutex> mu(*mem_maps_lock_); for (auto& pair : *gMaps) { @@ -162,22 +144,6 @@ bool MemMap::ContainedWithinExistingMap(uint8_t* ptr, size_t size, std::string* } } - std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true)); - if (map == nullptr) { - if (error_msg != nullptr) { - *error_msg = StringPrintf("Failed to build process map"); - } - return false; - } - - ScopedBacktraceMapIteratorLock lock(map.get()); - for (BacktraceMap::iterator it = map->begin(); it != map->end(); ++it) { - const backtrace_map_t* entry = *it; - if ((begin >= entry->start && begin < entry->end) // start of new within old - && (end > entry->start && end <= entry->end)) { // end of new within old - return true; - } - } if (error_msg != nullptr) { PrintFileToLog("/proc/self/maps", LogSeverity::ERROR); *error_msg = StringPrintf("Requested region 0x%08" PRIxPTR "-0x%08" PRIxPTR " does not overlap " @@ -186,36 +152,6 @@ bool MemMap::ContainedWithinExistingMap(uint8_t* ptr, size_t size, std::string* return false; } -// Return true if the address range does not conflict with any /proc/self/maps entry. -static bool CheckNonOverlapping(uintptr_t begin, - uintptr_t end, - std::string* error_msg) { - std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true)); - if (map.get() == nullptr) { - *error_msg = StringPrintf("Failed to build process map"); - return false; - } - ScopedBacktraceMapIteratorLock lock(map.get()); - for (BacktraceMap::iterator it = map->begin(); it != map->end(); ++it) { - const backtrace_map_t* entry = *it; - if ((begin >= entry->start && begin < entry->end) // start of new within old - || (end > entry->start && end < entry->end) // end of new within old - || (begin <= entry->start && end > entry->end)) { // start/end of new includes all of old - std::ostringstream map_info; - map_info << std::make_pair(it, map->end()); - *error_msg = StringPrintf("Requested region 0x%08" PRIxPTR "-0x%08" PRIxPTR " overlaps with " - "existing map 0x%08" PRIxPTR "-0x%08" PRIxPTR " (%s)\n%s", - begin, end, - static_cast<uintptr_t>(entry->start), - static_cast<uintptr_t>(entry->end), - entry->name.c_str(), - map_info.str().c_str()); - return false; - } - } - return true; -} - // CheckMapRequest to validate a non-MAP_FAILED mmap result based on // the expected value, calling munmap if validation fails, giving the // reason in error_msg. @@ -236,7 +172,6 @@ static bool CheckMapRequest(uint8_t* expected_ptr, void* actual_ptr, size_t byte uintptr_t actual = reinterpret_cast<uintptr_t>(actual_ptr); uintptr_t expected = reinterpret_cast<uintptr_t>(expected_ptr); - uintptr_t limit = expected + byte_count; if (expected_ptr == actual_ptr) { return true; @@ -256,15 +191,16 @@ static bool CheckMapRequest(uint8_t* expected_ptr, void* actual_ptr, size_t byte // true, even if there is no overlap // - There might have been an overlap at the point of mmap, but the // overlapping region has since been unmapped. - std::string error_detail; - CheckNonOverlapping(expected, limit, &error_detail); + + // Tell the client the mappings that were in place at the time. + if (kIsDebugBuild) { + PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); + } + std::ostringstream os; os << StringPrintf("Failed to mmap at expected address, mapped at " "0x%08" PRIxPTR " instead of 0x%08" PRIxPTR, actual, expected); - if (!error_detail.empty()) { - os << " : " << error_detail; - } *error_msg = os.str(); } return false; diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp index b2c041c81f..9d49f371f8 100644 --- a/libdexfile/Android.bp +++ b/libdexfile/Android.bp @@ -55,6 +55,7 @@ cc_defaults { }, generated_sources: ["dexfile_operator_srcs"], shared_libs: [ + "libartbase", // Important note: relying on libartbase's header_lib is perfectly acceptable. // However, relying on the libartbase shared library introduces further, possibly cyclic, // dependencies for clients outside of ART. diff --git a/patchoat/Android.bp b/patchoat/Android.bp index 0e8e517cd4..1e2f328ffd 100644 --- a/patchoat/Android.bp +++ b/patchoat/Android.bp @@ -25,6 +25,7 @@ cc_defaults { }, }, shared_libs: [ + "libartbase", "libbase", "libcrypto", // For computing the digest of image file ], diff --git a/runtime/Android.bp b/runtime/Android.bp index 64e6796ba0..472f8ce02f 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -32,7 +32,6 @@ cc_defaults { "art_field.cc", "art_method.cc", "barrier.cc", - "base/file_utils.cc", "base/mem_map_arena_pool.cc", "base/mutex.cc", "base/quasi_atomic.cc", @@ -207,7 +206,6 @@ cc_defaults { "well_known_classes.cc", "arch/context.cc", - "arch/instruction_set.cc", "arch/instruction_set_features.cc", "arch/memcmp16.cc", "arch/arm/instruction_set_features_arm.cc", @@ -420,7 +418,6 @@ gensrcs { cmd: "$(location generate_operator_out) art/runtime $(in) > $(out)", tools: ["generate_operator_out"], srcs: [ - "arch/instruction_set.h", "base/mutex.h", "class_loader_context.h", "class_status.h", @@ -531,7 +528,6 @@ art_cc_test { ], srcs: [ "arch/arch_test.cc", - "arch/instruction_set_test.cc", "arch/instruction_set_features_test.cc", "arch/memcmp16_test.cc", "arch/stub_test.cc", @@ -542,7 +538,6 @@ art_cc_test { "arch/x86/instruction_set_features_x86_test.cc", "arch/x86_64/instruction_set_features_x86_64_test.cc", "barrier_test.cc", - "base/file_utils_test.cc", "base/mutex_test.cc", "base/timing_logger_test.cc", "cha_test.cc", diff --git a/runtime/arch/code_offset.h b/runtime/arch/code_offset.h index 8e8dde4c4c..f0c6d22ef2 100644 --- a/runtime/arch/code_offset.h +++ b/runtime/arch/code_offset.h @@ -21,9 +21,9 @@ #include <android-base/logging.h> +#include "arch/instruction_set.h" #include "base/bit_utils.h" #include "base/macros.h" -#include "instruction_set.h" namespace art { diff --git a/runtime/arch/instruction_set_features.h b/runtime/arch/instruction_set_features.h index 5f1a507f7a..c31c927668 100644 --- a/runtime/arch/instruction_set_features.h +++ b/runtime/arch/instruction_set_features.h @@ -21,8 +21,8 @@ #include <ostream> #include <vector> +#include "arch/instruction_set.h" #include "base/macros.h" -#include "instruction_set.h" namespace art { diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 4141a37366..9c8b4383dc 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -4850,6 +4850,9 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass, const uint32_t field_idx = field->GetDexFieldIndex(); ArtField* resolved_field = dex_cache->GetResolvedField(field_idx, image_pointer_size_); if (resolved_field == nullptr) { + // Populating cache of a dex file which defines `klass` should always be allowed. + DCHECK_EQ(hiddenapi::GetMemberAction( + field, class_loader.Get(), dex_cache.Get(), hiddenapi::kNone), hiddenapi::kAllow); dex_cache->SetResolvedField(field_idx, field, image_pointer_size_); } else { DCHECK_EQ(field, resolved_field); @@ -8053,26 +8056,8 @@ ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx, return nullptr; } DCHECK(klass->IsResolved()); - Thread* self = is_static ? Thread::Current() : nullptr; - - // First try to find a field declared directly by `klass` by the field index. - ArtField* resolved_field = is_static - ? mirror::Class::FindStaticField(self, klass, dex_cache, field_idx) - : klass->FindInstanceField(dex_cache, field_idx); - - if (resolved_field == nullptr) { - // If not found in `klass` by field index, search the class hierarchy using the name and type. - const char* name = dex_file.GetFieldName(field_id); - const char* type = dex_file.GetFieldTypeDescriptor(field_id); - resolved_field = is_static - ? mirror::Class::FindStaticField(self, klass, name, type) - : klass->FindInstanceField(name, type); - } - if (resolved_field != nullptr) { - dex_cache->SetResolvedField(field_idx, resolved_field, image_pointer_size_); - } - return resolved_field; + return FindResolvedField(klass, dex_cache, class_loader, field_idx, is_static); } ArtField* ClassLinker::ResolveField(uint32_t field_idx, @@ -8087,39 +8072,18 @@ ArtField* ClassLinker::ResolveField(uint32_t field_idx, } const DexFile& dex_file = *dex_cache->GetDexFile(); const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); - Thread* const self = Thread::Current(); ObjPtr<mirror::Class> klass = ResolveType(field_id.class_idx_, dex_cache, class_loader); if (klass == nullptr) { DCHECK(Thread::Current()->IsExceptionPending()); return nullptr; } - if (is_static) { - resolved = mirror::Class::FindStaticField(self, klass, dex_cache.Get(), field_idx); - } else { - resolved = klass->FindInstanceField(dex_cache.Get(), field_idx); - } - + resolved = FindResolvedField(klass, dex_cache.Get(), class_loader.Get(), field_idx, is_static); if (resolved == nullptr) { const char* name = dex_file.GetFieldName(field_id); const char* type = dex_file.GetFieldTypeDescriptor(field_id); - if (is_static) { - resolved = mirror::Class::FindStaticField(self, klass, name, type); - } else { - resolved = klass->FindInstanceField(name, type); - } - } - - if (resolved == nullptr || - hiddenapi::GetMemberAction( - resolved, class_loader.Get(), dex_cache.Get(), hiddenapi::kLinking) == hiddenapi::kDeny) { - const char* name = dex_file.GetFieldName(field_id); - const char* type = dex_file.GetFieldTypeDescriptor(field_id); ThrowNoSuchFieldError(is_static ? "static " : "instance ", klass, type, name); - return nullptr; } - - dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_); return resolved; } @@ -8134,26 +8098,77 @@ ArtField* ClassLinker::ResolveFieldJLS(uint32_t field_idx, } const DexFile& dex_file = *dex_cache->GetDexFile(); const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); - Thread* self = Thread::Current(); ObjPtr<mirror::Class> klass = ResolveType(field_id.class_idx_, dex_cache, class_loader); if (klass == nullptr) { DCHECK(Thread::Current()->IsExceptionPending()); return nullptr; } - StringPiece name(dex_file.GetFieldName(field_id)); - StringPiece type(dex_file.GetFieldTypeDescriptor(field_id)); + resolved = FindResolvedFieldJLS(klass, dex_cache.Get(), class_loader.Get(), field_idx); + if (resolved == nullptr) { + const char* name = dex_file.GetFieldName(field_id); + const char* type = dex_file.GetFieldTypeDescriptor(field_id); + ThrowNoSuchFieldError("", klass, type, name); + } + return resolved; +} + +ArtField* ClassLinker::FindResolvedField(ObjPtr<mirror::Class> klass, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader, + uint32_t field_idx, + bool is_static) { + ArtField* resolved = nullptr; + Thread* self = is_static ? Thread::Current() : nullptr; + const DexFile& dex_file = *dex_cache->GetDexFile(); + + resolved = is_static ? mirror::Class::FindStaticField(self, klass, dex_cache, field_idx) + : klass->FindInstanceField(dex_cache, field_idx); + + if (resolved == nullptr) { + const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); + const char* name = dex_file.GetFieldName(field_id); + const char* type = dex_file.GetFieldTypeDescriptor(field_id); + resolved = is_static ? mirror::Class::FindStaticField(self, klass, name, type) + : klass->FindInstanceField(name, type); + } + + if (resolved != nullptr && + hiddenapi::GetMemberAction( + resolved, class_loader, dex_cache, hiddenapi::kLinking) == hiddenapi::kDeny) { + resolved = nullptr; + } + + if (resolved != nullptr) { + dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_); + } + + return resolved; +} + +ArtField* ClassLinker::FindResolvedFieldJLS(ObjPtr<mirror::Class> klass, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader, + uint32_t field_idx) { + ArtField* resolved = nullptr; + Thread* self = Thread::Current(); + const DexFile& dex_file = *dex_cache->GetDexFile(); + const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); + + const char* name = dex_file.GetFieldName(field_id); + const char* type = dex_file.GetFieldTypeDescriptor(field_id); resolved = mirror::Class::FindField(self, klass, name, type); + if (resolved != nullptr && hiddenapi::GetMemberAction( - resolved, class_loader.Get(), dex_cache.Get(), hiddenapi::kLinking) == hiddenapi::kDeny) { + resolved, class_loader, dex_cache, hiddenapi::kLinking) == hiddenapi::kDeny) { resolved = nullptr; } + if (resolved != nullptr) { dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_); - } else { - ThrowNoSuchFieldError("", klass, type, name); } + return resolved; } diff --git a/runtime/class_linker.h b/runtime/class_linker.h index e935d1dfb8..60cff9ee37 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -392,6 +392,27 @@ class ClassLinker { REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_); + // Find a field with a given ID from the DexFile associated with the given DexCache + // and ClassLoader, storing the result in DexCache. The declaring class is assumed + // to have been already resolved into `klass`. The `is_static` argument is used to + // determine if we are resolving a static or non-static field. + ArtField* FindResolvedField(ObjPtr<mirror::Class> klass, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader, + uint32_t field_idx, + bool is_static) + REQUIRES_SHARED(Locks::mutator_lock_); + + // Find a field with a given ID from the DexFile associated with the given DexCache + // and ClassLoader, storing the result in DexCache. The declaring class is assumed + // to have been already resolved into `klass`. No is_static argument is provided + // so that Java field resolution semantics are followed. + ArtField* FindResolvedFieldJLS(ObjPtr<mirror::Class> klass, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader, + uint32_t field_idx) + REQUIRES_SHARED(Locks::mutator_lock_); + // Resolve a method type with a given ID from the DexFile associated with a given DexCache // and ClassLoader, storing the result in the DexCache. ObjPtr<mirror::MethodType> ResolveMethodType(Thread* self, diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc index 719b4af293..026b5da748 100644 --- a/runtime/elf_file.cc +++ b/runtime/elf_file.cc @@ -1073,6 +1073,29 @@ bool ElfFileImpl<ElfTypes>::GetLoadedSize(size_t* size, std::string* error_msg) return true; } +static InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags) { + switch (e_machine) { + case EM_ARM: + return InstructionSet::kArm; + case EM_AARCH64: + return InstructionSet::kArm64; + case EM_386: + return InstructionSet::kX86; + case EM_X86_64: + return InstructionSet::kX86_64; + case EM_MIPS: { + if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R2 || + (e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) { + return InstructionSet::kMips; + } else if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_64R6) { + return InstructionSet::kMips64; + } + break; + } + } + return InstructionSet::kNone; +} + template <typename ElfTypes> bool ElfFileImpl<ElfTypes>::Load(File* file, bool executable, diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc index 9445ae0c8e..9354d721b7 100644 --- a/runtime/hidden_api.cc +++ b/runtime/hidden_api.cc @@ -158,10 +158,11 @@ inline static int32_t GetEnumValueForLog(AccessMethod access_method) { } void MemberSignature::LogAccessToEventLog(AccessMethod access_method, Action action_taken) { - if (access_method == kLinking) { + if (access_method == kLinking || access_method == kNone) { // Linking warnings come from static analysis/compilation of the bytecode // and can contain false positives (i.e. code that is never run). We choose // not to log these in the event log. + // None does not correspond to actual access, so should also be ignored. return; } ComplexEventLogger log_maker(ACTION_HIDDEN_API_ACCESSED); diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 371678d4d9..ffbc26c647 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -211,12 +211,12 @@ OatFileBase* OatFileBase::OpenOatFile(int zip_fd, return nullptr; } + ret->PreSetup(elf_filename); + if (!ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) { return nullptr; } - ret->PreSetup(elf_filename); - if (!ret->Setup(zip_fd, abs_dex_location, error_msg)) { return nullptr; } @@ -252,12 +252,12 @@ OatFileBase* OatFileBase::OpenOatFile(int zip_fd, return nullptr; } + ret->PreSetup(oat_location); + if (!ret->LoadVdex(vdex_fd, vdex_location, writable, low_4gb, error_msg)) { return nullptr; } - ret->PreSetup(oat_location); - if (!ret->Setup(zip_fd, abs_dex_location, error_msg)) { return nullptr; } diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 7d69927ffb..c00e47f9b8 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -860,6 +860,13 @@ bool OatFileAssistant::DexLocationToOatFilename(const std::string& location, CHECK(oat_filename != nullptr); CHECK(error_msg != nullptr); + // If ANDROID_DATA is not set, return false instead of aborting. + // This can occur for preopt when using a class loader context. + if (GetAndroidDataSafe(error_msg) == nullptr) { + *error_msg = "GetAndroidDataSafe failed: " + *error_msg; + return false; + } + std::string cache_dir = GetDalvikCache(GetInstructionSetString(isa)); if (cache_dir.empty()) { *error_msg = "Dalvik cache directory does not exist"; |