summaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/Android.bp5
-rw-r--r--runtime/arch/code_offset.h2
-rw-r--r--runtime/arch/instruction_set.cc201
-rw-r--r--runtime/arch/instruction_set.h302
-rw-r--r--runtime/arch/instruction_set_features.h2
-rw-r--r--runtime/arch/instruction_set_test.cc70
-rw-r--r--runtime/base/file_utils.cc281
-rw-r--r--runtime/base/file_utils.h82
-rw-r--r--runtime/base/file_utils_test.cc104
-rw-r--r--runtime/class_linker.cc109
-rw-r--r--runtime/class_linker.h21
-rw-r--r--runtime/elf_file.cc23
-rw-r--r--runtime/hidden_api.cc3
-rw-r--r--runtime/oat_file.cc8
-rw-r--r--runtime/oat_file_assistant.cc7
15 files changed, 121 insertions, 1099 deletions
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.cc b/runtime/arch/instruction_set.cc
deleted file mode 100644
index b848eb27fc..0000000000
--- a/runtime/arch/instruction_set.cc
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#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"
-
-namespace art {
-
-void InstructionSetAbort(InstructionSet isa) {
- switch (isa) {
- case InstructionSet::kArm:
- case InstructionSet::kThumb2:
- case InstructionSet::kArm64:
- case InstructionSet::kX86:
- case InstructionSet::kX86_64:
- case InstructionSet::kMips:
- case InstructionSet::kMips64:
- case InstructionSet::kNone:
- LOG(FATAL) << "Unsupported instruction set " << isa;
- UNREACHABLE();
- }
- LOG(FATAL) << "Unknown ISA " << isa;
- UNREACHABLE();
-}
-
-const char* GetInstructionSetString(InstructionSet isa) {
- switch (isa) {
- case InstructionSet::kArm:
- case InstructionSet::kThumb2:
- return "arm";
- case InstructionSet::kArm64:
- return "arm64";
- case InstructionSet::kX86:
- return "x86";
- case InstructionSet::kX86_64:
- return "x86_64";
- case InstructionSet::kMips:
- return "mips";
- case InstructionSet::kMips64:
- return "mips64";
- case InstructionSet::kNone:
- return "none";
- }
- LOG(FATAL) << "Unknown ISA " << isa;
- UNREACHABLE();
-}
-
-InstructionSet GetInstructionSetFromString(const char* isa_str) {
- CHECK(isa_str != nullptr);
-
- if (strcmp("arm", isa_str) == 0) {
- return InstructionSet::kArm;
- } else if (strcmp("arm64", isa_str) == 0) {
- return InstructionSet::kArm64;
- } else if (strcmp("x86", isa_str) == 0) {
- return InstructionSet::kX86;
- } else if (strcmp("x86_64", isa_str) == 0) {
- return InstructionSet::kX86_64;
- } else if (strcmp("mips", isa_str) == 0) {
- return InstructionSet::kMips;
- } else if (strcmp("mips64", isa_str) == 0) {
- return InstructionSet::kMips64;
- }
-
- 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:
- // Fall-through.
- case InstructionSet::kThumb2:
- return kArmAlignment;
- case InstructionSet::kArm64:
- return kArm64Alignment;
- case InstructionSet::kX86:
- // Fall-through.
- case InstructionSet::kX86_64:
- return kX86Alignment;
- case InstructionSet::kMips:
- // Fall-through.
- case InstructionSet::kMips64:
- return kMipsAlignment;
- case InstructionSet::kNone:
- LOG(FATAL) << "ISA kNone does not have alignment.";
- UNREACHABLE();
- }
- LOG(FATAL) << "Unknown ISA " << isa;
- UNREACHABLE();
-}
-
-#if !defined(ART_STACK_OVERFLOW_GAP_arm) || !defined(ART_STACK_OVERFLOW_GAP_arm64) || \
- !defined(ART_STACK_OVERFLOW_GAP_mips) || !defined(ART_STACK_OVERFLOW_GAP_mips64) || \
- !defined(ART_STACK_OVERFLOW_GAP_x86) || !defined(ART_STACK_OVERFLOW_GAP_x86_64)
-#error "Missing defines for stack overflow gap"
-#endif
-
-static constexpr size_t kArmStackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm;
-static constexpr size_t kArm64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm64;
-static constexpr size_t kMipsStackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_mips;
-static constexpr size_t kMips64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_mips64;
-static constexpr size_t kX86StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86;
-static constexpr size_t kX86_64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86_64;
-
-static_assert(IsAligned<kPageSize>(kArmStackOverflowReservedBytes), "ARM gap not page aligned");
-static_assert(IsAligned<kPageSize>(kArm64StackOverflowReservedBytes), "ARM64 gap not page aligned");
-static_assert(IsAligned<kPageSize>(kMipsStackOverflowReservedBytes), "Mips gap not page aligned");
-static_assert(IsAligned<kPageSize>(kMips64StackOverflowReservedBytes),
- "Mips64 gap not page aligned");
-static_assert(IsAligned<kPageSize>(kX86StackOverflowReservedBytes), "X86 gap not page aligned");
-static_assert(IsAligned<kPageSize>(kX86_64StackOverflowReservedBytes),
- "X86_64 gap not page aligned");
-
-#if !defined(ART_FRAME_SIZE_LIMIT)
-#error "ART frame size limit missing"
-#endif
-
-// TODO: Should we require an extra page (RoundUp(SIZE) + kPageSize)?
-static_assert(ART_FRAME_SIZE_LIMIT < kArmStackOverflowReservedBytes, "Frame size limit too large");
-static_assert(ART_FRAME_SIZE_LIMIT < kArm64StackOverflowReservedBytes,
- "Frame size limit too large");
-static_assert(ART_FRAME_SIZE_LIMIT < kMipsStackOverflowReservedBytes,
- "Frame size limit too large");
-static_assert(ART_FRAME_SIZE_LIMIT < kMips64StackOverflowReservedBytes,
- "Frame size limit too large");
-static_assert(ART_FRAME_SIZE_LIMIT < kX86StackOverflowReservedBytes,
- "Frame size limit too large");
-static_assert(ART_FRAME_SIZE_LIMIT < kX86_64StackOverflowReservedBytes,
- "Frame size limit too large");
-
-size_t GetStackOverflowReservedBytes(InstructionSet isa) {
- switch (isa) {
- case InstructionSet::kArm: // Intentional fall-through.
- case InstructionSet::kThumb2:
- return kArmStackOverflowReservedBytes;
-
- case InstructionSet::kArm64:
- return kArm64StackOverflowReservedBytes;
-
- case InstructionSet::kMips:
- return kMipsStackOverflowReservedBytes;
-
- case InstructionSet::kMips64:
- return kMips64StackOverflowReservedBytes;
-
- case InstructionSet::kX86:
- return kX86StackOverflowReservedBytes;
-
- case InstructionSet::kX86_64:
- return kX86_64StackOverflowReservedBytes;
-
- case InstructionSet::kNone:
- LOG(FATAL) << "kNone has no stack overflow size";
- UNREACHABLE();
- }
- LOG(FATAL) << "Unknown instruction set" << isa;
- UNREACHABLE();
-}
-
-} // namespace art
diff --git a/runtime/arch/instruction_set.h b/runtime/arch/instruction_set.h
deleted file mode 100644
index 6434005dda..0000000000
--- a/runtime/arch/instruction_set.h
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_ARCH_INSTRUCTION_SET_H_
-#define ART_RUNTIME_ARCH_INSTRUCTION_SET_H_
-
-#include <iosfwd>
-#include <string>
-
-#include "base/enums.h"
-#include "base/macros.h"
-
-namespace art {
-
-enum class InstructionSet {
- kNone,
- kArm,
- kArm64,
- kThumb2,
- kX86,
- kX86_64,
- kMips,
- kMips64,
- kLast = kMips64
-};
-std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs);
-
-#if defined(__arm__)
-static constexpr InstructionSet kRuntimeISA = InstructionSet::kArm;
-#elif defined(__aarch64__)
-static constexpr InstructionSet kRuntimeISA = InstructionSet::kArm64;
-#elif defined(__mips__) && !defined(__LP64__)
-static constexpr InstructionSet kRuntimeISA = InstructionSet::kMips;
-#elif defined(__mips__) && defined(__LP64__)
-static constexpr InstructionSet kRuntimeISA = InstructionSet::kMips64;
-#elif defined(__i386__)
-static constexpr InstructionSet kRuntimeISA = InstructionSet::kX86;
-#elif defined(__x86_64__)
-static constexpr InstructionSet kRuntimeISA = InstructionSet::kX86_64;
-#else
-static constexpr InstructionSet kRuntimeISA = InstructionSet::kNone;
-#endif
-
-// Architecture-specific pointer sizes
-static constexpr PointerSize kArmPointerSize = PointerSize::k32;
-static constexpr PointerSize kArm64PointerSize = PointerSize::k64;
-static constexpr PointerSize kMipsPointerSize = PointerSize::k32;
-static constexpr PointerSize kMips64PointerSize = PointerSize::k64;
-static constexpr PointerSize kX86PointerSize = PointerSize::k32;
-static constexpr PointerSize kX86_64PointerSize = PointerSize::k64;
-
-// ARM instruction alignment. ARM processors require code to be 4-byte aligned,
-// but ARM ELF requires 8..
-static constexpr size_t kArmAlignment = 8;
-
-// ARM64 instruction alignment. This is the recommended alignment for maximum performance.
-static constexpr size_t kArm64Alignment = 16;
-
-// MIPS instruction alignment. MIPS processors require code to be 4-byte aligned,
-// but 64-bit literals must be 8-byte aligned.
-static constexpr size_t kMipsAlignment = 8;
-
-// X86 instruction alignment. This is the recommended alignment for maximum performance.
-static constexpr size_t kX86Alignment = 16;
-
-// Different than code alignment since code alignment is only first instruction of method.
-static constexpr size_t kThumb2InstructionAlignment = 2;
-static constexpr size_t kArm64InstructionAlignment = 4;
-static constexpr size_t kX86InstructionAlignment = 1;
-static constexpr size_t kX86_64InstructionAlignment = 1;
-static constexpr size_t kMipsInstructionAlignment = 4;
-static constexpr size_t kMips64InstructionAlignment = 4;
-
-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);
-
-constexpr PointerSize GetInstructionSetPointerSize(InstructionSet isa) {
- switch (isa) {
- case InstructionSet::kArm:
- // Fall-through.
- case InstructionSet::kThumb2:
- return kArmPointerSize;
- case InstructionSet::kArm64:
- return kArm64PointerSize;
- case InstructionSet::kX86:
- return kX86PointerSize;
- case InstructionSet::kX86_64:
- return kX86_64PointerSize;
- case InstructionSet::kMips:
- return kMipsPointerSize;
- case InstructionSet::kMips64:
- return kMips64PointerSize;
-
- case InstructionSet::kNone:
- break;
- }
- InstructionSetAbort(isa);
-}
-
-constexpr size_t GetInstructionSetInstructionAlignment(InstructionSet isa) {
- switch (isa) {
- case InstructionSet::kArm:
- // Fall-through.
- case InstructionSet::kThumb2:
- return kThumb2InstructionAlignment;
- case InstructionSet::kArm64:
- return kArm64InstructionAlignment;
- case InstructionSet::kX86:
- return kX86InstructionAlignment;
- case InstructionSet::kX86_64:
- return kX86_64InstructionAlignment;
- case InstructionSet::kMips:
- return kMipsInstructionAlignment;
- case InstructionSet::kMips64:
- return kMips64InstructionAlignment;
-
- case InstructionSet::kNone:
- break;
- }
- InstructionSetAbort(isa);
-}
-
-constexpr bool IsValidInstructionSet(InstructionSet isa) {
- switch (isa) {
- case InstructionSet::kArm:
- case InstructionSet::kThumb2:
- case InstructionSet::kArm64:
- case InstructionSet::kX86:
- case InstructionSet::kX86_64:
- case InstructionSet::kMips:
- case InstructionSet::kMips64:
- return true;
-
- case InstructionSet::kNone:
- return false;
- }
- return false;
-}
-
-size_t GetInstructionSetAlignment(InstructionSet isa);
-
-constexpr bool Is64BitInstructionSet(InstructionSet isa) {
- switch (isa) {
- case InstructionSet::kArm:
- case InstructionSet::kThumb2:
- case InstructionSet::kX86:
- case InstructionSet::kMips:
- return false;
-
- case InstructionSet::kArm64:
- case InstructionSet::kX86_64:
- case InstructionSet::kMips64:
- return true;
-
- case InstructionSet::kNone:
- break;
- }
- InstructionSetAbort(isa);
-}
-
-constexpr PointerSize InstructionSetPointerSize(InstructionSet isa) {
- return Is64BitInstructionSet(isa) ? PointerSize::k64 : PointerSize::k32;
-}
-
-constexpr size_t GetBytesPerGprSpillLocation(InstructionSet isa) {
- switch (isa) {
- case InstructionSet::kArm:
- // Fall-through.
- case InstructionSet::kThumb2:
- return 4;
- case InstructionSet::kArm64:
- return 8;
- case InstructionSet::kX86:
- return 4;
- case InstructionSet::kX86_64:
- return 8;
- case InstructionSet::kMips:
- return 4;
- case InstructionSet::kMips64:
- return 8;
-
- case InstructionSet::kNone:
- break;
- }
- InstructionSetAbort(isa);
-}
-
-constexpr size_t GetBytesPerFprSpillLocation(InstructionSet isa) {
- switch (isa) {
- case InstructionSet::kArm:
- // Fall-through.
- case InstructionSet::kThumb2:
- return 4;
- case InstructionSet::kArm64:
- return 8;
- case InstructionSet::kX86:
- return 8;
- case InstructionSet::kX86_64:
- return 8;
- case InstructionSet::kMips:
- return 4;
- case InstructionSet::kMips64:
- return 8;
-
- case InstructionSet::kNone:
- break;
- }
- InstructionSetAbort(isa);
-}
-
-size_t GetStackOverflowReservedBytes(InstructionSet isa);
-
-// The following definitions create return types for two word-sized entities that will be passed
-// in registers so that memory operations for the interface trampolines can be avoided. The entities
-// are the resolved method and the pointer to the code to be invoked.
-//
-// On x86, ARM32 and MIPS, this is given for a *scalar* 64bit value. The definition thus *must* be
-// uint64_t or long long int.
-//
-// On x86_64, ARM64 and MIPS64, structs are decomposed for allocation, so we can create a structs of
-// two size_t-sized values.
-//
-// We need two operations:
-//
-// 1) A flag value that signals failure. The assembly stubs expect the lower part to be "0".
-// GetTwoWordFailureValue() will return a value that has lower part == 0.
-//
-// 2) A value that combines two word-sized values.
-// GetTwoWordSuccessValue() constructs this.
-//
-// IMPORTANT: If you use this to transfer object pointers, it is your responsibility to ensure
-// that the object does not move or the value is updated. Simple use of this is NOT SAFE
-// when the garbage collector can move objects concurrently. Ensure that required locks
-// are held when using!
-
-#if defined(__i386__) || defined(__arm__) || (defined(__mips__) && !defined(__LP64__))
-typedef uint64_t TwoWordReturn;
-
-// Encodes method_ptr==nullptr and code_ptr==nullptr
-static inline constexpr TwoWordReturn GetTwoWordFailureValue() {
- return 0;
-}
-
-// Use the lower 32b for the method pointer and the upper 32b for the code pointer.
-static inline constexpr TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
- static_assert(sizeof(uint32_t) == sizeof(uintptr_t), "Unexpected size difference");
- uint32_t lo32 = lo;
- uint64_t hi64 = static_cast<uint64_t>(hi);
- return ((hi64 << 32) | lo32);
-}
-
-#elif defined(__x86_64__) || defined(__aarch64__) || (defined(__mips__) && defined(__LP64__))
-
-// Note: TwoWordReturn can't be constexpr for 64-bit targets. We'd need a constexpr constructor,
-// which would violate C-linkage in the entrypoint functions.
-
-struct TwoWordReturn {
- uintptr_t lo;
- uintptr_t hi;
-};
-
-// Encodes method_ptr==nullptr. Leaves random value in code pointer.
-static inline TwoWordReturn GetTwoWordFailureValue() {
- TwoWordReturn ret;
- ret.lo = 0;
- return ret;
-}
-
-// Write values into their respective members.
-static inline TwoWordReturn GetTwoWordSuccessValue(uintptr_t hi, uintptr_t lo) {
- TwoWordReturn ret;
- ret.lo = lo;
- ret.hi = hi;
- return ret;
-}
-#else
-#error "Unsupported architecture"
-#endif
-
-} // namespace art
-
-#endif // ART_RUNTIME_ARCH_INSTRUCTION_SET_H_
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/arch/instruction_set_test.cc b/runtime/arch/instruction_set_test.cc
deleted file mode 100644
index 12a117d7a1..0000000000
--- a/runtime/arch/instruction_set_test.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "instruction_set.h"
-
-#include <gtest/gtest.h>
-
-#include "base/enums.h"
-
-namespace art {
-
-TEST(InstructionSetTest, GetInstructionSetFromString) {
- EXPECT_EQ(InstructionSet::kArm, GetInstructionSetFromString("arm"));
- EXPECT_EQ(InstructionSet::kArm64, GetInstructionSetFromString("arm64"));
- EXPECT_EQ(InstructionSet::kX86, GetInstructionSetFromString("x86"));
- EXPECT_EQ(InstructionSet::kX86_64, GetInstructionSetFromString("x86_64"));
- EXPECT_EQ(InstructionSet::kMips, GetInstructionSetFromString("mips"));
- EXPECT_EQ(InstructionSet::kMips64, GetInstructionSetFromString("mips64"));
- EXPECT_EQ(InstructionSet::kNone, GetInstructionSetFromString("none"));
- EXPECT_EQ(InstructionSet::kNone, GetInstructionSetFromString("random-string"));
-}
-
-TEST(InstructionSetTest, GetInstructionSetString) {
- EXPECT_STREQ("arm", GetInstructionSetString(InstructionSet::kArm));
- EXPECT_STREQ("arm", GetInstructionSetString(InstructionSet::kThumb2));
- EXPECT_STREQ("arm64", GetInstructionSetString(InstructionSet::kArm64));
- EXPECT_STREQ("x86", GetInstructionSetString(InstructionSet::kX86));
- EXPECT_STREQ("x86_64", GetInstructionSetString(InstructionSet::kX86_64));
- EXPECT_STREQ("mips", GetInstructionSetString(InstructionSet::kMips));
- EXPECT_STREQ("mips64", GetInstructionSetString(InstructionSet::kMips64));
- EXPECT_STREQ("none", GetInstructionSetString(InstructionSet::kNone));
-}
-
-TEST(InstructionSetTest, GetInstructionSetInstructionAlignment) {
- EXPECT_EQ(GetInstructionSetInstructionAlignment(InstructionSet::kThumb2),
- kThumb2InstructionAlignment);
- EXPECT_EQ(GetInstructionSetInstructionAlignment(InstructionSet::kArm64),
- kArm64InstructionAlignment);
- EXPECT_EQ(GetInstructionSetInstructionAlignment(InstructionSet::kX86),
- kX86InstructionAlignment);
- EXPECT_EQ(GetInstructionSetInstructionAlignment(InstructionSet::kX86_64),
- kX86_64InstructionAlignment);
- EXPECT_EQ(GetInstructionSetInstructionAlignment(InstructionSet::kMips),
- kMipsInstructionAlignment);
- EXPECT_EQ(GetInstructionSetInstructionAlignment(InstructionSet::kMips64),
- kMips64InstructionAlignment);
-}
-
-TEST(InstructionSetTest, TestRoundTrip) {
- EXPECT_EQ(kRuntimeISA, GetInstructionSetFromString(GetInstructionSetString(kRuntimeISA)));
-}
-
-TEST(InstructionSetTest, PointerSize) {
- EXPECT_EQ(kRuntimePointerSize, GetInstructionSetPointerSize(kRuntimeISA));
-}
-
-} // namespace art
diff --git a/runtime/base/file_utils.cc b/runtime/base/file_utils.cc
deleted file mode 100644
index 537216c198..0000000000
--- a/runtime/base/file_utils.cc
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "file_utils.h"
-
-#include <inttypes.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-// We need dladdr.
-#ifndef __APPLE__
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#define DEFINED_GNU_SOURCE
-#endif
-#include <dlfcn.h>
-#include <libgen.h>
-#ifdef DEFINED_GNU_SOURCE
-#undef _GNU_SOURCE
-#undef DEFINED_GNU_SOURCE
-#endif
-#endif
-
-
-#include <memory>
-
-#include "android-base/stringprintf.h"
-#include "android-base/strings.h"
-
-#include "base/bit_utils.h"
-#include "base/globals.h"
-#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>
-#include <sys/syscall.h>
-#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
-#endif
-
-#if defined(__linux__)
-#include <linux/unistd.h>
-#endif
-
-namespace art {
-
-using android::base::StringAppendF;
-using android::base::StringPrintf;
-
-bool ReadFileToString(const std::string& file_name, std::string* result) {
- File file(file_name, O_RDONLY, false);
- if (!file.IsOpened()) {
- return false;
- }
-
- std::vector<char> buf(8 * KB);
- while (true) {
- int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size()));
- if (n == -1) {
- return false;
- }
- if (n == 0) {
- return true;
- }
- result->append(&buf[0], n);
- }
-}
-
-std::string GetAndroidRootSafe(std::string* error_msg) {
- // Prefer ANDROID_ROOT if it's set.
- const char* android_dir = getenv("ANDROID_ROOT");
- if (android_dir != nullptr) {
- if (!OS::DirectoryExists(android_dir)) {
- *error_msg = StringPrintf("Failed to find ANDROID_ROOT directory %s", android_dir);
- return "";
- }
- return android_dir;
- }
-
- // Check where libart is from, and derive from there. Only do this for non-Mac.
-#ifndef __APPLE__
- {
- Dl_info info;
- if (dladdr(reinterpret_cast<const void*>(&GetAndroidRootSafe), /* out */ &info) != 0) {
- // Make a duplicate of the fname so dirname can modify it.
- UniqueCPtr<char> fname(strdup(info.dli_fname));
-
- char* dir1 = dirname(fname.get()); // This is the lib directory.
- char* dir2 = dirname(dir1); // This is the "system" directory.
- if (OS::DirectoryExists(dir2)) {
- std::string tmp = dir2; // Make a copy here so that fname can be released.
- return tmp;
- }
- }
- }
-#endif
-
- // Try "/system".
- if (!OS::DirectoryExists("/system")) {
- *error_msg = "Failed to find ANDROID_ROOT directory /system";
- return "";
- }
- return "/system";
-}
-
-std::string GetAndroidRoot() {
- std::string error_msg;
- std::string ret = GetAndroidRootSafe(&error_msg);
- if (ret.empty()) {
- LOG(FATAL) << error_msg;
- UNREACHABLE();
- }
- return ret;
-}
-
-
-static const char* GetAndroidDirSafe(const char* env_var,
- const char* default_dir,
- std::string* error_msg) {
- const char* android_dir = getenv(env_var);
- if (android_dir == nullptr) {
- if (OS::DirectoryExists(default_dir)) {
- android_dir = default_dir;
- } else {
- *error_msg = StringPrintf("%s not set and %s does not exist", env_var, default_dir);
- return nullptr;
- }
- }
- if (!OS::DirectoryExists(android_dir)) {
- *error_msg = StringPrintf("Failed to find %s directory %s", env_var, android_dir);
- return nullptr;
- }
- return android_dir;
-}
-
-static const char* GetAndroidDir(const char* env_var, const char* default_dir) {
- std::string error_msg;
- const char* dir = GetAndroidDirSafe(env_var, default_dir, &error_msg);
- if (dir != nullptr) {
- return dir;
- } else {
- LOG(FATAL) << error_msg;
- return nullptr;
- }
-}
-
-const char* GetAndroidData() {
- return GetAndroidDir("ANDROID_DATA", "/data");
-}
-
-const char* GetAndroidDataSafe(std::string* error_msg) {
- return GetAndroidDirSafe("ANDROID_DATA", "/data", error_msg);
-}
-
-std::string GetDefaultBootImageLocation(std::string* error_msg) {
- std::string android_root = GetAndroidRootSafe(error_msg);
- if (android_root.empty()) {
- return "";
- }
- return StringPrintf("%s/framework/boot.art", android_root.c_str());
-}
-
-void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache,
- bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache) {
- CHECK(subdir != nullptr);
- std::string error_msg;
- const char* android_data = GetAndroidDataSafe(&error_msg);
- if (android_data == nullptr) {
- *have_android_data = false;
- *dalvik_cache_exists = false;
- *is_global_cache = false;
- return;
- } else {
- *have_android_data = true;
- }
- const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
- *dalvik_cache = dalvik_cache_root + subdir;
- *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str());
- *is_global_cache = strcmp(android_data, "/data") == 0;
- if (create_if_absent && !*dalvik_cache_exists && !*is_global_cache) {
- // Don't create the system's /data/dalvik-cache/... because it needs special permissions.
- *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) &&
- (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST));
- }
-}
-
-std::string GetDalvikCache(const char* subdir) {
- CHECK(subdir != nullptr);
- const char* android_data = GetAndroidData();
- const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
- const std::string dalvik_cache = dalvik_cache_root + subdir;
- if (!OS::DirectoryExists(dalvik_cache.c_str())) {
- // TODO: Check callers. Traditional behavior is to not abort.
- return "";
- }
- return dalvik_cache;
-}
-
-bool GetDalvikCacheFilename(const char* location, const char* cache_location,
- std::string* filename, std::string* error_msg) {
- if (location[0] != '/') {
- *error_msg = StringPrintf("Expected path in location to be absolute: %s", location);
- return false;
- }
- std::string cache_file(&location[1]); // skip leading slash
- if (!android::base::EndsWith(location, ".dex") &&
- !android::base::EndsWith(location, ".art") &&
- !android::base::EndsWith(location, ".oat")) {
- cache_file += "/";
- cache_file += DexFileLoader::kClassesDex;
- }
- std::replace(cache_file.begin(), cache_file.end(), '/', '@');
- *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str());
- return true;
-}
-
-std::string GetVdexFilename(const std::string& oat_location) {
- return ReplaceFileExtension(oat_location, "vdex");
-}
-
-static void InsertIsaDirectory(const InstructionSet isa, std::string* filename) {
- // in = /foo/bar/baz
- // out = /foo/bar/<isa>/baz
- size_t pos = filename->rfind('/');
- CHECK_NE(pos, std::string::npos) << *filename << " " << isa;
- filename->insert(pos, "/", 1);
- filename->insert(pos + 1, GetInstructionSetString(isa));
-}
-
-std::string GetSystemImageFilename(const char* location, const InstructionSet isa) {
- // location = /system/framework/boot.art
- // filename = /system/framework/<isa>/boot.art
- std::string filename(location);
- InsertIsaDirectory(isa, &filename);
- return filename;
-}
-
-std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) {
- const size_t last_ext = filename.find_last_of("./");
- if (last_ext == std::string::npos || filename[last_ext] != '.') {
- return filename + "." + new_extension;
- } else {
- return filename.substr(0, last_ext + 1) + new_extension;
- }
-}
-
-bool LocationIsOnSystem(const char* path) {
- UniqueCPtr<const char[]> full_path(realpath(path, nullptr));
- return path != nullptr && android::base::StartsWith(full_path.get(), GetAndroidRoot().c_str());
-}
-
-bool LocationIsOnSystemFramework(const char* full_path) {
- std::string error_msg;
- std::string root_path = GetAndroidRootSafe(&error_msg);
- if (root_path.empty()) {
- // Could not find Android root.
- // TODO(dbrazdil): change to stricter GetAndroidRoot() once b/76452688 is resolved.
- return false;
- }
- std::string framework_path = root_path + "/framework/";
- return android::base::StartsWith(full_path, framework_path);
-}
-
-} // namespace art
diff --git a/runtime/base/file_utils.h b/runtime/base/file_utils.h
deleted file mode 100644
index d4f6c576c0..0000000000
--- a/runtime/base/file_utils.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_BASE_FILE_UTILS_H_
-#define ART_RUNTIME_BASE_FILE_UTILS_H_
-
-#include <stdlib.h>
-
-#include <string>
-
-#include <android-base/logging.h>
-
-#include "arch/instruction_set.h"
-
-namespace art {
-
-bool ReadFileToString(const std::string& file_name, std::string* result);
-
-// Find $ANDROID_ROOT, /system, or abort.
-std::string GetAndroidRoot();
-// Find $ANDROID_ROOT, /system, or return an empty string.
-std::string GetAndroidRootSafe(std::string* error_msg);
-
-// Find $ANDROID_DATA, /data, or abort.
-const char* GetAndroidData();
-// Find $ANDROID_DATA, /data, or return null.
-const char* GetAndroidDataSafe(std::string* error_msg);
-
-// Returns the default boot image location (ANDROID_ROOT/framework/boot.art).
-// Returns an empty string if ANDROID_ROOT is not set.
-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.
-// The flag is_global_cache tells whether this cache is /data/dalvik-cache.
-void GetDalvikCache(const char* subdir, bool create_if_absent, std::string* dalvik_cache,
- bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache);
-
-// Returns the absolute dalvik-cache path for a DexFile or OatFile. The path returned will be
-// rooted at cache_location.
-bool GetDalvikCacheFilename(const char* file_location, const char* cache_location,
- std::string* filename, std::string* error_msg);
-
-// Returns the system location for an image
-std::string GetSystemImageFilename(const char* location, InstructionSet isa);
-
-// Returns the vdex filename for the given oat filename.
-std::string GetVdexFilename(const std::string& oat_filename);
-
-// Returns `filename` with the text after the last occurrence of '.' replaced with
-// `extension`. If `filename` does not contain a period, returns a string containing `filename`,
-// a period, and `new_extension`.
-// Example: ReplaceFileExtension("foo.bar", "abc") == "foo.abc"
-// ReplaceFileExtension("foo", "abc") == "foo.abc"
-std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension);
-
-// Return whether the location is on system (i.e. android root).
-bool LocationIsOnSystem(const char* location);
-
-// Return whether the location is on system/framework (i.e. android_root/framework).
-bool LocationIsOnSystemFramework(const char* location);
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_FILE_UTILS_H_
diff --git a/runtime/base/file_utils_test.cc b/runtime/base/file_utils_test.cc
deleted file mode 100644
index e74dfe5e64..0000000000
--- a/runtime/base/file_utils_test.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "base/file_utils.h"
-
-#include <libgen.h>
-#include <stdlib.h>
-
-#include "base/stl_util.h"
-#include "common_runtime_test.h"
-
-namespace art {
-
-class FileUtilsTest : public CommonRuntimeTest {};
-
-TEST_F(FileUtilsTest, GetDalvikCacheFilename) {
- std::string name;
- std::string error;
-
- EXPECT_TRUE(GetDalvikCacheFilename("/system/app/Foo.apk", "/foo", &name, &error)) << error;
- EXPECT_EQ("/foo/system@app@Foo.apk@classes.dex", name);
-
- EXPECT_TRUE(GetDalvikCacheFilename("/data/app/foo-1.apk", "/foo", &name, &error)) << error;
- EXPECT_EQ("/foo/data@app@foo-1.apk@classes.dex", name);
-
- EXPECT_TRUE(GetDalvikCacheFilename("/system/framework/core.jar", "/foo", &name, &error)) << error;
- EXPECT_EQ("/foo/system@framework@core.jar@classes.dex", name);
-
- EXPECT_TRUE(GetDalvikCacheFilename("/system/framework/boot.art", "/foo", &name, &error)) << error;
- EXPECT_EQ("/foo/system@framework@boot.art", name);
-
- EXPECT_TRUE(GetDalvikCacheFilename("/system/framework/boot.oat", "/foo", &name, &error)) << error;
- EXPECT_EQ("/foo/system@framework@boot.oat", name);
-}
-
-TEST_F(FileUtilsTest, GetDalvikCache) {
- EXPECT_STREQ("", GetDalvikCache("should-not-exist123").c_str());
-
- EXPECT_STREQ((android_data_ + "/dalvik-cache/.").c_str(), GetDalvikCache(".").c_str());
-}
-
-
-TEST_F(FileUtilsTest, GetSystemImageFilename) {
- EXPECT_STREQ("/system/framework/arm/boot.art",
- GetSystemImageFilename("/system/framework/boot.art", InstructionSet::kArm).c_str());
-}
-
-TEST_F(FileUtilsTest, GetAndroidRootSafe) {
- std::string error_msg;
-
- // We don't expect null returns for most cases, so don't check and let std::string crash.
-
- // CommonRuntimeTest sets ANDROID_ROOT, so expect this to be the same.
- std::string android_root = GetAndroidRootSafe(&error_msg);
- std::string android_root_env = getenv("ANDROID_ROOT");
- EXPECT_EQ(android_root, android_root_env);
-
- // Set ANDROID_ROOT to something else (but the directory must exist). So use dirname.
- char* root_dup = strdup(android_root_env.c_str());
- char* dir = dirname(root_dup);
- ASSERT_EQ(0, setenv("ANDROID_ROOT", dir, 1 /* overwrite */));
- std::string android_root2 = GetAndroidRootSafe(&error_msg);
- EXPECT_STREQ(dir, android_root2.c_str());
- free(root_dup);
-
- // Set a bogus value for ANDROID_ROOT. This should be an error.
- ASSERT_EQ(0, setenv("ANDROID_ROOT", "/this/is/obviously/bogus", 1 /* overwrite */));
- EXPECT_TRUE(GetAndroidRootSafe(&error_msg) == nullptr);
-
- // Unset ANDROID_ROOT and see that it still returns something (as libart code is running).
- ASSERT_EQ(0, unsetenv("ANDROID_ROOT"));
- std::string android_root3 = GetAndroidRootSafe(&error_msg);
- // This should be the same as the other root (modulo realpath), otherwise the test setup is
- // broken.
- UniqueCPtr<char> real_root(realpath(android_root.c_str(), nullptr));
- UniqueCPtr<char> real_root3(realpath(android_root3.c_str(), nullptr));
- EXPECT_STREQ(real_root.get(), real_root3.get());
-
-
- // Reset ANDROID_ROOT, as other things may depend on it.
- ASSERT_EQ(0, setenv("ANDROID_ROOT", android_root_env.c_str(), 1 /* overwrite */));
-}
-
-TEST_F(FileUtilsTest, ReplaceFileExtension) {
- EXPECT_EQ("/directory/file.vdex", ReplaceFileExtension("/directory/file.oat", "vdex"));
- EXPECT_EQ("/.directory/file.vdex", ReplaceFileExtension("/.directory/file.oat", "vdex"));
- EXPECT_EQ("/directory/file.vdex", ReplaceFileExtension("/directory/file", "vdex"));
- EXPECT_EQ("/.directory/file.vdex", ReplaceFileExtension("/.directory/file", "vdex"));
-}
-
-} // 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";