blob: b848eb27fcceb1fa57d97aaf4f1cd9029d7c35a0 [file] [log] [blame]
Ian Rogersd582fa42014-11-05 23:46:43 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "instruction_set.h"
18
Andreas Gampe6f611412015-01-21 22:25:24 -080019// Explicitly include our own elf.h to avoid Linux and other dependencies.
20#include "../elf.h"
Andreas Gampe705543e2017-05-24 13:20:49 -070021#include "android-base/logging.h"
Andreas Gamped1262282016-08-11 18:35:58 -070022#include "base/bit_utils.h"
David Sehr1979c642018-04-26 14:41:18 -070023#include "base/globals.h"
Ian Rogersd582fa42014-11-05 23:46:43 -080024
25namespace art {
26
Andreas Gampebda1d602016-08-29 17:43:45 -070027void InstructionSetAbort(InstructionSet isa) {
28 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +000029 case InstructionSet::kArm:
30 case InstructionSet::kThumb2:
31 case InstructionSet::kArm64:
32 case InstructionSet::kX86:
33 case InstructionSet::kX86_64:
34 case InstructionSet::kMips:
35 case InstructionSet::kMips64:
36 case InstructionSet::kNone:
Andreas Gampebda1d602016-08-29 17:43:45 -070037 LOG(FATAL) << "Unsupported instruction set " << isa;
38 UNREACHABLE();
Andreas Gampebda1d602016-08-29 17:43:45 -070039 }
Andreas Gampe705543e2017-05-24 13:20:49 -070040 LOG(FATAL) << "Unknown ISA " << isa;
41 UNREACHABLE();
Andreas Gampebda1d602016-08-29 17:43:45 -070042}
43
44const char* GetInstructionSetString(InstructionSet isa) {
Ian Rogersd582fa42014-11-05 23:46:43 -080045 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +000046 case InstructionSet::kArm:
47 case InstructionSet::kThumb2:
Ian Rogersd582fa42014-11-05 23:46:43 -080048 return "arm";
Vladimir Marko33bff252017-11-01 14:35:42 +000049 case InstructionSet::kArm64:
Ian Rogersd582fa42014-11-05 23:46:43 -080050 return "arm64";
Vladimir Marko33bff252017-11-01 14:35:42 +000051 case InstructionSet::kX86:
Ian Rogersd582fa42014-11-05 23:46:43 -080052 return "x86";
Vladimir Marko33bff252017-11-01 14:35:42 +000053 case InstructionSet::kX86_64:
Ian Rogersd582fa42014-11-05 23:46:43 -080054 return "x86_64";
Vladimir Marko33bff252017-11-01 14:35:42 +000055 case InstructionSet::kMips:
Ian Rogersd582fa42014-11-05 23:46:43 -080056 return "mips";
Vladimir Marko33bff252017-11-01 14:35:42 +000057 case InstructionSet::kMips64:
Ian Rogersd582fa42014-11-05 23:46:43 -080058 return "mips64";
Vladimir Marko33bff252017-11-01 14:35:42 +000059 case InstructionSet::kNone:
Ian Rogersd582fa42014-11-05 23:46:43 -080060 return "none";
Ian Rogersd582fa42014-11-05 23:46:43 -080061 }
Andreas Gampe705543e2017-05-24 13:20:49 -070062 LOG(FATAL) << "Unknown ISA " << isa;
63 UNREACHABLE();
Ian Rogersd582fa42014-11-05 23:46:43 -080064}
65
66InstructionSet GetInstructionSetFromString(const char* isa_str) {
67 CHECK(isa_str != nullptr);
68
69 if (strcmp("arm", isa_str) == 0) {
Vladimir Marko33bff252017-11-01 14:35:42 +000070 return InstructionSet::kArm;
Ian Rogersd582fa42014-11-05 23:46:43 -080071 } else if (strcmp("arm64", isa_str) == 0) {
Vladimir Marko33bff252017-11-01 14:35:42 +000072 return InstructionSet::kArm64;
Ian Rogersd582fa42014-11-05 23:46:43 -080073 } else if (strcmp("x86", isa_str) == 0) {
Vladimir Marko33bff252017-11-01 14:35:42 +000074 return InstructionSet::kX86;
Ian Rogersd582fa42014-11-05 23:46:43 -080075 } else if (strcmp("x86_64", isa_str) == 0) {
Vladimir Marko33bff252017-11-01 14:35:42 +000076 return InstructionSet::kX86_64;
Ian Rogersd582fa42014-11-05 23:46:43 -080077 } else if (strcmp("mips", isa_str) == 0) {
Vladimir Marko33bff252017-11-01 14:35:42 +000078 return InstructionSet::kMips;
Ian Rogersd582fa42014-11-05 23:46:43 -080079 } else if (strcmp("mips64", isa_str) == 0) {
Vladimir Marko33bff252017-11-01 14:35:42 +000080 return InstructionSet::kMips64;
Ian Rogersd582fa42014-11-05 23:46:43 -080081 }
82
Vladimir Marko33bff252017-11-01 14:35:42 +000083 return InstructionSet::kNone;
Ian Rogersd582fa42014-11-05 23:46:43 -080084}
85
Andreas Gampe6f611412015-01-21 22:25:24 -080086InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags) {
87 switch (e_machine) {
88 case EM_ARM:
Vladimir Marko33bff252017-11-01 14:35:42 +000089 return InstructionSet::kArm;
Andreas Gampe6f611412015-01-21 22:25:24 -080090 case EM_AARCH64:
Vladimir Marko33bff252017-11-01 14:35:42 +000091 return InstructionSet::kArm64;
Andreas Gampe6f611412015-01-21 22:25:24 -080092 case EM_386:
Vladimir Marko33bff252017-11-01 14:35:42 +000093 return InstructionSet::kX86;
Andreas Gampe6f611412015-01-21 22:25:24 -080094 case EM_X86_64:
Vladimir Marko33bff252017-11-01 14:35:42 +000095 return InstructionSet::kX86_64;
Andreas Gampe6f611412015-01-21 22:25:24 -080096 case EM_MIPS: {
97 if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R2 ||
98 (e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) {
Vladimir Marko33bff252017-11-01 14:35:42 +000099 return InstructionSet::kMips;
Andreas Gampe6f611412015-01-21 22:25:24 -0800100 } else if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_64R6) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000101 return InstructionSet::kMips64;
Andreas Gampe6f611412015-01-21 22:25:24 -0800102 }
103 break;
104 }
105 }
Vladimir Marko33bff252017-11-01 14:35:42 +0000106 return InstructionSet::kNone;
Andreas Gampe6f611412015-01-21 22:25:24 -0800107}
108
Ian Rogersd582fa42014-11-05 23:46:43 -0800109size_t GetInstructionSetAlignment(InstructionSet isa) {
110 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000111 case InstructionSet::kArm:
Ian Rogersd582fa42014-11-05 23:46:43 -0800112 // Fall-through.
Vladimir Marko33bff252017-11-01 14:35:42 +0000113 case InstructionSet::kThumb2:
Ian Rogersd582fa42014-11-05 23:46:43 -0800114 return kArmAlignment;
Vladimir Marko33bff252017-11-01 14:35:42 +0000115 case InstructionSet::kArm64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800116 return kArm64Alignment;
Vladimir Marko33bff252017-11-01 14:35:42 +0000117 case InstructionSet::kX86:
Ian Rogersd582fa42014-11-05 23:46:43 -0800118 // Fall-through.
Vladimir Marko33bff252017-11-01 14:35:42 +0000119 case InstructionSet::kX86_64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800120 return kX86Alignment;
Vladimir Marko33bff252017-11-01 14:35:42 +0000121 case InstructionSet::kMips:
Andreas Gampe57b34292015-01-14 15:45:59 -0800122 // Fall-through.
Vladimir Marko33bff252017-11-01 14:35:42 +0000123 case InstructionSet::kMips64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800124 return kMipsAlignment;
Vladimir Marko33bff252017-11-01 14:35:42 +0000125 case InstructionSet::kNone:
Ian Rogersd582fa42014-11-05 23:46:43 -0800126 LOG(FATAL) << "ISA kNone does not have alignment.";
127 UNREACHABLE();
Ian Rogersd582fa42014-11-05 23:46:43 -0800128 }
Andreas Gampe705543e2017-05-24 13:20:49 -0700129 LOG(FATAL) << "Unknown ISA " << isa;
130 UNREACHABLE();
Ian Rogersd582fa42014-11-05 23:46:43 -0800131}
132
Andreas Gamped1262282016-08-11 18:35:58 -0700133#if !defined(ART_STACK_OVERFLOW_GAP_arm) || !defined(ART_STACK_OVERFLOW_GAP_arm64) || \
134 !defined(ART_STACK_OVERFLOW_GAP_mips) || !defined(ART_STACK_OVERFLOW_GAP_mips64) || \
135 !defined(ART_STACK_OVERFLOW_GAP_x86) || !defined(ART_STACK_OVERFLOW_GAP_x86_64)
136#error "Missing defines for stack overflow gap"
137#endif
Ian Rogersd582fa42014-11-05 23:46:43 -0800138
Andreas Gamped1262282016-08-11 18:35:58 -0700139static constexpr size_t kArmStackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm;
140static constexpr size_t kArm64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm64;
141static constexpr size_t kMipsStackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_mips;
142static constexpr size_t kMips64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_mips64;
143static constexpr size_t kX86StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86;
144static constexpr size_t kX86_64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86_64;
145
146static_assert(IsAligned<kPageSize>(kArmStackOverflowReservedBytes), "ARM gap not page aligned");
147static_assert(IsAligned<kPageSize>(kArm64StackOverflowReservedBytes), "ARM64 gap not page aligned");
148static_assert(IsAligned<kPageSize>(kMipsStackOverflowReservedBytes), "Mips gap not page aligned");
149static_assert(IsAligned<kPageSize>(kMips64StackOverflowReservedBytes),
150 "Mips64 gap not page aligned");
151static_assert(IsAligned<kPageSize>(kX86StackOverflowReservedBytes), "X86 gap not page aligned");
152static_assert(IsAligned<kPageSize>(kX86_64StackOverflowReservedBytes),
153 "X86_64 gap not page aligned");
154
155#if !defined(ART_FRAME_SIZE_LIMIT)
156#error "ART frame size limit missing"
157#endif
158
159// TODO: Should we require an extra page (RoundUp(SIZE) + kPageSize)?
160static_assert(ART_FRAME_SIZE_LIMIT < kArmStackOverflowReservedBytes, "Frame size limit too large");
161static_assert(ART_FRAME_SIZE_LIMIT < kArm64StackOverflowReservedBytes,
162 "Frame size limit too large");
163static_assert(ART_FRAME_SIZE_LIMIT < kMipsStackOverflowReservedBytes,
164 "Frame size limit too large");
165static_assert(ART_FRAME_SIZE_LIMIT < kMips64StackOverflowReservedBytes,
166 "Frame size limit too large");
167static_assert(ART_FRAME_SIZE_LIMIT < kX86StackOverflowReservedBytes,
168 "Frame size limit too large");
169static_assert(ART_FRAME_SIZE_LIMIT < kX86_64StackOverflowReservedBytes,
170 "Frame size limit too large");
Ian Rogersd582fa42014-11-05 23:46:43 -0800171
172size_t GetStackOverflowReservedBytes(InstructionSet isa) {
173 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000174 case InstructionSet::kArm: // Intentional fall-through.
175 case InstructionSet::kThumb2:
Ian Rogersd582fa42014-11-05 23:46:43 -0800176 return kArmStackOverflowReservedBytes;
177
Vladimir Marko33bff252017-11-01 14:35:42 +0000178 case InstructionSet::kArm64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800179 return kArm64StackOverflowReservedBytes;
180
Vladimir Marko33bff252017-11-01 14:35:42 +0000181 case InstructionSet::kMips:
Ian Rogersd582fa42014-11-05 23:46:43 -0800182 return kMipsStackOverflowReservedBytes;
183
Vladimir Marko33bff252017-11-01 14:35:42 +0000184 case InstructionSet::kMips64:
Andreas Gampe57b34292015-01-14 15:45:59 -0800185 return kMips64StackOverflowReservedBytes;
186
Vladimir Marko33bff252017-11-01 14:35:42 +0000187 case InstructionSet::kX86:
Ian Rogersd582fa42014-11-05 23:46:43 -0800188 return kX86StackOverflowReservedBytes;
189
Vladimir Marko33bff252017-11-01 14:35:42 +0000190 case InstructionSet::kX86_64:
Ian Rogersd582fa42014-11-05 23:46:43 -0800191 return kX86_64StackOverflowReservedBytes;
192
Vladimir Marko33bff252017-11-01 14:35:42 +0000193 case InstructionSet::kNone:
Ian Rogersd582fa42014-11-05 23:46:43 -0800194 LOG(FATAL) << "kNone has no stack overflow size";
195 UNREACHABLE();
Ian Rogersd582fa42014-11-05 23:46:43 -0800196 }
Andreas Gampe705543e2017-05-24 13:20:49 -0700197 LOG(FATAL) << "Unknown instruction set" << isa;
198 UNREACHABLE();
Ian Rogersd582fa42014-11-05 23:46:43 -0800199}
200
201} // namespace art