1 /*
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
19 // Explicitly include our own elf.h to avoid Linux and other dependencies.
20 #include "../elf.h"
21 #include "base/bit_utils.h"
22 #include "base/logging.h"
23 #include "globals.h"
24
25 namespace art {
26
InstructionSetAbort(InstructionSet isa)27 void InstructionSetAbort(InstructionSet isa) {
28 switch (isa) {
29 case kArm:
30 case kThumb2:
31 case kArm64:
32 case kX86:
33 case kX86_64:
34 case kMips:
35 case kMips64:
36 case kNone:
37 LOG(FATAL) << "Unsupported instruction set " << isa;
38 UNREACHABLE();
39
40 default:
41 LOG(FATAL) << "Unknown ISA " << isa;
42 UNREACHABLE();
43 }
44 }
45
GetInstructionSetString(InstructionSet isa)46 const char* GetInstructionSetString(InstructionSet isa) {
47 switch (isa) {
48 case kArm:
49 case kThumb2:
50 return "arm";
51 case kArm64:
52 return "arm64";
53 case kX86:
54 return "x86";
55 case kX86_64:
56 return "x86_64";
57 case kMips:
58 return "mips";
59 case kMips64:
60 return "mips64";
61 case kNone:
62 return "none";
63 default:
64 LOG(FATAL) << "Unknown ISA " << isa;
65 UNREACHABLE();
66 }
67 }
68
GetInstructionSetFromString(const char * isa_str)69 InstructionSet GetInstructionSetFromString(const char* isa_str) {
70 CHECK(isa_str != nullptr);
71
72 if (strcmp("arm", isa_str) == 0) {
73 return kArm;
74 } else if (strcmp("arm64", isa_str) == 0) {
75 return kArm64;
76 } else if (strcmp("x86", isa_str) == 0) {
77 return kX86;
78 } else if (strcmp("x86_64", isa_str) == 0) {
79 return kX86_64;
80 } else if (strcmp("mips", isa_str) == 0) {
81 return kMips;
82 } else if (strcmp("mips64", isa_str) == 0) {
83 return kMips64;
84 }
85
86 return kNone;
87 }
88
GetInstructionSetFromELF(uint16_t e_machine,uint32_t e_flags)89 InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags) {
90 switch (e_machine) {
91 case EM_ARM:
92 return kArm;
93 case EM_AARCH64:
94 return kArm64;
95 case EM_386:
96 return kX86;
97 case EM_X86_64:
98 return kX86_64;
99 case EM_MIPS: {
100 if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R2 ||
101 (e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) {
102 return kMips;
103 } else if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_64R6) {
104 return kMips64;
105 }
106 break;
107 }
108 }
109 return kNone;
110 }
111
GetInstructionSetAlignment(InstructionSet isa)112 size_t GetInstructionSetAlignment(InstructionSet isa) {
113 switch (isa) {
114 case kArm:
115 // Fall-through.
116 case kThumb2:
117 return kArmAlignment;
118 case kArm64:
119 return kArm64Alignment;
120 case kX86:
121 // Fall-through.
122 case kX86_64:
123 return kX86Alignment;
124 case kMips:
125 // Fall-through.
126 case kMips64:
127 return kMipsAlignment;
128 case kNone:
129 LOG(FATAL) << "ISA kNone does not have alignment.";
130 UNREACHABLE();
131 default:
132 LOG(FATAL) << "Unknown ISA " << isa;
133 UNREACHABLE();
134 }
135 }
136
137 #if !defined(ART_STACK_OVERFLOW_GAP_arm) || !defined(ART_STACK_OVERFLOW_GAP_arm64) || \
138 !defined(ART_STACK_OVERFLOW_GAP_mips) || !defined(ART_STACK_OVERFLOW_GAP_mips64) || \
139 !defined(ART_STACK_OVERFLOW_GAP_x86) || !defined(ART_STACK_OVERFLOW_GAP_x86_64)
140 #error "Missing defines for stack overflow gap"
141 #endif
142
143 static constexpr size_t kArmStackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm;
144 static constexpr size_t kArm64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm64;
145 static constexpr size_t kMipsStackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_mips;
146 static constexpr size_t kMips64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_mips64;
147 static constexpr size_t kX86StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86;
148 static constexpr size_t kX86_64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86_64;
149
150 static_assert(IsAligned<kPageSize>(kArmStackOverflowReservedBytes), "ARM gap not page aligned");
151 static_assert(IsAligned<kPageSize>(kArm64StackOverflowReservedBytes), "ARM64 gap not page aligned");
152 static_assert(IsAligned<kPageSize>(kMipsStackOverflowReservedBytes), "Mips gap not page aligned");
153 static_assert(IsAligned<kPageSize>(kMips64StackOverflowReservedBytes),
154 "Mips64 gap not page aligned");
155 static_assert(IsAligned<kPageSize>(kX86StackOverflowReservedBytes), "X86 gap not page aligned");
156 static_assert(IsAligned<kPageSize>(kX86_64StackOverflowReservedBytes),
157 "X86_64 gap not page aligned");
158
159 #if !defined(ART_FRAME_SIZE_LIMIT)
160 #error "ART frame size limit missing"
161 #endif
162
163 // TODO: Should we require an extra page (RoundUp(SIZE) + kPageSize)?
164 static_assert(ART_FRAME_SIZE_LIMIT < kArmStackOverflowReservedBytes, "Frame size limit too large");
165 static_assert(ART_FRAME_SIZE_LIMIT < kArm64StackOverflowReservedBytes,
166 "Frame size limit too large");
167 static_assert(ART_FRAME_SIZE_LIMIT < kMipsStackOverflowReservedBytes,
168 "Frame size limit too large");
169 static_assert(ART_FRAME_SIZE_LIMIT < kMips64StackOverflowReservedBytes,
170 "Frame size limit too large");
171 static_assert(ART_FRAME_SIZE_LIMIT < kX86StackOverflowReservedBytes,
172 "Frame size limit too large");
173 static_assert(ART_FRAME_SIZE_LIMIT < kX86_64StackOverflowReservedBytes,
174 "Frame size limit too large");
175
GetStackOverflowReservedBytes(InstructionSet isa)176 size_t GetStackOverflowReservedBytes(InstructionSet isa) {
177 switch (isa) {
178 case kArm: // Intentional fall-through.
179 case kThumb2:
180 return kArmStackOverflowReservedBytes;
181
182 case kArm64:
183 return kArm64StackOverflowReservedBytes;
184
185 case kMips:
186 return kMipsStackOverflowReservedBytes;
187
188 case kMips64:
189 return kMips64StackOverflowReservedBytes;
190
191 case kX86:
192 return kX86StackOverflowReservedBytes;
193
194 case kX86_64:
195 return kX86_64StackOverflowReservedBytes;
196
197 case kNone:
198 LOG(FATAL) << "kNone has no stack overflow size";
199 UNREACHABLE();
200
201 default:
202 LOG(FATAL) << "Unknown instruction set" << isa;
203 UNREACHABLE();
204 }
205 }
206
207 } // namespace art
208