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