diff options
Diffstat (limited to 'runtime')
| -rw-r--r-- | runtime/Android.bp | 5 | ||||
| -rw-r--r-- | runtime/arch/code_offset.h | 2 | ||||
| -rw-r--r-- | runtime/arch/instruction_set.cc | 201 | ||||
| -rw-r--r-- | runtime/arch/instruction_set.h | 302 | ||||
| -rw-r--r-- | runtime/arch/instruction_set_features.h | 2 | ||||
| -rw-r--r-- | runtime/arch/instruction_set_test.cc | 70 | ||||
| -rw-r--r-- | runtime/base/file_utils.cc | 281 | ||||
| -rw-r--r-- | runtime/base/file_utils.h | 82 | ||||
| -rw-r--r-- | runtime/base/file_utils_test.cc | 104 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 109 | ||||
| -rw-r--r-- | runtime/class_linker.h | 21 | ||||
| -rw-r--r-- | runtime/elf_file.cc | 23 | ||||
| -rw-r--r-- | runtime/hidden_api.cc | 3 | ||||
| -rw-r--r-- | runtime/oat_file.cc | 8 | ||||
| -rw-r--r-- | runtime/oat_file_assistant.cc | 7 |
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"; |