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