Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/libpkg/binfmt_macho.c
2065 views
1
/*-
2
* Copyright (c) 2024 Keve Müller <[email protected]>
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
read_fully(const int fd, const size_t len, void *dest)
58
{
59
unsigned char *p = dest;
60
size_t n = len;
61
ssize_t x;
62
while (n > 0) {
63
if ((x = read(fd, p, n)) < 0) {
64
if ( EAGAIN == errno) {
65
continue;
66
}
67
return x;
68
}
69
if ( 0 == x) {
70
return -1;
71
}
72
n -= x;
73
p += x;
74
}
75
return len;
76
}
77
78
ssize_t
79
read_u32(const int fd, const bool swap, uint32_t *dest)
80
{
81
unsigned char buf[4];
82
ssize_t x;
83
if ((x = read_fully(fd, sizeof(buf), buf)) < 0) {
84
return x;
85
}
86
if (swap) {
87
*dest = le32dec(buf);
88
} else {
89
*dest = be32dec(buf);
90
}
91
return x;
92
}
93
94
static ssize_t
95
read_u64(const int fd, const bool swap, uint64_t *dest)
96
{
97
unsigned char buf[8];
98
ssize_t x;
99
if ((x = read_fully(fd, sizeof(buf), buf)) < 0) {
100
return x;
101
}
102
if (swap) {
103
*dest = le64dec(buf);
104
} else {
105
*dest = be64dec(buf);
106
}
107
return x;
108
}
109
110
static ssize_t
111
read_cpu_type(const int fd, const bool swap, cpu_type_subtype_t *dest)
112
{
113
ssize_t n = 0, x;
114
uint32_t cputype;
115
uint32_t cpusubtype;
116
117
READ(u32, cputype);
118
READ(u32, cpusubtype);
119
dest->type = cputype & ~CPU_ARCH_MASK;
120
dest->type_is64 = (cputype & CPU_ARCH_MASK) == CPU_ARCH_ABI64;
121
dest->type_is64_32 = (cputype & CPU_ARCH_MASK) == CPU_ARCH_ABI64_32;
122
dest->subtype_islib64 = (cpusubtype & CPU_SUBTYPE_MASK) ==
123
CPU_SUBTYPE_LIB64;
124
switch (dest->type) {
125
case CPU_TYPE_ARM:
126
dest->subtype_arm = cpusubtype & ~CPU_SUBTYPE_MASK;
127
break;
128
case CPU_TYPE_X86:
129
dest->subtype_x86 = cpusubtype & ~CPU_SUBTYPE_MASK;
130
break;
131
case CPU_TYPE_POWERPC:
132
dest->subtype_ppc = cpusubtype & ~CPU_SUBTYPE_MASK;
133
break;
134
default:
135
errno = EINVAL;
136
return -1;
137
}
138
return n;
139
}
140
141
static ssize_t
142
read_fat_arch(const int fd, const uint32_t magic, fat_arch_t *dest)
143
{
144
ssize_t n = 0, x;
145
const bool swap = magic == FAT_CIGAM || magic == FAT_CIGAM_64;
146
147
READ(cpu_type, dest->cpu);
148
uint32_t align;
149
uint32_t reserved;
150
151
switch (magic) {
152
case FAT_MAGIC:
153
case FAT_CIGAM:;
154
uint32_t offset32;
155
uint32_t size32;
156
READ(u32, offset32);
157
READ(u32, size32);
158
READ(u32, align); // bits
159
160
dest->offset = offset32;
161
dest->size = size32;
162
dest->align = align;
163
break;
164
case FAT_MAGIC_64:
165
case FAT_CIGAM_64:
166
READ(u64, dest->offset);
167
READ(u64, dest->size);
168
READ(u32, align);
169
READ(u32, reserved);
170
dest->align = align;
171
break;
172
default:
173
errno = EINVAL;
174
return -1;
175
}
176
return n;
177
}
178
179
static ssize_t
180
read_version(const int fd, const bool swap, macho_version_t *dest)
181
{
182
ssize_t n = 0, x;
183
184
uint32_t version;
185
READ(u32, version);
186
dest->major = (version >> 16) & 0xffff;
187
dest->minor = (version >> 8) & 0xff;
188
dest->patch = version & 0xff;
189
return n;
190
}
191
192
ssize_t
193
read_min_version(const int fd, const bool swap, const uint32_t loadcmd,
194
build_version_t **dest)
195
{
196
ssize_t n = 0, x;
197
198
*dest = malloc(sizeof(build_version_t));
199
(*dest)->ntools = 0;
200
switch (loadcmd) {
201
case LC_VERSION_MIN_IPHONEOS:
202
(*dest)->platform = PLATFORM_IOS;
203
break;
204
case LC_VERSION_MIN_MACOSX:
205
(*dest)->platform = PLATFORM_MACOS;
206
break;
207
case LC_VERSION_MIN_TVOS:
208
(*dest)->platform = PLATFORM_TVOS;
209
break;
210
case LC_VERSION_MIN_WATCHOS:
211
(*dest)->platform = PLATFORM_WATCHOS;
212
break;
213
default:
214
return -1;
215
}
216
READ(version, (*dest)->minos);
217
READ(version, (*dest)->sdk);
218
return n;
219
}
220
221
ssize_t
222
read_path(const int fd, const bool swap, const uint32_t loadcmdsize,
223
char **dest)
224
{
225
ssize_t n = 0, x;
226
227
uint32_t name_ofs;
228
READ(u32, name_ofs);
229
if (-1 == (x = lseek(fd, name_ofs - 12, SEEK_CUR))) {
230
return x;
231
}
232
n += name_ofs - 12;
233
*dest = malloc(loadcmdsize - name_ofs + 1);
234
if ((x = read_fully(fd, loadcmdsize - name_ofs, *dest)) < 0) {
235
free(*dest);
236
*dest = 0;
237
return x;
238
}
239
n += x;
240
(*dest)[loadcmdsize - name_ofs] = '\0';
241
return n;
242
}
243
244
ssize_t
245
read_dylib(const int fd, const bool swap, const uint32_t loadcmdsize,
246
dylib_t **dest)
247
{
248
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
READ(u32, name_ofs);
256
READ(u32, timestamp);
257
READ(version, current_version);
258
READ(version, compatibility_version);
259
260
if (-1 == (x = lseek(fd, name_ofs - 24, SEEK_CUR))) {
261
return x;
262
}
263
n += name_ofs - 24;
264
265
*dest = malloc(sizeof(dylib_t) + loadcmdsize - name_ofs + 1);
266
(*dest)->timestamp = timestamp;
267
(*dest)->current_version = current_version;
268
(*dest)->compatibility_version = compatibility_version;
269
if ((x = read_fully(fd, loadcmdsize - name_ofs, (*dest)->path)) < 0) {
270
free(*dest);
271
*dest = 0;
272
return x;
273
}
274
n += x;
275
(*dest)->path[loadcmdsize - name_ofs] = '\0';
276
return n;
277
}
278
279
ssize_t
280
read_build_version(const int fd, const bool swap, build_version_t **dest)
281
{
282
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
READ(u32, platform);
290
READ(version, minos);
291
READ(version, sdk);
292
READ(u32, ntools);
293
294
*dest = malloc(
295
sizeof(build_version_t) + ntools * sizeof(tool_version_t));
296
(*dest)->platform = platform;
297
(*dest)->minos = minos;
298
(*dest)->sdk = sdk;
299
(*dest)->ntools = ntools;
300
tool_version_t *p = (*dest)->tools;
301
302
for (; ntools-- > 0; p++) {
303
uint32_t tool;
304
READ(u32, tool);
305
p->tool = tool;
306
READ(version, p->version);
307
}
308
return n;
309
}
310
311
ssize_t
312
read_macho_header(const int fd, macho_header_t *dest)
313
{
314
ssize_t n = 0, x;
315
uint32_t reserved;
316
317
if ((x = read_u32(fd, false, &dest->magic) < 0)) {
318
return x;
319
}
320
n += x;
321
322
const bool swap = dest->swap = dest->magic == MH_CIGAM ||
323
dest->magic == MH_CIGAM_64;
324
325
READ(cpu_type, dest->cpu);
326
READ(u32, dest->filetype);
327
READ(u32, dest->ncmds);
328
READ(u32, dest->sizeofcmds);
329
READ(u32, dest->flags);
330
switch (dest->magic) {
331
case MH_MAGIC_64:
332
case MH_CIGAM_64:
333
READ(u32, reserved);
334
break;
335
default:
336
break;
337
}
338
return n;
339
}
340
341
ssize_t
342
read_macho_file(const int fd, macho_file_t **dest)
343
{
344
ssize_t n = 0, x;
345
346
uint32_t magic;
347
if ((x = read_u32(fd, false, &magic)) < 0) {
348
return x;
349
}
350
n += x;
351
352
const bool swap = magic == FAT_CIGAM || magic == FAT_CIGAM_64 ||
353
magic == MH_CIGAM || magic == MH_CIGAM_64;
354
355
uint32_t nfat_arch;
356
fat_arch_t *p;
357
switch (magic) {
358
case FAT_MAGIC:
359
case FAT_MAGIC_64:
360
case FAT_CIGAM:
361
case FAT_CIGAM_64:
362
READ(u32, nfat_arch);
363
*dest = malloc(
364
sizeof(macho_file_t) + nfat_arch * sizeof(fat_arch_t));
365
(*dest)->magic = magic;
366
(*dest)->narch = nfat_arch;
367
p = (*dest)->arch;
368
369
while (nfat_arch-- > 0) {
370
if ((x = read_fat_arch(fd, magic, p)) < 0) {
371
free(*dest);
372
*dest = 0;
373
return x;
374
}
375
n += x;
376
p++;
377
}
378
break;
379
380
case MH_MAGIC:
381
case MH_MAGIC_64:
382
case MH_CIGAM:
383
case MH_CIGAM_64:
384
nfat_arch = 1;
385
*dest = malloc(
386
sizeof(macho_file_t) + nfat_arch * sizeof(fat_arch_t));
387
(*dest)->magic = magic;
388
(*dest)->narch = nfat_arch;
389
p = (*dest)->arch;
390
READ(cpu_type, p->cpu);
391
off_t xo;
392
if (-1 == (xo = lseek(fd, 0, SEEK_END))) {
393
free(*dest);
394
*dest = 0;
395
return xo;
396
}
397
p->offset = 0;
398
p->size = xo;
399
p->align = 0; // number of trailing zero bits in size;
400
n = xo;
401
break;
402
default:
403
errno = EINVAL;
404
return -1;
405
}
406
return n;
407
}
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
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
switch (platform) {
651
case PLATFORM_MACOS:
652
p = macos_to_darwin[0];
653
break;
654
655
case PLATFORM_IOS:
656
case PLATFORM_IOSSIMULATOR:
657
case PLATFORM_TVOS:
658
case PLATFORM_TVOSSIMULATOR:
659
p = ios_to_darwin[0];
660
break;
661
662
case PLATFORM_WATCHOS:
663
case PLATFORM_WATCHOSSIMULATOR:
664
darwin->major = version.major + 13;
665
darwin->minor = version.minor;
666
darwin->patch = 0;
667
return 0;
668
669
default:
670
return -1;
671
}
672
while (p->major > version.major || p->minor > version.minor ||
673
p->patch > version.patch) {
674
p += 2;
675
}
676
p++;
677
if (0 == p->major && 0 == p->minor && 0 == p->patch) {
678
return -1;
679
}
680
*darwin = *p;
681
return 0;
682
}
683
684