1 // Copyright (c) 2012, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 #include "common/mac/arch_utilities.h"
31
32 #include <mach-o/arch.h>
33 #include <mach-o/fat.h>
34 #include <stdio.h>
35 #include <string.h>
36
37 #ifndef CPU_SUBTYPE_ARM_V7S
38 #define CPU_SUBTYPE_ARM_V7S (static_cast<cpu_subtype_t>(11))
39 #endif // CPU_SUBTYPE_ARM_V7S
40
41 #ifndef CPU_TYPE_ARM64
42 #define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
43 #endif // CPU_TYPE_ARM64
44
45 #ifndef CPU_SUBTYPE_ARM64_ALL
46 #define CPU_SUBTYPE_ARM64_ALL (static_cast<cpu_subtype_t>(0))
47 #endif // CPU_SUBTYPE_ARM64_ALL
48
49 #ifndef CPU_SUBTYPE_ARM64_E
50 #define CPU_SUBTYPE_ARM64_E (static_cast<cpu_subtype_t>(2))
51 #endif // CPU_SUBTYPE_ARM64_E
52
53 namespace {
54
ArchInfo_arm64(cpu_subtype_t cpu_subtype)55 const NXArchInfo* ArchInfo_arm64(cpu_subtype_t cpu_subtype) {
56 const char* name = NULL;
57 switch (cpu_subtype) {
58 case CPU_SUBTYPE_ARM64_ALL:
59 name = "arm64";
60 break;
61 case CPU_SUBTYPE_ARM64_E:
62 name = "arm64e";
63 break;
64 default:
65 return NULL;
66 }
67
68 NXArchInfo* arm64 = new NXArchInfo;
69 *arm64 = *NXGetArchInfoFromCpuType(CPU_TYPE_ARM,
70 CPU_SUBTYPE_ARM_V7);
71 arm64->name = name;
72 arm64->cputype = CPU_TYPE_ARM64;
73 arm64->cpusubtype = cpu_subtype;
74 arm64->description = "arm 64";
75 return arm64;
76 }
77
ArchInfo_armv7s()78 const NXArchInfo* ArchInfo_armv7s() {
79 NXArchInfo* armv7s = new NXArchInfo;
80 *armv7s = *NXGetArchInfoFromCpuType(CPU_TYPE_ARM,
81 CPU_SUBTYPE_ARM_V7);
82 armv7s->name = "armv7s";
83 armv7s->cpusubtype = CPU_SUBTYPE_ARM_V7S;
84 armv7s->description = "arm v7s";
85 return armv7s;
86 }
87
88 } // namespace
89
90 namespace google_breakpad {
91
BreakpadGetArchInfoFromName(const char * arch_name)92 const NXArchInfo* BreakpadGetArchInfoFromName(const char* arch_name) {
93 // TODO: Remove this when the OS knows about arm64.
94 if (!strcmp("arm64", arch_name))
95 return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM64,
96 CPU_SUBTYPE_ARM64_ALL);
97
98 if (!strcmp("arm64e", arch_name))
99 return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM64,
100 CPU_SUBTYPE_ARM64_E);
101
102 // TODO: Remove this when the OS knows about armv7s.
103 if (!strcmp("armv7s", arch_name))
104 return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S);
105
106 return NXGetArchInfoFromName(arch_name);
107 }
108
BreakpadGetArchInfoFromCpuType(cpu_type_t cpu_type,cpu_subtype_t cpu_subtype)109 const NXArchInfo* BreakpadGetArchInfoFromCpuType(cpu_type_t cpu_type,
110 cpu_subtype_t cpu_subtype) {
111 // TODO: Remove this when the OS knows about arm64.
112 if (cpu_type == CPU_TYPE_ARM64 && cpu_subtype == CPU_SUBTYPE_ARM64_ALL) {
113 static const NXArchInfo* arm64 = ArchInfo_arm64(cpu_subtype);
114 return arm64;
115 }
116
117 if (cpu_type == CPU_TYPE_ARM64 && cpu_subtype == CPU_SUBTYPE_ARM64_E) {
118 static const NXArchInfo* arm64e = ArchInfo_arm64(cpu_subtype);
119 return arm64e;
120 }
121
122 // TODO: Remove this when the OS knows about armv7s.
123 if (cpu_type == CPU_TYPE_ARM && cpu_subtype == CPU_SUBTYPE_ARM_V7S) {
124 static const NXArchInfo* armv7s = ArchInfo_armv7s();
125 return armv7s;
126 }
127
128 return NXGetArchInfoFromCpuType(cpu_type, cpu_subtype);
129 }
130
131 } // namespace google_breakpad
132
133 #ifndef __APPLE__
134 namespace {
135
136 enum Architecture {
137 kArch_i386 = 0,
138 kArch_x86_64,
139 kArch_x86_64h,
140 kArch_arm,
141 kArch_arm64,
142 kArch_arm64e,
143 kArch_ppc,
144 // This must be last.
145 kNumArchitectures
146 };
147
148 // enum Architecture above and kKnownArchitectures below
149 // must be kept in sync.
150 const NXArchInfo kKnownArchitectures[] = {
151 {
152 "i386",
153 CPU_TYPE_I386,
154 CPU_SUBTYPE_I386_ALL,
155 NX_LittleEndian,
156 "Intel 80x86"
157 },
158 {
159 "x86_64",
160 CPU_TYPE_X86_64,
161 CPU_SUBTYPE_X86_64_ALL,
162 NX_LittleEndian,
163 "Intel x86-64"
164 },
165 {
166 "x86_64h",
167 CPU_TYPE_X86_64,
168 CPU_SUBTYPE_X86_64_H,
169 NX_LittleEndian,
170 "Intel x86-64h Haswell"
171 },
172 {
173 "arm",
174 CPU_TYPE_ARM,
175 CPU_SUBTYPE_ARM_ALL,
176 NX_LittleEndian,
177 "ARM"
178 },
179 {
180 "arm64",
181 CPU_TYPE_ARM64,
182 CPU_SUBTYPE_ARM64_ALL,
183 NX_LittleEndian,
184 "ARM64"
185 },
186 {
187 "arm64e",
188 CPU_TYPE_ARM64,
189 CPU_SUBTYPE_ARM64_E,
190 NX_LittleEndian,
191 "ARM64e"
192 },
193 {
194 "ppc",
195 CPU_TYPE_POWERPC,
196 CPU_SUBTYPE_POWERPC_ALL,
197 NX_BigEndian,
198 "PowerPC"
199 }
200 };
201
202 } // namespace
203
NXGetLocalArchInfo(void)204 const NXArchInfo *NXGetLocalArchInfo(void) {
205 Architecture arch;
206 #if defined(__i386__)
207 arch = kArch_i386;
208 #elif defined(__x86_64__)
209 arch = kArch_x86_64;
210 #elif defined(__arm64)
211 arch = kArch_arm64;
212 #elif defined(__arm__)
213 arch = kArch_arm;
214 #elif defined(__powerpc__)
215 arch = kArch_ppc;
216 #else
217 #error "Unsupported CPU architecture"
218 #endif
219 return &kKnownArchitectures[arch];
220 }
221
NXGetArchInfoFromName(const char * name)222 const NXArchInfo *NXGetArchInfoFromName(const char *name) {
223 for (int arch = 0; arch < kNumArchitectures; ++arch) {
224 if (!strcmp(name, kKnownArchitectures[arch].name)) {
225 return &kKnownArchitectures[arch];
226 }
227 }
228 return NULL;
229 }
230
NXGetArchInfoFromCpuType(cpu_type_t cputype,cpu_subtype_t cpusubtype)231 const NXArchInfo *NXGetArchInfoFromCpuType(cpu_type_t cputype,
232 cpu_subtype_t cpusubtype) {
233 const NXArchInfo *candidate = NULL;
234 for (int arch = 0; arch < kNumArchitectures; ++arch) {
235 if (kKnownArchitectures[arch].cputype == cputype) {
236 if (kKnownArchitectures[arch].cpusubtype == cpusubtype) {
237 return &kKnownArchitectures[arch];
238 }
239 if (!candidate) {
240 candidate = &kKnownArchitectures[arch];
241 }
242 }
243 }
244 return candidate;
245 }
246
NXFindBestFatArch(cpu_type_t cputype,cpu_subtype_t cpusubtype,struct fat_arch * fat_archs,uint32_t nfat_archs)247 struct fat_arch *NXFindBestFatArch(cpu_type_t cputype,
248 cpu_subtype_t cpusubtype,
249 struct fat_arch *fat_archs,
250 uint32_t nfat_archs) {
251 struct fat_arch *candidate = NULL;
252 for (uint32_t f = 0; f < nfat_archs; ++f) {
253 if (fat_archs[f].cputype == cputype) {
254 if (fat_archs[f].cpusubtype == cpusubtype) {
255 return &fat_archs[f];
256 }
257 if (!candidate) {
258 candidate = &fat_archs[f];
259 }
260 }
261 }
262 return candidate;
263 }
264 #endif // !__APPLE__
265