Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2024 Keve Müller <kevemueller@users.github.com>
3 : : *
4 : : * Redistribution and use in source and binary forms, with or without
5 : : * modification, are permitted provided that the following conditions
6 : : * are met:
7 : : * 1. Redistributions of source code must retain the above copyright
8 : : * notice, this list of conditions and the following disclaimer
9 : : * in this position and unchanged.
10 : : * 2. Redistributions in binary form must reproduce the above copyright
11 : : * notice, this list of conditions and the following disclaimer in the
12 : : * documentation and/or other materials provided with the distribution.
13 : : *
14 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 : : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 : : */
25 : :
26 : : #ifdef HAVE_CONFIG_H
27 : : #include "pkg_config.h"
28 : : #endif
29 : :
30 : : #ifdef HAVE_SYS_ENDIAN_H
31 : : #include <sys/endian.h>
32 : : #elif HAVE_ENDIAN_H
33 : : #include <endian.h>
34 : : #elif HAVE_MACHINE_ENDIAN_H
35 : : #include <machine/endian.h>
36 : : #endif
37 : : #include <errno.h>
38 : : #include <fcntl.h>
39 : : #include <stdio.h>
40 : : #include <stdlib.h>
41 : : #include <string.h>
42 : : #include <unistd.h>
43 : :
44 : : #include <bsd_compat.h>
45 : : #include "private/binfmt_macho.h"
46 : :
47 : : /**
48 : : * Minimal Mach-O binary file parser for both FAT as well as plain binaries with
49 : : * sufficient functionality to handle architecture, OS, file type, library
50 : : * dependencies.
51 : : * As well as utility functions to convert data into different formats.
52 : : */
53 : :
54 : : /**** Readers ****/
55 : :
56 : : static ssize_t
57 : 2085 : read_fully(const int fd, const size_t len, void *dest)
58 : : {
59 : 2085 : unsigned char *p = dest;
60 : 2085 : size_t n = len;
61 : : ssize_t x;
62 [ + + ]: 4170 : while (n > 0) {
63 [ + - ]: 2085 : if ((x = read(fd, p, n)) < 0) {
64 [ # # ]: 0 : if ( EAGAIN == errno) {
65 : 0 : continue;
66 : : }
67 : 0 : return x;
68 : : }
69 [ - + ]: 2085 : if ( 0 == x) {
70 : 0 : return -1;
71 : : }
72 : 2085 : n -= x;
73 : 2085 : p += x;
74 : : }
75 : 2085 : return len;
76 : 2085 : }
77 : :
78 : : ssize_t
79 : 2064 : read_u32(const int fd, const bool swap, uint32_t *dest)
80 : : {
81 : : unsigned char buf[4];
82 : : ssize_t x;
83 [ + - ]: 2064 : if ((x = read_fully(fd, sizeof(buf), buf)) < 0) {
84 : 0 : return x;
85 : : }
86 [ + + ]: 2064 : if (swap) {
87 : 1672 : *dest = le32dec(buf);
88 : 1672 : } else {
89 : 392 : *dest = be32dec(buf);
90 : : }
91 : 2064 : return x;
92 : 2064 : }
93 : :
94 : : static ssize_t
95 : 0 : read_u64(const int fd, const bool swap, uint64_t *dest)
96 : : {
97 : : unsigned char buf[8];
98 : : ssize_t x;
99 [ # # ]: 0 : if ((x = read_fully(fd, sizeof(buf), buf)) < 0) {
100 : 0 : return x;
101 : : }
102 [ # # ]: 0 : if (swap) {
103 : 0 : *dest = le64dec(buf);
104 : 0 : } else {
105 : 0 : *dest = be64dec(buf);
106 : : }
107 : 0 : return x;
108 : 0 : }
109 : :
110 : : static ssize_t
111 : 112 : read_cpu_type(const int fd, const bool swap, cpu_type_subtype_t *dest)
112 : : {
113 : 112 : ssize_t n = 0, x;
114 : : uint32_t cputype;
115 : : uint32_t cpusubtype;
116 : :
117 [ + - ]: 112 : READ(u32, cputype);
118 [ + - ]: 112 : READ(u32, cpusubtype);
119 : 112 : dest->type = cputype & ~CPU_ARCH_MASK;
120 : 112 : dest->type_is64 = (cputype & CPU_ARCH_MASK) == CPU_ARCH_ABI64;
121 : 112 : dest->type_is64_32 = (cputype & CPU_ARCH_MASK) == CPU_ARCH_ABI64_32;
122 : 112 : dest->subtype_islib64 = (cpusubtype & CPU_SUBTYPE_MASK) ==
123 : : CPU_SUBTYPE_LIB64;
124 [ + - + - ]: 112 : switch (dest->type) {
125 : : case CPU_TYPE_ARM:
126 : 50 : dest->subtype_arm = cpusubtype & ~CPU_SUBTYPE_MASK;
127 : 50 : break;
128 : : case CPU_TYPE_X86:
129 : 62 : dest->subtype_x86 = cpusubtype & ~CPU_SUBTYPE_MASK;
130 : 62 : break;
131 : : case CPU_TYPE_POWERPC:
132 : 0 : dest->subtype_ppc = cpusubtype & ~CPU_SUBTYPE_MASK;
133 : 0 : break;
134 : : default:
135 : 0 : errno = EINVAL;
136 : 0 : return -1;
137 : : }
138 : 112 : return n;
139 : 112 : }
140 : :
141 : : static ssize_t
142 : 56 : read_fat_arch(const int fd, const uint32_t magic, fat_arch_t *dest)
143 : : {
144 : 56 : ssize_t n = 0, x;
145 [ + - - + ]: 56 : const bool swap = magic == FAT_CIGAM || magic == FAT_CIGAM_64;
146 : :
147 [ + - ]: 56 : READ(cpu_type, dest->cpu);
148 : : uint32_t align;
149 : : uint32_t reserved;
150 : :
151 [ - + - - : 56 : switch (magic) {
- ]
152 : : case FAT_MAGIC:
153 : : case FAT_CIGAM:;
154 : : uint32_t offset32;
155 : : uint32_t size32;
156 [ + - ]: 56 : READ(u32, offset32);
157 [ + - ]: 56 : READ(u32, size32);
158 [ + - ]: 56 : READ(u32, align); // bits
159 : :
160 : 56 : dest->offset = offset32;
161 : 56 : dest->size = size32;
162 : 56 : dest->align = align;
163 : 56 : break;
164 : : case FAT_MAGIC_64:
165 : : case FAT_CIGAM_64:
166 [ # # ]: 0 : READ(u64, dest->offset);
167 [ # # ]: 0 : READ(u64, dest->size);
168 [ # # ]: 0 : READ(u32, align);
169 [ # # ]: 0 : READ(u32, reserved);
170 : 0 : dest->align = align;
171 : 0 : break;
172 : : default:
173 : 0 : errno = EINVAL;
174 : 0 : return -1;
175 : : }
176 : 56 : return n;
177 : 56 : }
178 : :
179 : : static ssize_t
180 : 106 : read_version(const int fd, const bool swap, macho_version_t *dest)
181 : : {
182 : 106 : ssize_t n = 0, x;
183 : :
184 : : uint32_t version;
185 [ + - ]: 106 : READ(u32, version);
186 : 106 : dest->major = (version >> 16) & 0xffff;
187 : 106 : dest->minor = (version >> 8) & 0xff;
188 : 106 : dest->patch = version & 0xff;
189 : 106 : return n;
190 : 106 : }
191 : :
192 : : ssize_t
193 : 17 : read_min_version(const int fd, const bool swap, const uint32_t loadcmd,
194 : : build_version_t **dest)
195 : : {
196 : 17 : ssize_t n = 0, x;
197 : :
198 : 17 : *dest = malloc(sizeof(build_version_t));
199 : 17 : (*dest)->ntools = 0;
200 [ - - + - : 17 : switch (loadcmd) {
- ]
201 : : case LC_VERSION_MIN_IPHONEOS:
202 : 0 : (*dest)->platform = PLATFORM_IOS;
203 : 0 : break;
204 : : case LC_VERSION_MIN_MACOSX:
205 : 17 : (*dest)->platform = PLATFORM_MACOS;
206 : 17 : break;
207 : : case LC_VERSION_MIN_TVOS:
208 : 0 : (*dest)->platform = PLATFORM_TVOS;
209 : 0 : break;
210 : : case LC_VERSION_MIN_WATCHOS:
211 : 0 : (*dest)->platform = PLATFORM_WATCHOS;
212 : 0 : break;
213 : : default:
214 : 0 : return -1;
215 : : }
216 [ + - ]: 17 : READ(version, (*dest)->minos);
217 [ + - ]: 17 : READ(version, (*dest)->sdk);
218 : 17 : return n;
219 : 17 : }
220 : :
221 : : ssize_t
222 : 6 : read_path(const int fd, const bool swap, const uint32_t loadcmdsize,
223 : : char **dest)
224 : : {
225 : 6 : ssize_t n = 0, x;
226 : :
227 : : uint32_t name_ofs;
228 [ + - ]: 6 : READ(u32, name_ofs);
229 [ - + ]: 6 : if (-1 == (x = lseek(fd, name_ofs - 12, SEEK_CUR))) {
230 : 0 : return x;
231 : : }
232 : 6 : n += name_ofs - 12;
233 : 6 : *dest = malloc(loadcmdsize - name_ofs + 1);
234 [ + - ]: 6 : if ((x = read_fully(fd, loadcmdsize - name_ofs, *dest)) < 0) {
235 : 0 : free(*dest);
236 : 0 : *dest = 0;
237 : 0 : return x;
238 : : }
239 : 6 : n += x;
240 : 6 : (*dest)[loadcmdsize - name_ofs] = '\0';
241 : 6 : return n;
242 : 6 : }
243 : :
244 : : ssize_t
245 : 15 : read_dylib(const int fd, const bool swap, const uint32_t loadcmdsize,
246 : : dylib_t **dest)
247 : : {
248 : 15 : ssize_t n = 0, x;
249 : :
250 : : uint32_t name_ofs;
251 : : uint32_t timestamp;
252 : : macho_version_t current_version;
253 : : macho_version_t compatibility_version;
254 : :
255 [ + - ]: 15 : READ(u32, name_ofs);
256 [ + - ]: 15 : READ(u32, timestamp);
257 [ + - ]: 15 : READ(version, current_version);
258 [ + - ]: 15 : READ(version, compatibility_version);
259 : :
260 [ - + ]: 15 : if (-1 == (x = lseek(fd, name_ofs - 24, SEEK_CUR))) {
261 : 0 : return x;
262 : : }
263 : 15 : n += name_ofs - 24;
264 : :
265 : 15 : *dest = malloc(sizeof(dylib_t) + loadcmdsize - name_ofs + 1);
266 : 15 : (*dest)->timestamp = timestamp;
267 : 15 : (*dest)->current_version = current_version;
268 : 15 : (*dest)->compatibility_version = compatibility_version;
269 [ + - ]: 15 : if ((x = read_fully(fd, loadcmdsize - name_ofs, (*dest)->path)) < 0) {
270 : 0 : free(*dest);
271 : 0 : *dest = 0;
272 : 0 : return x;
273 : : }
274 : 15 : n += x;
275 : 15 : (*dest)->path[loadcmdsize - name_ofs] = '\0';
276 : 15 : return n;
277 : 15 : }
278 : :
279 : : ssize_t
280 : 14 : read_build_version(const int fd, const bool swap, build_version_t **dest)
281 : : {
282 : 14 : ssize_t n = 0, x;
283 : :
284 : : uint32_t platform;
285 : : macho_version_t minos;
286 : : macho_version_t sdk;
287 : : uint32_t ntools;
288 : :
289 [ + - ]: 14 : READ(u32, platform);
290 [ + - ]: 14 : READ(version, minos);
291 [ + - ]: 14 : READ(version, sdk);
292 [ + - ]: 14 : READ(u32, ntools);
293 : :
294 : 14 : *dest = malloc(
295 : 14 : sizeof(build_version_t) + ntools * sizeof(tool_version_t));
296 : 14 : (*dest)->platform = platform;
297 : 14 : (*dest)->minos = minos;
298 : 14 : (*dest)->sdk = sdk;
299 : 14 : (*dest)->ntools = ntools;
300 : 14 : tool_version_t *p = (*dest)->tools;
301 : :
302 [ + + ]: 28 : for (; ntools-- > 0; p++) {
303 : : uint32_t tool;
304 [ - + ]: 14 : READ(u32, tool);
305 : 14 : p->tool = tool;
306 [ - + ]: 14 : READ(version, p->version);
307 : 14 : }
308 : 14 : return n;
309 : 14 : }
310 : :
311 : : ssize_t
312 : 40 : read_macho_header(const int fd, macho_header_t *dest)
313 : : {
314 : 40 : ssize_t n = 0, x;
315 : : uint32_t reserved;
316 : :
317 [ - + ]: 40 : if ((x = read_u32(fd, false, &dest->magic) < 0)) {
318 : 0 : return x;
319 : : }
320 : 40 : n += x;
321 : :
322 [ + - + - ]: 40 : const bool swap = dest->swap = dest->magic == MH_CIGAM ||
323 : 40 : dest->magic == MH_CIGAM_64;
324 : :
325 [ + - ]: 40 : READ(cpu_type, dest->cpu);
326 [ + - ]: 40 : READ(u32, dest->filetype);
327 [ + - ]: 40 : READ(u32, dest->ncmds);
328 [ + - ]: 40 : READ(u32, dest->sizeofcmds);
329 [ + - ]: 40 : READ(u32, dest->flags);
330 [ - - + ]: 40 : switch (dest->magic) {
331 : : case MH_MAGIC_64:
332 : : case MH_CIGAM_64:
333 [ + - ]: 40 : READ(u32, reserved);
334 : 40 : break;
335 : : default:
336 : 0 : break;
337 : : }
338 : 40 : return n;
339 : 40 : }
340 : :
341 : : ssize_t
342 : 44 : read_macho_file(const int fd, macho_file_t **dest)
343 : : {
344 : 44 : ssize_t n = 0, x;
345 : :
346 : : uint32_t magic;
347 [ + - ]: 44 : if ((x = read_u32(fd, false, &magic)) < 0) {
348 : 0 : return x;
349 : : }
350 : 44 : n += x;
351 : :
352 [ + - - + ]: 88 : const bool swap = magic == FAT_CIGAM || magic == FAT_CIGAM_64 ||
353 [ - + + + ]: 44 : magic == MH_CIGAM || magic == MH_CIGAM_64;
354 : :
355 : : uint32_t nfat_arch;
356 : : fat_arch_t *p;
357 [ + - - - : 44 : switch (magic) {
- - - +
- ]
358 : : case FAT_MAGIC:
359 : : case FAT_MAGIC_64:
360 : : case FAT_CIGAM:
361 : : case FAT_CIGAM_64:
362 [ + - ]: 28 : READ(u32, nfat_arch);
363 : 28 : *dest = malloc(
364 : 28 : sizeof(macho_file_t) + nfat_arch * sizeof(fat_arch_t));
365 : 28 : (*dest)->magic = magic;
366 : 28 : (*dest)->narch = nfat_arch;
367 : 28 : p = (*dest)->arch;
368 : :
369 [ + + ]: 84 : while (nfat_arch-- > 0) {
370 [ - + ]: 56 : if ((x = read_fat_arch(fd, magic, p)) < 0) {
371 : 0 : free(*dest);
372 : 0 : *dest = 0;
373 : 0 : return x;
374 : : }
375 : 56 : n += x;
376 : 56 : p++;
377 : : }
378 : 44 : break;
379 : :
380 : : case MH_MAGIC:
381 : : case MH_MAGIC_64:
382 : : case MH_CIGAM:
383 : : case MH_CIGAM_64:
384 : 16 : nfat_arch = 1;
385 : 16 : *dest = malloc(
386 : 16 : sizeof(macho_file_t) + nfat_arch * sizeof(fat_arch_t));
387 : 16 : (*dest)->magic = magic;
388 : 16 : (*dest)->narch = nfat_arch;
389 : 16 : p = (*dest)->arch;
390 [ + - ]: 16 : READ(cpu_type, p->cpu);
391 : : off_t xo;
392 [ - + ]: 16 : if (-1 == (xo = lseek(fd, 0, SEEK_END))) {
393 : 0 : free(*dest);
394 : 0 : *dest = 0;
395 : 0 : return xo;
396 : : }
397 : 16 : p->offset = 0;
398 : 16 : p->size = xo;
399 : 16 : p->align = 0; // number of trailing zero bits in size;
400 : 16 : n = xo;
401 : 16 : break;
402 : : default:
403 : 0 : errno = EINVAL;
404 : 0 : return -1;
405 : : }
406 : 44 : return n;
407 : 44 : }
408 : :
409 : : /**** OS -> Kernel conversion ****/
410 : :
411 : : static macho_version_t macos_to_darwin[][2] = {
412 : : // macOS Sequoia
413 : : { { 15, 2, 0 }, { 24, 2, 0 } },
414 : : { { 15, 1, 0 }, { 24, 1, 0 } },
415 : : { { 15, 0, 0 }, { 24, 0, 0 } },
416 : : // macOS Sonoma
417 : : { { 14, 6, 0 }, { 23, 6, 0 } },
418 : : { { 14, 5, 0 }, { 23, 4, 0 } },
419 : : { { 14, 4, 0 }, { 23, 5, 0 } },
420 : : { { 14, 3, 0 }, { 23, 3, 0 } },
421 : : { { 14, 2, 0 }, { 23, 2, 0 } },
422 : : { { 14, 1, 0 }, { 23, 1, 0 } },
423 : : { { 14, 0, 0 }, { 23, 0, 0 } },
424 : : // macOS Ventura
425 : : { { 13, 5, 0 }, { 22, 6, 0 } },
426 : : { { 13, 4, 0 }, { 22, 5, 0 } },
427 : : { { 13, 3, 0 }, { 22, 4, 0 } },
428 : : { { 13, 2, 0 }, { 22, 3, 0 } },
429 : : { { 13, 1, 0 }, { 22, 2, 0 } },
430 : : { { 13, 0, 0 }, { 22, 1, 0 } },
431 : : // macOS Monterey
432 : : { { 12, 5, 0 }, { 21, 6, 0 } },
433 : : { { 12, 4, 0 }, { 21, 5, 0 } },
434 : : { { 12, 3, 0 }, { 21, 4, 0 } },
435 : : { { 12, 2, 0 }, { 21, 3, 0 } },
436 : : { { 12, 1, 0 }, { 21, 2, 0 } },
437 : : { { 12, 0, 1 }, { 21, 1, 0 } },
438 : : { { 12, 0, 0 }, { 21, 0, 1 } },
439 : : // macOS Big Sur
440 : : { { 11, 5, 0 }, { 20, 6, 0 } },
441 : : { { 11, 4, 0 }, { 20, 5, 0 } },
442 : : { { 11, 3, 0 }, { 20, 4, 0 } },
443 : : { { 11, 2, 0 }, { 20, 3, 0 } },
444 : : { { 11, 1, 0 }, { 20, 2, 0 } },
445 : : { { 11, 0, 0 }, { 20, 1, 0 } },
446 : : // macOS Catalina
447 : : { { 10, 15, 6 }, { 19, 6, 0 } },
448 : : { { 10, 15, 5 }, { 19, 5, 0 } },
449 : : { { 10, 15, 4 }, { 19, 4, 0 } },
450 : : { { 10, 15, 3 }, { 19, 3, 0 } },
451 : : { { 10, 15, 2 }, { 19, 2, 0 } },
452 : : { { 10, 15, 0 }, { 19, 0, 0 } },
453 : : // macOS Mojave
454 : : { { 10, 14, 6 }, { 18, 7, 0 } },
455 : : { { 10, 14, 5 }, { 18, 6, 0 } },
456 : : { { 10, 14, 4 }, { 18, 5, 0 } },
457 : : { { 10, 14, 1 }, { 18, 2, 0 } },
458 : : { { 10, 14, 0 }, { 18, 0, 0 } },
459 : : // macOS High Sierra
460 : : { { 10, 13, 6 }, { 17, 7, 0 } },
461 : : { { 10, 13, 5 }, { 17, 6, 0 } },
462 : : { { 10, 13, 4 }, { 17, 5, 0 } },
463 : : { { 10, 13, 3 }, { 17, 4, 0 } },
464 : : { { 10, 13, 2 }, { 17, 3, 0 } },
465 : : { { 10, 13, 1 }, { 17, 2, 0 } },
466 : : { { 10, 13, 0 }, { 17, 0, 0 } },
467 : : // macOS Sierra
468 : : { { 10, 12, 6 }, { 16, 7, 0 } },
469 : : { { 10, 12, 5 }, { 16, 6, 0 } },
470 : : { { 10, 12, 4 }, { 16, 5, 0 } },
471 : : { { 10, 12, 3 }, { 16, 4, 0 } },
472 : : { { 10, 12, 2 }, { 16, 3, 0 } },
473 : : { { 10, 12, 1 }, { 16, 1, 0 } },
474 : : { { 10, 12, 0 }, { 16, 0, 0 } },
475 : : // OS X El Capitan
476 : : { { 10, 11, 6 }, { 15, 6, 0 } },
477 : : { { 10, 11, 5 }, { 15, 5, 0 } },
478 : : { { 10, 11, 4 }, { 15, 4, 0 } },
479 : : { { 10, 11, 3 }, { 15, 3, 0 } },
480 : : { { 10, 11, 2 }, { 15, 2, 0 } },
481 : : { { 10, 11, 0 }, { 15, 0, 0 } },
482 : : // OS X Yosemite
483 : : { { 10, 10, 5 }, { 14, 5, 0 } },
484 : : { { 10, 10, 4 }, { 14, 4, 0 } },
485 : : { { 10, 10, 3 }, { 14, 3, 0 } },
486 : : { { 10, 10, 2 }, { 14, 1, 0 } },
487 : : { { 10, 10, 0 }, { 14, 0, 0 } },
488 : : // OS X Mavericks
489 : : { { 10, 9, 5 }, { 13, 4, 0 } },
490 : : { { 10, 9, 4 }, { 13, 3, 0 } },
491 : : { { 10, 9, 3 }, { 13, 2, 0 } },
492 : : { { 10, 9, 2 }, { 13, 1, 0 } },
493 : : { { 10, 9, 0 }, { 13, 0, 0 } },
494 : : // OS X Mountain Lion
495 : : { { 10, 8, 5 }, { 12, 5, 0 } }, // Build 12F45 switched to 12.6
496 : : { { 10, 8, 4 }, { 12, 4, 0 } },
497 : : { { 10, 8, 3 }, { 12, 3, 0 } },
498 : : { { 10, 8, 2 }, { 12, 2, 0 } },
499 : : { { 10, 8, 1 }, { 12, 1, 0 } },
500 : : { { 10, 8, 0 }, { 12, 0, 0 } },
501 : : // OS X Lion
502 : : { { 10, 7, 5 }, { 11, 4, 2 } },
503 : : { { 10, 7, 4 }, { 11, 4, 0 } },
504 : : { { 10, 7, 3 }, { 11, 3, 0 } },
505 : : { { 10, 7, 2 }, { 11, 2, 0 } },
506 : : { { 10, 7, 1 }, { 11, 1, 0 } },
507 : : { { 10, 7, 0 }, { 11, 0, 0 } },
508 : : // Mac OS X Snow Leopard
509 : : { { 10, 6, 8 }, { 10, 8, 0 } },
510 : : { { 10, 6, 7 }, { 10, 7, 0 } },
511 : : { { 10, 6, 6 }, { 10, 6, 0 } },
512 : : { { 10, 6, 5 }, { 10, 5, 0 } },
513 : : { { 10, 6, 4 }, { 10, 4, 0 } },
514 : : { { 10, 6, 3 }, { 10, 3, 0 } },
515 : : { { 10, 6, 2 }, { 10, 2, 0 } },
516 : : { { 10, 6, 1 }, { 10, 1, 0 } },
517 : : { { 10, 6, 0 }, { 10, 0, 0 } },
518 : : // Mac OS X Leopard
519 : : { { 10, 5, 8 }, { 9, 8, 0 } },
520 : : { { 10, 5, 7 }, { 9, 7, 0 } },
521 : : { { 10, 5, 6 }, { 9, 6, 0 } },
522 : : { { 10, 5, 5 }, { 9, 5, 0 } },
523 : : { { 10, 5, 4 }, { 9, 4, 0 } },
524 : : { { 10, 5, 3 }, { 9, 3, 0 } },
525 : : { { 10, 5, 2 }, { 9, 2, 0 } },
526 : : { { 10, 5, 1 }, { 9, 1, 0 } }, // Build 9B2117 switched to 9.1.1
527 : : { { 10, 5, 0 }, { 9, 0, 0 } },
528 : : // Mac OS X Tiger
529 : : { { 10, 4, 11 }, { 8, 11, 0 } },
530 : : { { 10, 4, 10 }, { 8, 10, 0 } },
531 : : { { 10, 4, 9 }, { 8, 9, 0 } },
532 : : { { 10, 4, 8 }, { 8, 8, 0 } },
533 : : { { 10, 4, 7 }, { 8, 7, 0 } },
534 : : { { 10, 4, 6 }, { 8, 6, 0 } },
535 : : { { 10, 4, 5 }, { 8, 5, 0 } },
536 : : { { 10, 4, 4 }, { 8, 4, 0 } },
537 : : { { 10, 4, 3 }, { 8, 3, 0 } },
538 : : { { 10, 4, 2 }, { 8, 2, 0 } },
539 : : { { 10, 4, 1 }, { 8, 1, 0 } },
540 : : { { 10, 4, 0 }, { 8, 0, 0 } },
541 : : // Mac OS X Panther
542 : : { { 10, 3, 9 }, { 7, 9, 0 } },
543 : : { { 10, 3, 8 }, { 7, 8, 0 } },
544 : : { { 10, 3, 7 }, { 7, 7, 0 } },
545 : : { { 10, 3, 6 }, { 7, 6, 0 } },
546 : : { { 10, 3, 5 }, { 7, 5, 0 } },
547 : : { { 10, 3, 4 }, { 7, 4, 0 } },
548 : : { { 10, 3, 3 }, { 7, 3, 0 } },
549 : : { { 10, 3, 2 }, { 7, 2, 0 } },
550 : : { { 10, 3, 1 }, { 7, 1, 0 } },
551 : : { { 10, 3, 0 }, { 7, 0, 0 } },
552 : : // Mac OS X Jaguar
553 : : { { 10, 2, 8 }, { 6, 8, 0 } },
554 : : { { 10, 2, 7 }, { 6, 7, 0 } },
555 : : { { 10, 2, 6 }, { 6, 6, 0 } },
556 : : { { 10, 2, 5 }, { 6, 5, 0 } },
557 : : { { 10, 2, 4 }, { 6, 4, 0 } },
558 : : { { 10, 2, 3 }, { 6, 3, 0 } },
559 : : { { 10, 2, 2 }, { 6, 2, 0 } },
560 : : { { 10, 2, 1 }, { 6, 1, 0 } },
561 : : { { 10, 2, 0 }, { 6, 0, 0 } },
562 : : // Mac OS X 10.1 Puma
563 : : { { 10, 1, 5 }, { 5, 5, 0 } },
564 : : { { 10, 1, 4 }, { 5, 4, 0 } },
565 : : { { 10, 1, 3 }, { 5, 3, 0 } },
566 : : { { 10, 1, 2 }, { 5, 2, 0 } },
567 : : { { 10, 1, 1 }, { 5, 1, 0 } },
568 : : { { 10, 1, 0 }, { 1, 4, 1 } },
569 : : // Mac OS X 10.0 Cheetah
570 : : { { 10, 0, 1 }, { 1, 3, 1 } },
571 : : { { 10, 0, 0 }, { 1, 3, 0 } },
572 : : // Mac OS X Public Beta
573 : : // {{x,y,z}}, {1,2,1}},
574 : : // Mac OS X Server 1.0
575 : : { { 1, 0, 2 }, { 0, 3, 0 } },
576 : : { { 1, 0, 1 }, { 0, 2, 0 } },
577 : : { { 1, 0, 0 }, { 0, 1, 0 } },
578 : : // EOA
579 : : { { 0, 0, 0 }, { 0, 0, 0 } },
580 : : };
581 : :
582 : : static macho_version_t ios_to_darwin[][2] = {
583 : : // iOS 18, iPadOS 18, tvOS 18
584 : : { { 18, 0, 0 }, { 24, 0, 0 } },
585 : : // iOS 17, iPadOS 17, tvOS 17
586 : : { { 17, 5, 0 }, { 23, 5, 0 } },
587 : : { { 17, 4, 0 }, { 23, 4, 0 } },
588 : : { { 17, 3, 0 }, { 23, 3, 0 } },
589 : : { { 17, 2, 0 }, { 23, 2, 0 } },
590 : : { { 17, 1, 0 }, { 23, 1, 0 } },
591 : : { { 17, 0, 0 }, { 23, 0, 0 } },
592 : : // iOS 16, iPadOS 16, tvOS 16
593 : : { { 16, 6, 0 }, { 22, 6, 0 } },
594 : : { { 16, 5, 0 }, { 22, 5, 0 } },
595 : : { { 16, 4, 0 }, { 22, 4, 0 } },
596 : : { { 16, 3, 0 }, { 22, 3, 0 } },
597 : : { { 16, 2, 0 }, { 22, 2, 0 } },
598 : : { { 16, 1, 0 }, { 22, 1, 0 } },
599 : : { { 16, 0, 0 }, { 22, 0, 0 } },
600 : : // iOS 15, iPadOS 15, tvOS 15
601 : : { { 15, 6, 0 }, { 21, 6, 0 } },
602 : : { { 15, 5, 0 }, { 21, 5, 0 } },
603 : : { { 15, 4, 0 }, { 21, 4, 0 } },
604 : : { { 15, 3, 0 }, { 21, 3, 0 } },
605 : : { { 15, 2, 0 }, { 21, 2, 0 } },
606 : : { { 15, 0, 0 }, { 21, 1, 0 } },
607 : : // iOS 15.0 beta 1 -> 21.0.0
608 : : // iOS 14, iPadOS 14, tvOS 14
609 : : { { 14, 7, 0 }, { 20, 6, 0 } },
610 : : { { 14, 6, 0 }, { 20, 5, 0 } },
611 : : { { 14, 5, 0 }, { 20, 4, 0 } },
612 : : { { 14, 4, 0 }, { 20, 3, 0 } },
613 : : { { 14, 3, 0 }, { 20, 2, 0 } },
614 : : { { 14, 0, 0 }, { 20, 0, 0 } },
615 : : // iOS 13
616 : : { { 13, 6, 0 }, { 19, 6, 0 } },
617 : : { { 13, 5, 0 }, { 19, 5, 0 } },
618 : : { { 13, 3, 1 }, { 19, 3, 0 } },
619 : : { { 13, 3, 0 }, { 19, 2, 0 } },
620 : : // iOS 12
621 : : { { 12, 1, 0 }, { 18, 2, 0 } },
622 : : // iOS 11
623 : : { { 11, 4, 1 }, { 17, 7, 0 } },
624 : : // iOS 10
625 : : { { 10, 3, 3 }, { 16, 6, 0 } },
626 : : { { 10, 3, 0 }, { 16, 3, 0 } },
627 : : { { 10, 0, 1 }, { 16, 0, 0 } },
628 : : // iOS 9
629 : : { { 9, 3, 3 }, { 15, 6, 0 } },
630 : : { { 9, 0, 0 }, { 15, 0, 0 } },
631 : : // iOS 7, iOS 8
632 : : { { 7, 0, 0 }, { 14, 0, 0 } },
633 : : // iOS 6
634 : : { { 6, 0, 0 }, { 13, 0, 0 } },
635 : : // iOS 4.3
636 : : { { 4, 3, 0 }, { 11, 0, 0 } },
637 : : // iPhone OS 3
638 : : { { 3, 0, 0 }, { 10, 0, 0 } },
639 : : // iPhone OS 1
640 : : { { 1, 0, 0 }, { 9, 0, 0 } },
641 : : // EOA
642 : : { { 0, 0, 0 }, { 0, 0, 0 } },
643 : : };
644 : :
645 : : int
646 : 31 : map_platform_to_darwin(macho_version_t *darwin,
647 : : const enum MachoPlatform platform, const macho_version_t version)
648 : : {
649 : : macho_version_t *p;
650 [ - - - - : 31 : switch (platform) {
+ - - - ]
651 : : case PLATFORM_MACOS:
652 : 31 : p = macos_to_darwin[0];
653 : 31 : break;
654 : :
655 : : case PLATFORM_IOS:
656 : : case PLATFORM_IOSSIMULATOR:
657 : : case PLATFORM_TVOS:
658 : : case PLATFORM_TVOSSIMULATOR:
659 : 0 : p = ios_to_darwin[0];
660 : 0 : break;
661 : :
662 : : case PLATFORM_WATCHOS:
663 : : case PLATFORM_WATCHOSSIMULATOR:
664 : 0 : darwin->major = version.major + 13;
665 : 0 : darwin->minor = version.minor;
666 : 0 : darwin->patch = 0;
667 : 0 : return 0;
668 : :
669 : : default:
670 : 0 : return -1;
671 : : }
672 [ + + + + : 1129 : while (p->major > version.major || p->minor > version.minor ||
+ + + + ]
673 : 139 : p->patch > version.patch) {
674 : 1098 : p += 2;
675 : : }
676 : 31 : p++;
677 [ - + # # : 31 : if (0 == p->major && 0 == p->minor && 0 == p->patch) {
# # ]
678 : 0 : return -1;
679 : : }
680 : 31 : *darwin = *p;
681 : 31 : return 0;
682 : 31 : }
|