Merge "Use std::cout for dexanalyze logging"
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 9e5cd80..492f9ce 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -1067,18 +1067,12 @@
}
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 @@
}
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 @@
}
}
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 50abdd3..c8a06ed 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -19,11 +19,13 @@
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 @@
generated_sources: ["art_libartbase_operator_srcs"],
cflags: ["-DBUILDING_LIBART=1"],
shared_libs: [
- "libbacktrace",
"liblog",
// For ashmem.
"libcutils",
@@ -81,6 +82,7 @@
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_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
similarity index 88%
rename from runtime/arch/instruction_set.cc
rename to libartbase/arch/instruction_set.cc
index b848eb2..a187663 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 @@
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
similarity index 97%
rename from runtime/arch/instruction_set.h
rename to libartbase/arch/instruction_set.h
index 6434005..06bd53a 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 @@
// 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 @@
} // 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
similarity index 100%
rename from runtime/arch/instruction_set_test.cc
rename to libartbase/arch/instruction_set_test.cc
diff --git a/runtime/base/file_utils.cc b/libartbase/base/file_utils.cc
similarity index 98%
rename from runtime/base/file_utils.cc
rename to libartbase/base/file_utils.cc
index 537216c..9450e1e 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 @@
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 @@
!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
similarity index 95%
rename from runtime/base/file_utils.h
rename to libartbase/base/file_utils.h
index d4f6c57..063393b 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 @@
// 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 @@
} // 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
similarity index 100%
rename from runtime/base/file_utils_test.cc
rename to libartbase/base/file_utils_test.cc
diff --git a/libartbase/base/mem_map.cc b/libartbase/base/mem_map.cc
index 9a1392c..c455fed 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 @@
// 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 @@
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 @@
}
}
- 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 @@
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 @@
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 @@
// 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 b2c041c..9d49f37 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -55,6 +55,7 @@
},
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 0e8e517..1e2f328 100644
--- a/patchoat/Android.bp
+++ b/patchoat/Android.bp
@@ -25,6 +25,7 @@
},
},
shared_libs: [
+ "libartbase",
"libbase",
"libcrypto", // For computing the digest of image file
],
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 64e6796..472f8ce 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -32,7 +32,6 @@
"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 @@
"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 @@
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 @@
],
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 @@
"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 8e8dde4..f0c6d22 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 5f1a507..c31c927 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 4141a37..9c8b438 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4850,6 +4850,9 @@
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 @@
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 @@
}
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,29 +8098,80 @@
}
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 = mirror::Class::FindField(self, klass, name, type);
- if (resolved != nullptr &&
- hiddenapi::GetMemberAction(
- resolved, class_loader.Get(), dex_cache.Get(), hiddenapi::kLinking) == hiddenapi::kDeny) {
- resolved = nullptr;
- }
- if (resolved != nullptr) {
- dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_);
- } else {
+ 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, dex_cache, hiddenapi::kLinking) == hiddenapi::kDeny) {
+ resolved = nullptr;
+ }
+
+ if (resolved != nullptr) {
+ dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_);
+ }
+
+ return resolved;
+}
+
ObjPtr<mirror::MethodType> ClassLinker::ResolveMethodType(
Thread* self,
uint32_t proto_idx,
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index e935d1d..60cff9e 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -392,6 +392,27 @@
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 719b4af..026b5da 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1073,6 +1073,29 @@
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 9445ae0..9354d72 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -158,10 +158,11 @@
}
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 371678d..ffbc26c 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -211,12 +211,12 @@
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 @@
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 7d69927..c00e47f 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -860,6 +860,13 @@
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";