Coverage Report

Created: 2026-06-30 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/upx/src/p_mach.h
Line
Count
Source
1
/* p_mach.h --
2
3
   This file is part of the UPX executable compressor.
4
5
   Copyright (C) Markus Franz Xaver Johannes Oberhumer
6
   Copyright (C) Laszlo Molnar
7
   All Rights Reserved.
8
9
   UPX and the UCL library are free software; you can redistribute them
10
   and/or modify them under the terms of the GNU General Public License as
11
   published by the Free Software Foundation; either version 2 of
12
   the License, or (at your option) any later version.
13
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
19
   You should have received a copy of the GNU General Public License
20
   along with this program; see the file COPYING.
21
   If not, write to the Free Software Foundation, Inc.,
22
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24
   Markus F.X.J. Oberhumer              Laszlo Molnar
25
   <markus@oberhumer.com>               <ezerotven+github@gmail.com>
26
 */
27
28
#pragma once
29
30
#include "conf.h"
31
32
packed_struct(Mach_fat_header) {
33
    BE32 magic;
34
        enum : unsigned {  // note conflict with java bytecode PackLinuxI386
35
            FAT_MAGIC      = 0xcafebabe,
36
            FAT_MAGIC_SWAB = 0xbebafeca,
37
        };
38
    BE32 nfat_arch;  // Number of Mach_fat_arch which follow.
39
};
40
41
packed_struct(Mach_fat_arch) {
42
    BE32 cputype;
43
    BE32 cpusubtype;
44
    BE32 offset;
45
    BE32 size;
46
    BE32 align;  /* shift count; log base 2 */
47
};
48
49
/*************************************************************************
50
// Mach  Mach Object executable; all structures are target-endian
51
// 'otool' is the Mach analog of 'readelf' (convert executable file to ASCII).
52
**************************************************************************/
53
54
namespace N_Mach {
55
56
// integral types
57
template <class TWord, class TXword, class TAddr, class TOff>
58
struct MachITypes
59
{
60
    typedef TWord   Word;
61
    typedef TXword  Xword;
62
    typedef TAddr   Addr;
63
    typedef TOff    Off;
64
};
65
66
template <class TMachITypes>
67
packed_struct(Mach_header) {
68
    typedef typename TMachITypes::Word Word;
69
70
    Word magic;
71
    Word cputype;
72
    Word cpusubtype;
73
    Word filetype;
74
    Word ncmds;
75
    Word sizeofcmds;
76
    Word flags;
77
#define WANT_MACH_HEADER_ENUM 1
78
#include "p_mach_enum.h"
79
};
80
81
template <class TMachITypes>
82
packed_struct(Mach_header64) {
83
    // only difference is padding to 0 mod 8
84
    typedef typename TMachITypes::Word Word;
85
86
    Word magic;
87
    Word cputype;
88
    Word cpusubtype;
89
    Word filetype;
90
    Word ncmds;
91
    Word sizeofcmds;
92
    Word flags;
93
    Word reserved;  // pad to 0 mod 8
94
#define WANT_MACH_HEADER_ENUM 1
95
#include "p_mach_enum.h"
96
};
97
98
template <class TMachITypes>
99
packed_struct(Mach_command) { // generic prefix
100
    typedef typename TMachITypes::Word Word;
101
102
    Word cmd;
103
    Word cmdsize;
104
    Word data[2];  // because cmdsize >= 16
105
#define WANT_MACH_SEGMENT_ENUM 1
106
#include "p_mach_enum.h"
107
};
108
109
template <class TMachITypes>
110
packed_struct(Mach_segment_command) {
111
    typedef typename TMachITypes::Word Word;
112
    typedef typename TMachITypes::Addr Addr;
113
    typedef typename TMachITypes::Off  Off;
114
115
    Word cmd;
116
    Word cmdsize;
117
    char segname[16];
118
    Addr vmaddr;
119
    Addr vmsize;
120
    Off  fileoff;
121
    Off  filesize;
122
    Word maxprot;
123
    Word initprot;
124
    Word nsects;
125
    Word flags;
126
#define WANT_MACH_SEGMENT_ENUM 1
127
#include "p_mach_enum.h"
128
};
129
130
template <class TMachITypes>
131
packed_struct(Mach_section_command) {
132
    typedef typename TMachITypes::Word Word;
133
    typedef typename TMachITypes::Addr Addr;
134
    typedef typename TMachITypes::Off  Off;
135
136
    char sectname[16];
137
    char segname[16];
138
    Addr addr;   /* memory address */
139
    Addr size;   /* size in bytes */
140
    Word offset; /* file offset */
141
    Word align;  /* power of 2 */
142
    Word reloff; /* file offset of relocation entries */
143
    Word nreloc; /* number of relocation entries */
144
    Word flags;  /* section type and attributes */
145
    Word reserved1;  /* for offset or index */
146
    Word reserved2;  /* for count or sizeof */
147
#define WANT_MACH_SECTION_ENUM 1
148
#include "p_mach_enum.h"
149
};
150
151
template <class TMachITypes>
152
packed_struct(Mach_section_command_64) {
153
    typedef typename TMachITypes::Word Word;
154
    typedef typename TMachITypes::Addr Addr;
155
    typedef typename TMachITypes::Off  Off;
156
    typedef typename TMachITypes::Word Off32;
157
    typedef typename TMachITypes::Xword Xword;
158
159
    char sectname[16];
160
    char segname[16];
161
    Addr addr;   /* memory address */
162
    Addr size;   /* size in bytes */
163
    Off32 offset; /* file offset */
164
    Word align;  /* power of 2 */
165
    Word reloff; /* file offset of relocation entries */
166
    Word nreloc; /* number of relocation entries */
167
    Word flags;  /* section type and attributes */
168
    Word reserved1;  /* for offset or index */
169
    Word reserved2;  /* for count or sizeof */
170
    Word reserved3;  /* NOT IN 32-bit VERSION!! */
171
#define WANT_MACH_SECTION_ENUM 1
172
#include "p_mach_enum.h"
173
};
174
175
template <class TMachITypes>
176
packed_struct(Mach_symtab_command) {
177
    typedef typename TMachITypes::Word Word;
178
    typedef typename TMachITypes::Off  Off;
179
    typedef typename TMachITypes::Word Off32;
180
181
    Word cmd;      /* LC_SYMTAB */
182
    Word cmdsize;  /* sizeof(struct Mach_symtab_command) */
183
    Off32 symoff;  /* symbol table offset */
184
    Word nsyms;    /* number of symbol table entries */
185
    Off32 stroff;  /* string table offset */
186
    Word strsize;  /* string table size in bytes */
187
};
188
189
template <class TMachITypes>
190
packed_struct(Mach_dysymtab_command) {
191
    typedef typename TMachITypes::Word Word;
192
    typedef typename TMachITypes::Off  Off;
193
    typedef typename TMachITypes::Word Off32;
194
195
    Word cmd;           /* LC_DYSYMTAB */
196
    Word cmdsize;       /* sizeof(struct Mach_dysymtab_command) */
197
    Word ilocalsym;     /* index to local symbols */
198
    Word nlocalsym;     /* number of local symbols */
199
    Word iextdefsym;    /* index to externally defined symbols */
200
    Word nextdefsym;    /* number of externally defined symbols */
201
    Word iundefsym;     /* index to undefined symbols */
202
    Word nundefsym;     /* number of undefined symbols */
203
    Off32 tocoff;       /* file offset to table of contents */
204
    Word ntoc;          /* number of entries in table of contents */
205
    Off32 modtaboff;    /* file offset to module table */
206
    Word nmodtab;       /* number of module table entries */
207
    Off32 extrefsymoff; /* offset to referenced symbol table */
208
    Word nextrefsymoff; /* number of referenced symbol table entries */
209
    Off32 indirectsymoff; /* file offset to the indirect symbol table */
210
    Word nindirectsyms; /* number of indirect symbol table entries */
211
    Off32 extreloff;    /* offset to external relocation entries */
212
    Word nextrel;       /* number of external relocation entries */
213
    Off32 locreloff;      /* offset to local relocation entries */
214
    Word nlocrel;       /* number of local relocation entries */
215
};
216
217
template <class TMachITypes>
218
packed_struct(Mach_segsplit_info_command) {
219
    typedef typename TMachITypes::Word Word;
220
    typedef typename TMachITypes::Off  Off;
221
222
    Word cmd;           /* LC_SEGMENT_SPLIT_INFO */
223
    Word cmdsize;       /* sizeof(struct Mach_segsplit_info_command) */
224
    Off dataoff;
225
    Word datasize;
226
};
227
228
template <class TMachITypes>
229
packed_struct(Mach_routines_command) {
230
    typedef typename TMachITypes::Word Word;
231
    typedef typename TMachITypes::Addr Addr;
232
233
    Word cmd;
234
    Word cmdsize;
235
    Addr init_address;
236
    Word init_module;
237
    Word reserved1;
238
    Word reserved2;
239
    Word reserved3;
240
    Word reserved4;
241
    Word reserved5;
242
    Word reserved6;
243
#define WANT_MACH_SEGMENT_ENUM 1
244
#include "p_mach_enum.h"
245
};
246
247
template <class TMachITypes>
248
packed_struct(Mach_routines_command_64) {
249
    typedef typename TMachITypes::Word Word;
250
    typedef typename TMachITypes::Addr Addr;
251
    typedef typename TMachITypes::Xword Xword;
252
253
    Word cmd;
254
    Word cmdsize;
255
    Addr init_address;
256
    Xword init_module;
257
    Xword reserved1;
258
    Xword reserved2;
259
    Xword reserved3;
260
    Xword reserved4;
261
    Xword reserved5;
262
    Xword reserved6;
263
#define WANT_MACH_SEGMENT_ENUM 1
264
#include "p_mach_enum.h"
265
};
266
267
template <class TMachITypes>
268
packed_struct(Mach_twolevel_hints_command) {
269
    typedef typename TMachITypes::Word Word;
270
    typedef typename TMachITypes::Off  Off;
271
272
    Word cmd;
273
    Word cmdsize;
274
    Off offset;   /* offset to the hint table */
275
    Word nhints;  /* number of hints */
276
#define WANT_MACH_SEGMENT_ENUM 1
277
#include "p_mach_enum.h"
278
};
279
280
template <class TMachITypes>
281
packed_struct(Mach_linkedit_data_command) {
282
    typedef typename TMachITypes::Word Word;
283
284
    Word cmd;  // LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO,
285
               // LC_FUNCTION_STARTS, LC_DATA_IN_CODE,
286
               // LC_DYLIB_CODE_SIGN_DRS, LC_LINKER_OPTIMIZATION_HINT
287
    Word cmdsize;
288
    Word dataoff;  // file offset of data in __LINKEDIT segment
289
    Word datasize;  // file size of data in __LINKEDIT segment
290
};
291
292
template <class TMachITypes>
293
packed_struct(Mach_uuid_command) {
294
    typedef typename TMachITypes::Word Word;
295
296
    Word cmd;  // LC_UUID
297
    Word cmdsize;  // 24
298
    unsigned char uuid[16];
299
};
300
301
template <class TMachITypes, class TMachThreadState>
302
packed_struct(Mach_thread_command) {
303
    typedef typename TMachITypes::Word Word;
304
305
    Word cmd;            /* LC_THREAD or  LC_UNIXTHREAD */
306
    Word cmdsize;        /* total size of this command */
307
    Word flavor;
308
    Word count;          /* sizeof(following_thread_state)/4 */
309
    TMachThreadState state;
310
#define WANT_MACH_THREAD_ENUM 1
311
#include "p_mach_enum.h"
312
};
313
314
template <class TMachITypes>
315
packed_struct(Mach_main_command) {
316
    typedef typename TMachITypes::Word Word;
317
    typedef typename TMachITypes::Xword Xword;
318
319
    Word cmd;  // LC_MAIN;  MH_EXECUTE only
320
    Word cmdsize;  // 24
321
    Xword entryoff;  // file offset of main() [expected in __TEXT]
322
    Xword stacksize;  // non-default initial stack size
323
};
324
325
template <class TMachITypes>
326
packed_struct(Mach_source_version_command) {
327
    typedef typename TMachITypes::Word Word;
328
329
    Word cmd;  // LC_SOURCE_VERSION
330
    Word cmdsize;  // 16
331
    Word version;
332
    Word __pad;  // to 0 mod 8
333
};
334
335
template <class TMachITypes>
336
packed_struct(Mach_version_min_command) {
337
    typedef typename TMachITypes::Word Word;
338
339
    Word cmd;  // LC_VERSION_MIN_MACOSX
340
    Word cmdsize;  // 16
341
    Word version;  // X.Y.Z ==> xxxx.yy.zz
342
    Word sdk;  // X.Y.Z ==> xxxx.yy.zz
343
};
344
345
template <class TMachITypes>
346
packed_struct(Mach_dyld_info_only_command) {
347
    typedef typename TMachITypes::Word Word;
348
349
    Word cmd;  // LC_DYLD_INFO_ONLY
350
    Word cmdsize;  // 48
351
    Word rebase_off;
352
    Word rebase_size;
353
    Word bind_off;
354
    Word bind_size;
355
    Word weak_bind_off;
356
    Word weak_bind_size;
357
    Word lazy_bind_off;
358
    Word lazy_bind_size;
359
    Word export_off;
360
    Word export_size;
361
};
362
363
template <class TMachITypes>
364
packed_struct(Mach_load_dylinker_command) {
365
    typedef typename TMachITypes::Word Word;
366
367
    Word cmd;
368
    Word cmdsize;
369
    Word name;
370
};
371
372
template <class TMachITypes>
373
packed_struct(Mach_dylib) {
374
    typedef typename TMachITypes::Word Word;
375
376
    Word name;         /* library's path name */
377
    Word timestamp;         /* library's build time stamp */
378
    Word current_version;       /* library's current version number */
379
    Word compatibility_version; /* library's compatibility vers number*/
380
};
381
382
template <class TMachITypes>
383
packed_struct(Mach_load_dylib_command) {
384
    typedef typename TMachITypes::Word Word;
385
386
    Word cmd;
387
    Word cmdsize;
388
    Mach_dylib<TMachITypes> dylib;
389
};
390
391
}  // namespace N_Mach
392
393
namespace N_Mach32 {
394
395
template <class TMachITypes>
396
packed_struct(Mach_ppc_thread_state) {
397
    typedef typename TMachITypes::Addr Addr;
398
399
    Addr srr0;      /* Instruction address register (PC; entry addr) */
400
    Addr srr1;      /* Machine state register (supervisor) */
401
    Addr  r0, r1, r2, r3, r4, r5, r6, r7;
402
    Addr  r8, r9,r10,r11,r12,r13,r14,r15;
403
    Addr r16,r17,r18,r19,r20,r21,r22,r23;
404
    Addr r24,r25,r26,r27,r28,r29,r30,r31;
405
406
    Addr cr;        /* Condition register */  // FIXME: Word?
407
    Addr xer;       /* User's integer exception register */
408
    Addr lr;        /* Link register */
409
    Addr ctr;       /* Count register */
410
    Addr mq;        /* MQ register (601 only) */
411
412
    Addr vrsave;    /* Vector Save Register */
413
};
414
415
template <class TMachITypes>
416
packed_struct(Mach_i386_thread_state) {
417
    typedef typename TMachITypes::Word Word;
418
419
    Word eax, ebx, ecx, edx;
420
    Word edi, esi, ebp;
421
    Word esp, ss;
422
    Word eflags;
423
    Word eip, cs;
424
    Word ds, es, fs, gs;
425
};
426
427
template <class TMachITypes>
428
packed_struct(Mach_ARM_thread_state) {
429
    typedef typename TMachITypes::Word Word;
430
431
    Word r[13];  // r0-r12
432
    Word sp;  // r13
433
    Word lr;  // r14
434
    Word pc;  // r15
435
    Word cpsr;
436
};
437
438
} // namespace N_Mach32
439
440
namespace N_Mach64 {
441
442
template <class TMachITypes>
443
packed_struct(Mach_AMD64_thread_state) {
444
    typedef typename TMachITypes::Xword Xword;
445
446
    Xword rax, rbx, rcx, rdx;
447
    Xword rdi, rsi, rbp, rsp;
448
    Xword  r8,  r9, r10, r11;
449
    Xword r12, r13, r14, r15;
450
    Xword rip, rflags;
451
    Xword cs, fs, gs;
452
};
453
454
template <class TMachITypes>
455
packed_struct(Mach_ppc_thread_state64) {
456
    typedef typename TMachITypes::Word Word;
457
    typedef typename TMachITypes::Xword Xword;
458
459
    Xword srr0;    /* Instruction address register (PC; entry addr) */
460
    Xword srr1;    /* Machine state register (supervisor) */
461
    Xword  r0, r1, r2, r3, r4, r5, r6, r7;
462
    Xword  r8, r9,r10,r11,r12,r13,r14,r15;
463
    Xword r16,r17,r18,r19,r20,r21,r22,r23;
464
    Xword r24,r25,r26,r27,r28,r29,r30,r31;
465
466
    Word cr;        /* Condition register */  // FIXME: Xword?
467
    Xword xer;      /* User's integer exception register */
468
    Xword lr;       /* Link register */
469
    Xword ctr;      /* Count register */
470
471
    Word vrsave;    /* Vector Save Register */
472
};
473
474
template <class TMachITypes>
475
packed_struct(Mach_ARM64_thread_state) {
476
    typedef typename TMachITypes::Xword Xword;
477
    typedef typename TMachITypes::Word Word;
478
479
    Xword x0,  x1,  x2,  x3;
480
    Xword x4,  x5,  x6,  x7;
481
    Xword x8,  x9,  x10, x11;
482
    Xword x12, x13, x14, x15;
483
    Xword x16, x17, x18, x19;
484
    Xword x20, x21, x22, x23;
485
    Xword x24, x25, x26, x27;
486
    Xword x28, fp,  lr,  sp;
487
    Xword pc;
488
    Word cpsr;
489
    Word pad;  // to (0 mod 8)
490
};
491
492
}  // namespace N_Mach64
493
494
namespace N_Mach {
495
496
template <class TP>
497
struct MachClass_32
498
{
499
    typedef TP BeLePolicy;
500
501
    // integral types (target endianness)
502
    typedef typename TP::U16 TE16;
503
    typedef typename TP::U32 TE32;
504
    typedef typename TP::U64 TE64;
505
    typedef N_Mach::MachITypes<TE32, TE64, TE32, TE32> MachITypes;
506
    typedef typename MachITypes::Addr Addr;
507
508
    // Mach types
509
    typedef N_Mach::Mach_header<MachITypes> Mach_header;
510
    typedef N_Mach::Mach_command<MachITypes> Mach_command;
511
    typedef N_Mach::Mach_segment_command<MachITypes> Mach_segment_command;
512
    typedef N_Mach::Mach_section_command<MachITypes> Mach_section_command;
513
    typedef N_Mach::Mach_symtab_command<MachITypes>  Mach_symtab_command;
514
    typedef N_Mach::Mach_dysymtab_command<MachITypes> Mach_dysymtab_command;
515
    typedef N_Mach::Mach_segsplit_info_command<MachITypes> Mach_segsplit_info_command;
516
    typedef N_Mach::Mach_routines_command<MachITypes> Mach_routines_command;
517
    typedef N_Mach::Mach_twolevel_hints_command<MachITypes> Mach_twolevel_hints_command;
518
    typedef N_Mach::Mach_linkedit_data_command<MachITypes> Mach_linkedit_data_command;
519
    typedef N_Mach::Mach_uuid_command<MachITypes> Mach_uuid_command;
520
    typedef N_Mach::Mach_load_dylib_command<MachITypes> Mach_load_dylib_command;
521
    typedef N_Mach::Mach_dylib<MachITypes> Mach_dylib;
522
    typedef N_Mach::Mach_load_dylinker_command<MachITypes> Mach_load_dylinker_command;
523
    typedef N_Mach::Mach_dyld_info_only_command<MachITypes> Mach_dyld_info_only_command;
524
    typedef N_Mach::Mach_version_min_command<MachITypes> Mach_version_min_command;
525
    typedef N_Mach::Mach_source_version_command<MachITypes> Mach_source_version_command;
526
    typedef N_Mach::Mach_main_command<MachITypes> Mach_main_command;
527
528
    typedef N_Mach32::Mach_ppc_thread_state<MachITypes> Mach_ppc_thread_state;
529
    typedef N_Mach32::Mach_i386_thread_state<MachITypes> Mach_i386_thread_state;
530
    typedef N_Mach32::Mach_ARM_thread_state<MachITypes> Mach_ARM_thread_state;
531
532
44.9k
    static void compileTimeAssertions() {
533
44.9k
        BeLePolicy::compileTimeAssertions();
534
44.9k
        COMPILE_TIME_ASSERT(sizeof(Addr) == 4)
535
44.9k
    }
N_Mach::MachClass_32<N_BELE_CTP::BEPolicy>::compileTimeAssertions()
Line
Count
Source
532
16.8k
    static void compileTimeAssertions() {
533
16.8k
        BeLePolicy::compileTimeAssertions();
534
16.8k
        COMPILE_TIME_ASSERT(sizeof(Addr) == 4)
535
16.8k
    }
N_Mach::MachClass_32<N_BELE_CTP::LEPolicy>::compileTimeAssertions()
Line
Count
Source
532
28.0k
    static void compileTimeAssertions() {
533
28.0k
        BeLePolicy::compileTimeAssertions();
534
28.0k
        COMPILE_TIME_ASSERT(sizeof(Addr) == 4)
535
28.0k
    }
536
};
537
538
template <class TP>
539
struct MachClass_64
540
{
541
    typedef TP BeLePolicy;
542
543
    // integral types (target endianness)
544
    typedef typename TP::U16 TE16;
545
    typedef typename TP::U32 TE32;
546
    typedef typename TP::U64 TE64;
547
    typedef N_Mach::MachITypes<TE32, TE64, TE64, TE64> MachITypes;
548
    typedef typename MachITypes::Addr Addr;
549
550
    // Mach types
551
    typedef N_Mach::Mach_header64<MachITypes> Mach_header;
552
    typedef N_Mach::Mach_command<MachITypes> Mach_command;
553
    typedef N_Mach::Mach_segment_command<MachITypes> Mach_segment_command;
554
    typedef N_Mach::Mach_section_command_64<MachITypes> Mach_section_command;
555
    typedef N_Mach::Mach_symtab_command<MachITypes>  Mach_symtab_command;
556
    typedef N_Mach::Mach_dysymtab_command<MachITypes> Mach_dysymtab_command;
557
    typedef N_Mach::Mach_segsplit_info_command<MachITypes> Mach_segsplit_info_command;
558
    typedef N_Mach::Mach_routines_command_64<MachITypes> Mach_routines_command;
559
    typedef N_Mach::Mach_twolevel_hints_command<MachITypes> Mach_twolevel_hints_command;
560
    typedef N_Mach::Mach_linkedit_data_command<MachITypes> Mach_linkedit_data_command;
561
    typedef N_Mach::Mach_uuid_command<MachITypes> Mach_uuid_command;
562
    typedef N_Mach::Mach_load_dylib_command<MachITypes> Mach_load_dylib_command;
563
    typedef N_Mach::Mach_dylib<MachITypes> Mach_dylib;
564
    typedef N_Mach::Mach_load_dylinker_command<MachITypes> Mach_load_dylinker_command;
565
    typedef N_Mach::Mach_dyld_info_only_command<MachITypes> Mach_dyld_info_only_command;
566
    typedef N_Mach::Mach_version_min_command<MachITypes> Mach_version_min_command;
567
    typedef N_Mach::Mach_source_version_command<MachITypes> Mach_source_version_command;
568
    typedef N_Mach::Mach_main_command<MachITypes> Mach_main_command;
569
570
    typedef N_Mach64::Mach_ppc_thread_state64<MachITypes> Mach_ppc_thread_state64;
571
    typedef N_Mach64::Mach_AMD64_thread_state<MachITypes> Mach_AMD64_thread_state;
572
    typedef N_Mach64::Mach_ARM64_thread_state<MachITypes> Mach_ARM64_thread_state;
573
574
43.0k
    static void compileTimeAssertions() {
575
43.0k
        BeLePolicy::compileTimeAssertions();
576
43.0k
        COMPILE_TIME_ASSERT(sizeof(Addr) == 8)
577
43.0k
    }
N_Mach::MachClass_64<N_BELE_CTP::BEPolicy>::compileTimeAssertions()
Line
Count
Source
574
314
    static void compileTimeAssertions() {
575
314
        BeLePolicy::compileTimeAssertions();
576
314
        COMPILE_TIME_ASSERT(sizeof(Addr) == 8)
577
314
    }
N_Mach::MachClass_64<N_BELE_CTP::LEPolicy>::compileTimeAssertions()
Line
Count
Source
574
42.7k
    static void compileTimeAssertions() {
575
42.7k
        BeLePolicy::compileTimeAssertions();
576
42.7k
        COMPILE_TIME_ASSERT(sizeof(Addr) == 8)
577
42.7k
    }
578
};
579
580
}  // namespace N_Mach
581
582
typedef N_Mach::MachClass_32<N_BELE_CTP::HostPolicy> MachClass_Host32;
583
typedef N_Mach::MachClass_64<N_BELE_CTP::HostPolicy> MachClass_Host64;
584
typedef N_Mach::MachClass_32<N_BELE_CTP::BEPolicy>   MachClass_BE32;
585
typedef N_Mach::MachClass_64<N_BELE_CTP::BEPolicy>   MachClass_BE64;
586
typedef N_Mach::MachClass_32<N_BELE_CTP::LEPolicy>   MachClass_LE32;
587
typedef N_Mach::MachClass_64<N_BELE_CTP::LEPolicy>   MachClass_LE64;
588
589
// shortcuts
590
typedef MachClass_Host32::Mach_segment_command Mach32_segment_command;
591
typedef MachClass_Host32::Mach_section_command Mach32_section_command;
592
typedef MachClass_Host32::Mach_symtab_command Mach32_symtab_command;
593
typedef MachClass_Host32::Mach_dysymtab_command Mach32_dysymtab_command;
594
typedef MachClass_Host32::Mach_segsplit_info_command Mach32_segsplit_info_command;
595
typedef MachClass_Host32::Mach_routines_command Mach32_routines_command;
596
typedef MachClass_Host32::Mach_twolevel_hints_command Mach32_twolevel_hints_command;
597
typedef MachClass_Host32::Mach_linkedit_data_command Mach32_linkedit_data_command;
598
typedef MachClass_Host32::Mach_uuid_command Mach32_uuid_command;
599
typedef MachClass_Host32::Mach_main_command Mach32_main_command;
600
typedef MachClass_Host32::Mach_load_dylib_command Mach32_load_dylib_command;
601
typedef MachClass_Host32::Mach_dylib Mach32_dylib;
602
typedef MachClass_Host32::Mach_load_dylinker_command Mach32_load_dylinker_command;
603
typedef MachClass_Host32::Mach_dyld_info_only_command Mach32_dyld_info_only_command;
604
typedef MachClass_Host32::Mach_version_min_command Mach32_version_min_command;
605
typedef MachClass_Host32::Mach_source_version_command Mach32_source_version_command;
606
607
typedef MachClass_Host64::Mach_segment_command Mach64_segment_command;
608
typedef MachClass_Host64::Mach_section_command Mach64_section_command;
609
typedef MachClass_Host64::Mach_symtab_command Mach64_symtab_command;
610
typedef MachClass_Host64::Mach_dysymtab_command Mach64_dysymtab_command;
611
typedef MachClass_Host64::Mach_segsplit_info_command Mach64_segsplit_info_command;
612
typedef MachClass_Host64::Mach_routines_command Mach64_routines_command;
613
typedef MachClass_Host64::Mach_twolevel_hints_command Mach64_twolevel_hints_command;
614
typedef MachClass_Host64::Mach_linkedit_data_command Mach64_linkedit_data_command;
615
typedef MachClass_Host64::Mach_uuid_command Mach64_uuid_command;
616
typedef MachClass_Host64::Mach_main_command Mach64_main_command;
617
typedef MachClass_Host64::Mach_load_dylib_command Mach64_load_dylib_command;
618
typedef MachClass_Host64::Mach_dylib Mach64_dylib;
619
typedef MachClass_Host64::Mach_load_dylinker_command Mach64_load_dylinker_command;
620
typedef MachClass_Host64::Mach_dyld_info_only_command Mach64_dyld_info_only_command;
621
typedef MachClass_Host64::Mach_version_min_command Mach64_version_min_command;
622
typedef MachClass_Host64::Mach_source_version_command Mach64_source_version_command;
623
624
typedef MachClass_BE32::Mach_segment_command   MachBE32_segment_command;
625
typedef MachClass_BE32::Mach_section_command   MachBE32_section_command;
626
typedef MachClass_BE32::Mach_symtab_command   MachBE32_symtab_command;
627
typedef MachClass_BE32::Mach_dysymtab_command   MachBE32_dysymtab_command;
628
typedef MachClass_BE32::Mach_segsplit_info_command   MachBE32_segsplit_info_command;
629
typedef MachClass_BE32::Mach_routines_command   MachBE32_routines_command;
630
typedef MachClass_BE32::Mach_twolevel_hints_command   MachBE32_twolevel_hints_command;
631
typedef MachClass_BE32::Mach_linkedit_data_command   MachBE32_linkedit_data_command;
632
typedef MachClass_BE32::Mach_uuid_command   MachBE32_uuid_command;
633
typedef MachClass_BE32::Mach_main_command MachBE32_main_command;
634
typedef MachClass_BE32::Mach_load_dylib_command MachBE32_load_dylib_command;
635
typedef MachClass_BE32::Mach_dylib MachBE32_dylib;
636
typedef MachClass_BE32::Mach_load_dylinker_command MachBE32_load_dylinker_command;
637
typedef MachClass_BE32::Mach_dyld_info_only_command MachBE32_dyld_info_only_command;
638
typedef MachClass_BE32::Mach_version_min_command MachBE32_version_min_command;
639
typedef MachClass_BE32::Mach_source_version_command MachBE32_source_version_command;
640
641
typedef MachClass_BE64::Mach_segment_command   MachBE64_segment_command;
642
typedef MachClass_BE64::Mach_section_command   MachBE64_section_command;
643
typedef MachClass_BE64::Mach_symtab_command   MachBE64_symtab_command;
644
typedef MachClass_BE64::Mach_dysymtab_command   MachBE64_dysymtab_command;
645
typedef MachClass_BE64::Mach_segsplit_info_command   MachBE64_segsplit_info_command;
646
typedef MachClass_BE64::Mach_routines_command   MachBE64_routines_command;
647
typedef MachClass_BE64::Mach_twolevel_hints_command   MachBE64_twolevel_hints_command;
648
typedef MachClass_BE64::Mach_linkedit_data_command   MachBE64_linkedit_data_command;
649
typedef MachClass_BE64::Mach_uuid_command   MachBE64_uuid_command;
650
typedef MachClass_BE64::Mach_main_command MachBE64_main_command;
651
typedef MachClass_BE64::Mach_load_dylib_command MachBE64_load_dylib_command;
652
typedef MachClass_BE64::Mach_dylib MachBE64_dylib;
653
typedef MachClass_BE64::Mach_load_dylinker_command MachBE64_load_dylinker_command;
654
typedef MachClass_BE64::Mach_dyld_info_only_command MachBE64_dyld_info_only_command;
655
typedef MachClass_BE64::Mach_version_min_command MachBE64_version_min_command;
656
typedef MachClass_BE64::Mach_source_version_command MachBE64_source_version_command;
657
658
typedef MachClass_LE32::Mach_segment_command   MachLE32_segment_command;
659
typedef MachClass_LE32::Mach_section_command   MachLE32_section_command;
660
typedef MachClass_LE32::Mach_symtab_command   MachLE32_symtab_command;
661
typedef MachClass_LE32::Mach_dysymtab_command   MachLE32_dysymtab_command;
662
typedef MachClass_LE32::Mach_segsplit_info_command   MachLE32_segsplit_info_command;
663
typedef MachClass_LE32::Mach_routines_command   MachLE32_routines_command;
664
typedef MachClass_LE32::Mach_twolevel_hints_command   MachLE32_twolevel_hints_command;
665
typedef MachClass_LE32::Mach_linkedit_data_command   MachLE32_linkedit_data_command;
666
typedef MachClass_LE32::Mach_uuid_command   MachLE32_uuid_command;
667
typedef MachClass_LE32::Mach_main_command  MachLE32_main_command;
668
typedef MachClass_LE32::Mach_load_dylib_command  MachLE32_load_dylib_command;
669
typedef MachClass_LE32::Mach_dylib  MachLE32_dylib;
670
typedef MachClass_LE32::Mach_load_dylinker_command  MachLE32_load_dylinker_command;
671
typedef MachClass_LE32::Mach_dyld_info_only_command  MachLE32_dyld_info_only_command;
672
typedef MachClass_LE32::Mach_version_min_command  MachLE32_version_min_command;
673
typedef MachClass_LE32::Mach_source_version_command MachLE32_source_version_command;
674
675
typedef MachClass_LE64::Mach_segment_command   MachLE64_segment_command;
676
typedef MachClass_LE64::Mach_section_command   MachLE64_section_command;
677
typedef MachClass_LE64::Mach_symtab_command   MachLE64_symtab_command;
678
typedef MachClass_LE64::Mach_dysymtab_command   MachLE64_dysymtab_command;
679
typedef MachClass_LE64::Mach_segsplit_info_command   MachLE64_segsplit_info_command;
680
typedef MachClass_LE64::Mach_routines_command   MachLE64_routines_command;
681
typedef MachClass_LE64::Mach_twolevel_hints_command   MachLE64_twolevel_hints_command;
682
typedef MachClass_LE64::Mach_linkedit_data_command   MachLE64_linkedit_data_command;
683
typedef MachClass_LE64::Mach_uuid_command   MachLE64_uuid_command;
684
typedef MachClass_LE64::Mach_main_command MachLE64_main_command;
685
typedef MachClass_LE64::Mach_load_dylib_command MachLE64_load_dylib_command;
686
typedef MachClass_LE64::Mach_dylib MachLE64_dylib;
687
typedef MachClass_LE64::Mach_load_dylinker_command MachLE64_load_dylinker_command;
688
typedef MachClass_LE64::Mach_dyld_info_only_command MachLE64_dyld_info_only_command;
689
typedef MachClass_LE64::Mach_version_min_command MachLE64_version_min_command;
690
typedef MachClass_LE64::Mach_source_version_command MachLE64_source_version_command;
691
692
typedef MachClass_BE32::Mach_ppc_thread_state  Mach_ppc_thread_state;
693
typedef MachClass_BE64::Mach_ppc_thread_state64  Mach_ppc_thread_state64;
694
typedef MachClass_LE32::Mach_i386_thread_state Mach_i386_thread_state;
695
typedef MachClass_LE64::Mach_AMD64_thread_state  Mach_AMD64_thread_state;
696
typedef MachClass_LE64::Mach_ARM64_thread_state  Mach_ARM64_thread_state;
697
typedef MachClass_LE32::Mach_ARM_thread_state  Mach_ARM_thread_state;
698
#include "p_unix.h"
699
700
701
template <class TMachClass>
702
class PackMachBase : public PackUnix
703
{
704
    typedef PackUnix super;
705
protected:
706
    typedef TMachClass MachClass;
707
    typedef typename MachClass::BeLePolicy BeLePolicy;
708
    typedef typename MachClass::MachITypes MachITypes;
709
    // integral types (target endianness)
710
    typedef typename MachClass::TE16  TE16;
711
    typedef typename MachClass::TE32  TE32;
712
    typedef typename MachClass::TE64  TE64;
713
    typedef typename MachClass::Addr  Addr;
714
    // Mach types
715
    typedef typename MachClass::Mach_header Mach_header;
716
    typedef typename MachClass::Mach_command Mach_command;
717
    typedef typename MachClass::Mach_segment_command Mach_segment_command;
718
    typedef typename MachClass::Mach_section_command Mach_section_command;
719
    typedef typename MachClass::Mach_symtab_command Mach_symtab_command;
720
    typedef typename MachClass::Mach_dysymtab_command Mach_dysymtab_command;
721
    typedef typename MachClass::Mach_segsplit_info_command Mach_segsplit_info_command;
722
    typedef typename MachClass::Mach_routines_command Mach_routines_command;
723
    typedef typename MachClass::Mach_twolevel_hints_command Mach_twolevel_hints_command;
724
    typedef typename MachClass::Mach_linkedit_data_command Mach_linkedit_data_command;
725
    typedef typename MachClass::Mach_uuid_command Mach_uuid_command;
726
    typedef typename MachClass::Mach_main_command Mach_main_command;
727
    typedef typename MachClass::Mach_load_dylib_command Mach_load_dylib_command;
728
    typedef typename MachClass::Mach_dylib Mach_dylib;
729
    typedef typename MachClass::Mach_load_dylinker_command Mach_load_dylinker_command;
730
    typedef typename MachClass::Mach_dyld_info_only_command Mach_dyld_info_only_command;
731
    typedef typename MachClass::Mach_version_min_command Mach_version_min_command;
732
    typedef typename MachClass::Mach_source_version_command Mach_source_version_command;
733
734
public:
735
    PackMachBase(InputFile *, unsigned cpuid, unsigned filetype,
736
        unsigned t_flavor, unsigned ts_word_cnt, unsigned tc_size,
737
        unsigned page_shift);
738
    virtual ~PackMachBase();
739
88.4k
    virtual int getVersion() const override { return 13; }
PackMachBase<N_Mach::MachClass_32<N_BELE_CTP::BEPolicy> >::getVersion() const
Line
Count
Source
739
16.8k
    virtual int getVersion() const override { return 13; }
PackMachBase<N_Mach::MachClass_32<N_BELE_CTP::LEPolicy> >::getVersion() const
Line
Count
Source
739
27.7k
    virtual int getVersion() const override { return 13; }
PackMachBase<N_Mach::MachClass_64<N_BELE_CTP::LEPolicy> >::getVersion() const
Line
Count
Source
739
43.9k
    virtual int getVersion() const override { return 13; }
Unexecuted instantiation: PackMachBase<N_Mach::MachClass_64<N_BELE_CTP::BEPolicy> >::getVersion() const
740
    virtual const int *getCompressionMethods(int method, int level) const override;
741
742
    // called by the generic pack()
743
    virtual void pack1(OutputFile *, Filter &) override;  // generate executable header
744
    virtual int  pack2(OutputFile *, Filter &) override;  // append compressed data
745
    virtual off_t pack3(OutputFile *, Filter &) override /*= 0*/;  // append loader
746
    virtual void pack4(OutputFile *, Filter &) override /*= 0*/;  // append PackHeader
747
748
    virtual void pack4dylib(OutputFile *, Filter &, Addr init_address);
749
750
    virtual int  threado_size() const = 0;
751
    virtual void threado_setPC(upx_uint64_t pc) = 0;
752
    virtual void threado_rewrite(OutputFile *) = 0;
753
    virtual void threado_write(OutputFile *) = 0;
754
    virtual void pack1_setup_threado(OutputFile *const fo) = 0;
755
    virtual void unpack(OutputFile *fo) override;
756
757
    virtual tribool canPack() override;
758
    virtual tribool canUnpack() override;
759
    virtual upx_uint64_t get_mod_init_func(Mach_segment_command const *segptr);
760
    virtual unsigned find_SEGMENT_gap(unsigned const k, unsigned pos_eof);
761
762
protected:
763
    virtual void patchLoader() override;
764
    virtual void patchLoaderChecksum() override;
765
    virtual void updateLoader(OutputFile *) override;
766
    virtual void buildLoader(const Filter *ft) override;
767
    virtual void buildMachLoader(
768
        upx_byte const *const proto,
769
        unsigned        const szproto,
770
        upx_byte const *const fold,
771
        unsigned        const szfold,
772
        Filter const *ft );
773
    virtual void defineSymbols(Filter const *);
774
    virtual void addStubEntrySections(Filter const *);
775
776
    static int __acc_cdecl_qsort compare_segment_command(void const *aa, void const *bb);
777
778
    virtual upx_uint64_t threadc_getPC(void /*MachThreadCommand*/ const *) = 0;
779
780
    upx_uint64_t entryVMA;
781
    upx_uint64_t my_page_size;
782
    upx_uint64_t my_page_mask;
783
    unsigned my_cputype;
784
    unsigned my_cpusubtype;
785
    unsigned my_filetype;
786
    unsigned my_thread_flavor;
787
    unsigned my_thread_state_word_count;
788
    unsigned my_thread_command_size;
789
790
    unsigned  n_segment;
791
    unsigned sz_segment;
792
    unsigned sz_mach_headers;
793
    unsigned sz_stub_entry;
794
    unsigned sz_stub_fold;
795
    unsigned sz_stub_main;
796
    upx_byte const *stub_entry;
797
    upx_byte const *stub_fold;
798
    upx_byte const *stub_main;
799
800
    MemBuffer rawmseg_buf;  // Mach_segment_command[];
801
    Mach_segment_command *rawmseg;  // as input, with sections
802
803
    MemBuffer msegcmd_buf;  // Mach_segment_command[];
804
    Mach_segment_command *msegcmd;  // LC_SEGMENT first, without sections
805
806
    unsigned o__mod_init_func;  // file offset to __DATA.__mod_init_func Mach_section_command
807
    upx_uint64_t prev_mod_init_func;
808
    upx_uint64_t pagezero_vmsize;
809
    upx_uint64_t vma_max;  // max over (.vmsize + .vmaddr)
810
    Mach_header mhdri;
811
812
    Mach_header mhdro;
813
    Mach_segment_command segZERO;
814
    Mach_segment_command segXHDR;  // location to put eXtra headers
815
    Mach_section_command secXHDR;
816
    Mach_segment_command segTEXT;
817
    Mach_section_command secTEXT;
818
    Mach_segment_command segLINK;
819
    Mach_linkedit_data_command linkitem;
820
    Mach_uuid_command cmdUUID;  // copied from input, then incremented
821
    Mach_source_version_command cmdSRCVER;  // copied from input
822
    Mach_version_min_command cmdVERMIN;  // copied from input
823
824
    packed_struct(b_info) {    // 12-byte header before each compressed block
825
        TE32 sz_unc;  // uncompressed_size
826
        TE32 sz_cpr;  //   compressed_size
827
        unsigned char b_method; // compression algorithm
828
        unsigned char b_ftid;   // filter id
829
        unsigned char b_cto8;   // filter parameter
830
        unsigned char b_segseq; // LC_SEGMENT ordinal
831
    };
832
833
    packed_struct(l_info) {    // 12-byte trailer in header for loader
834
        TE32 l_checksum;
835
        LE32 l_magic;
836
        TE16 l_lsize;
837
        unsigned char l_version;
838
        unsigned char l_format;
839
    };
840
841
    packed_struct(p_info) {    // 12-byte packed program header
842
        TE32 p_progid;
843
        TE32 p_filesize;
844
        TE32 p_blocksize;
845
    };
846
847
    struct l_info linfo;
848
849
0
    static void compileTimeAssertions() {
850
0
        MachClass::compileTimeAssertions();
851
0
        COMPILE_TIME_ASSERT(sizeof(b_info) == 12)
852
0
        COMPILE_TIME_ASSERT(sizeof(l_info) == 12)
853
0
        COMPILE_TIME_ASSERT(sizeof(p_info) == 12)
854
0
        COMPILE_TIME_ASSERT_ALIGNED1(b_info)
855
0
        COMPILE_TIME_ASSERT_ALIGNED1(l_info)
856
0
        COMPILE_TIME_ASSERT_ALIGNED1(p_info)
857
0
    }
Unexecuted instantiation: PackMachBase<N_Mach::MachClass_32<N_BELE_CTP::BEPolicy> >::compileTimeAssertions()
Unexecuted instantiation: PackMachBase<N_Mach::MachClass_32<N_BELE_CTP::LEPolicy> >::compileTimeAssertions()
Unexecuted instantiation: PackMachBase<N_Mach::MachClass_64<N_BELE_CTP::LEPolicy> >::compileTimeAssertions()
858
};
859
860
861
class PackMachPPC32 : public PackMachBase<MachClass_BE32>
862
{
863
    typedef PackMachBase<MachClass_BE32> super;
864
865
public:
866
    PackMachPPC32(InputFile *f);
867
868
33.6k
    virtual int getFormat() const override { return UPX_F_MACH_PPC32; }
869
60
    virtual const char *getName() const override { return "macho/ppc32"; }
870
0
    virtual const char *getFullName(const options_t *) const override { return "powerpc-darwin.macho"; }
871
872
protected:
873
    virtual const int *getFilters() const override;
874
875
    virtual void pack1_setup_threado(OutputFile *const fo) override;
876
    virtual Linker* newLinker() const override;
877
    virtual void addStubEntrySections(Filter const *) override;
878
879
    packed_struct(Mach_thread_command) {
880
        TE32 cmd;            /* LC_THREAD or  LC_UNIXTHREAD */
881
        TE32 cmdsize;        /* total size of this command */
882
        TE32 flavor;
883
        TE32 count;          /* sizeof(following_thread_state)/4 */
884
        Mach_ppc_thread_state state;
885
    #define WANT_MACH_THREAD_ENUM 1
886
    #include "p_mach_enum.h"
887
    };
888
889
    Mach_thread_command threado;
890
0
    int  threado_size() const override { return sizeof(threado); }
891
0
    void threado_setPC(upx_uint64_t pc) override {
892
0
        memset(&threado, 0, sizeof(threado));
893
0
        threado.cmd = Mach_segment_command::LC_UNIXTHREAD;
894
0
        threado.cmdsize = sizeof(threado);
895
0
        threado.flavor = my_thread_flavor;
896
0
        threado.count =  my_thread_state_word_count;
897
0
        threado.state.srr0 = pc;
898
0
    }
899
0
    void threado_rewrite(OutputFile *fo) override { fo->rewrite(&threado, sizeof(threado)); }
900
0
    void   threado_write(OutputFile *fo) override {   fo->write(&threado, sizeof(threado)); }
901
902
691
    upx_uint64_t threadc_getPC(void const *ptr) override {
903
691
        Mach_thread_command const *tc = (Mach_thread_command const *)ptr;
904
691
        if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD
905
691
        ||  tc->cmdsize!=sizeof(threado)
906
532
        ||  tc->flavor!=my_thread_flavor
907
644
        ||  tc->count!=my_thread_state_word_count) {
908
644
            return ~0ull;
909
644
        }
910
47
        return tc->state.srr0;
911
691
    }
912
};
913
914
class PackMachPPC64 : public PackMachBase<MachClass_BE64>
915
{
916
    typedef PackMachBase<MachClass_BE64> super;
917
918
public:
919
    PackMachPPC64(InputFile *f);
920
921
0
    virtual int getFormat() const override { return UPX_F_MACH_PPC64; }
922
0
    virtual const char *getName() const override { return "macho/ppc64"; }
923
0
    virtual const char *getFullName(const options_t *) const override { return "powerpc64-darwin.macho"; }
924
925
protected:
926
    virtual const int *getFilters() const override;
927
928
    virtual void pack1_setup_threado(OutputFile *const fo) override;
929
    virtual Linker* newLinker() const override;
930
931
    packed_struct(Mach_thread_command) {
932
        BE32 cmd;            /* LC_THREAD or  LC_UNIXTHREAD */
933
        BE32 cmdsize;        /* total size of this command */
934
        BE32 flavor;
935
        BE32 count;          /* sizeof(following_thread_state)/4 */
936
        Mach_ppc_thread_state64 state64;
937
    #define WANT_MACH_THREAD_ENUM 1
938
    #include "p_mach_enum.h"
939
    };
940
941
    Mach_thread_command threado;
942
0
    int threado_size() const override { return sizeof(threado); }
943
0
    void threado_setPC(upx_uint64_t pc) override {
944
0
        memset(&threado, 0, sizeof(threado));
945
0
        threado.cmd = Mach_segment_command::LC_UNIXTHREAD;
946
0
        threado.cmdsize = sizeof(threado);
947
0
        threado.flavor = my_thread_flavor;
948
0
        threado.count =  my_thread_state_word_count;
949
0
        threado.state64.srr0 = pc;
950
0
    }
951
0
    void threado_rewrite(OutputFile *fo) override { fo->rewrite(&threado, sizeof(threado)); }
952
0
    void   threado_write(OutputFile *fo) override {   fo->write(&threado, sizeof(threado)); }
953
954
1
    upx_uint64_t threadc_getPC(void const *ptr)  override{
955
1
        Mach_thread_command const *tc = (Mach_thread_command const *)ptr;
956
1
        if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD
957
1
        ||  tc->cmdsize!=sizeof(threado)
958
0
        ||  tc->flavor!=my_thread_flavor
959
1
        ||  tc->count!=my_thread_state_word_count) {
960
1
            return ~0ull;
961
1
        }
962
0
        return tc->state64.srr0;
963
1
    }
964
};
965
966
class PackDylibPPC32 : public PackMachPPC32
967
{
968
    typedef PackMachPPC32 super;
969
970
public:
971
    PackDylibPPC32(InputFile *f);
972
973
2
    virtual int getFormat() const override { return UPX_F_DYLIB_PPC32; }
974
0
    virtual const char *getName() const override { return "dylib/ppc32"; }
975
0
    virtual const char *getFullName(const options_t *) const override { return "powerpc-darwin.dylib"; }
976
protected:
977
    virtual off_t pack3(OutputFile *, Filter &) override;  // append loader
978
    virtual void pack4(OutputFile *, Filter &) override;  // append PackHeader
979
};
980
981
class PackDylibPPC64 : public PackMachPPC64
982
{
983
    typedef PackMachPPC64 super;
984
985
public:
986
    PackDylibPPC64(InputFile *f);
987
988
0
    virtual int getFormat() const override { return UPX_F_DYLIB_PPC64; }
989
0
    virtual const char *getName() const override { return "dylib/ppc64"; }
990
0
    virtual const char *getFullName(const options_t *) const override { return "powerpc64-darwin.dylib"; }
991
protected:
992
    virtual off_t pack3(OutputFile *, Filter &) override;  // append loader
993
    virtual void pack4(OutputFile *, Filter &) override;  // append PackHeader
994
};
995
996
class PackMachI386 : public PackMachBase<MachClass_LE32>
997
{
998
    typedef PackMachBase<MachClass_LE32> super;
999
1000
public:
1001
    PackMachI386(InputFile *f);
1002
1003
29.6k
    virtual int getFormat() const override { return UPX_F_MACH_i386; }
1004
1
    virtual const char *getName() const override { return "macho/i386"; }
1005
0
    virtual const char *getFullName(const options_t *) const override { return "i386-darwin.macho"; }
1006
protected:
1007
    virtual const int *getFilters() const override;
1008
1009
    virtual void pack1_setup_threado(OutputFile *const fo) override;
1010
    virtual Linker* newLinker() const override;
1011
    virtual void addStubEntrySections(Filter const *) override;
1012
1013
    packed_struct(Mach_thread_command) {
1014
        LE32 cmd;            /* LC_THREAD or  LC_UNIXTHREAD */
1015
        LE32 cmdsize;        /* total size of this command */
1016
        LE32 flavor;
1017
        LE32 count;          /* sizeof(following_thread_state)/4 */
1018
        Mach_i386_thread_state state;
1019
    #define WANT_MACH_THREAD_ENUM 1
1020
    #include "p_mach_enum.h"
1021
    };
1022
1023
    Mach_thread_command threado;
1024
0
    int threado_size() const override { return sizeof(threado); }
1025
0
    void threado_setPC(upx_uint64_t pc) override {
1026
0
        memset(&threado, 0, sizeof(threado));
1027
0
        threado.cmd = Mach_segment_command::LC_UNIXTHREAD;
1028
0
        threado.cmdsize = sizeof(threado);
1029
0
        threado.flavor = my_thread_flavor;
1030
0
        threado.count =  my_thread_state_word_count;
1031
0
        threado.state.eip = pc;
1032
0
    }
1033
0
    void threado_rewrite(OutputFile *fo) override { fo->rewrite(&threado, sizeof(threado)); }
1034
0
    void   threado_write(OutputFile *fo) override {   fo->write(&threado, sizeof(threado)); }
1035
1036
1.00k
    upx_uint64_t threadc_getPC(void const *ptr)  override{
1037
1.00k
        Mach_thread_command const *tc = (Mach_thread_command const *)ptr;
1038
1.00k
        if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD
1039
1.00k
        ||  tc->cmdsize!=sizeof(threado)
1040
599
        ||  tc->flavor!=my_thread_flavor
1041
930
        ||  tc->count!=my_thread_state_word_count) {
1042
930
            return ~0ull;
1043
930
        }
1044
74
        return tc->state.eip;
1045
1.00k
    }
1046
};
1047
1048
class PackDylibI386 : public PackMachI386
1049
{
1050
    typedef PackMachI386 super;
1051
1052
public:
1053
    PackDylibI386(InputFile *f);
1054
1055
15
    virtual int getFormat() const override { return UPX_F_DYLIB_i386; }
1056
0
    virtual const char *getName() const override { return "dylib/i386"; }
1057
0
    virtual const char *getFullName(const options_t *) const override { return "i386-darwin.dylib"; }
1058
protected:
1059
    virtual off_t pack3(OutputFile *, Filter &) override;  // append loader
1060
    virtual void pack4(OutputFile *, Filter &) override;  // append PackHeader
1061
};
1062
1063
class PackMachAMD64 : public PackMachBase<MachClass_LE64>
1064
{
1065
    typedef PackMachBase<MachClass_LE64> super;
1066
1067
public:
1068
    PackMachAMD64(InputFile *f);
1069
1070
28.7k
    virtual int getFormat() const override { return UPX_F_MACH_AMD64; }
1071
31
    virtual const char *getName() const override { return "macho/amd64"; }
1072
0
    virtual const char *getFullName(const options_t *) const override { return "amd64-darwin.macho"; }
1073
protected:
1074
    virtual const int *getFilters() const override;
1075
1076
    virtual void pack1_setup_threado(OutputFile *const fo) override;
1077
    virtual Linker* newLinker() const override;
1078
    virtual void addStubEntrySections(Filter const *) override;
1079
1080
    packed_struct(Mach_thread_command) {
1081
        typedef MachITypes::Word Word;
1082
        Word cmd;            /* LC_THREAD or  LC_UNIXTHREAD */
1083
        Word cmdsize;        /* total size of this command */
1084
        Word flavor;
1085
        Word count;          /* sizeof(following_thread_state)/4 */
1086
        Mach_AMD64_thread_state state;
1087
    #define WANT_MACH_THREAD_ENUM 1
1088
    #include "p_mach_enum.h"
1089
    };
1090
1091
    Mach_thread_command threado;
1092
0
    int threado_size() const override { return sizeof(threado); }
1093
0
    void threado_setPC(upx_uint64_t pc) override {
1094
0
        memset(&threado, 0, sizeof(threado));
1095
0
        threado.cmd = Mach_segment_command::LC_UNIXTHREAD;
1096
0
        threado.cmdsize = sizeof(threado);
1097
0
        threado.flavor = my_thread_flavor;
1098
0
        threado.count =  my_thread_state_word_count;
1099
0
        threado.state.rip = pc;
1100
0
    }
1101
0
    void threado_rewrite(OutputFile *fo) override { fo->rewrite(&threado, sizeof(threado)); }
1102
0
    void   threado_write(OutputFile *fo) override {   fo->write(&threado, sizeof(threado)); }
1103
1104
1.82k
    upx_uint64_t threadc_getPC(void const *ptr) override {
1105
1.82k
        Mach_thread_command const *tc = (Mach_thread_command const *)ptr;
1106
1.82k
        if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD
1107
1.82k
        ||  tc->cmdsize!=sizeof(threado)
1108
1.48k
        ||  tc->flavor!=my_thread_flavor
1109
1.09k
        ||  tc->count!=my_thread_state_word_count) {
1110
994
            return ~0ull;
1111
994
        }
1112
826
        return tc->state.rip;
1113
1.82k
    }
1114
};
1115
1116
class PackDylibAMD64 : public PackMachAMD64
1117
{
1118
    typedef PackMachAMD64 super;
1119
1120
public:
1121
    PackDylibAMD64(InputFile *f);
1122
1123
33.8k
    virtual int getFormat() const override { return UPX_F_DYLIB_AMD64; }
1124
3
    virtual const char *getName() const override { return "dylib/amd64"; }
1125
0
    virtual const char *getFullName(const options_t *) const override { return "amd64-darwin.dylib"; }
1126
protected:
1127
    virtual off_t pack3(OutputFile *, Filter &) override;  // append loader
1128
    virtual void pack4(OutputFile *, Filter &) override;  // append PackHeader
1129
};
1130
1131
class PackMachARMEL : public PackMachBase<MachClass_LE32>
1132
{
1133
    typedef PackMachBase<MachClass_LE32> super;
1134
1135
public:
1136
    PackMachARMEL(InputFile *f);
1137
1138
25.7k
    virtual int getFormat() const override { return UPX_F_MACH_ARM; }
1139
56
    virtual const char *getName() const override { return "macho/arm"; }
1140
0
    virtual const char *getFullName(const options_t *) const override { return "arm-darwin.macho"; }
1141
protected:
1142
    virtual const int *getCompressionMethods(int method, int level) const override;
1143
    virtual const int *getFilters() const override;
1144
1145
    virtual void pack1_setup_threado(OutputFile *const fo) override;
1146
    virtual Linker* newLinker() const override;
1147
    virtual void addStubEntrySections(Filter const *) override;
1148
1149
    packed_struct(Mach_thread_command) {
1150
        LE32 cmd;            /* LC_THREAD or  LC_UNIXTHREAD */
1151
        LE32 cmdsize;        /* total size of this command */
1152
        LE32 flavor;
1153
        LE32 count;          /* sizeof(following_thread_state)/4 */
1154
        Mach_ARM_thread_state state;
1155
    #define WANT_MACH_THREAD_ENUM 1
1156
    #include "p_mach_enum.h"
1157
    };
1158
1159
    Mach_thread_command threado;
1160
0
    int threado_size() const override { return sizeof(threado); }
1161
0
    void threado_setPC(upx_uint64_t pc) override {
1162
0
        memset(&threado, 0, sizeof(threado));
1163
0
        threado.cmd = Mach_segment_command::LC_UNIXTHREAD;
1164
0
        threado.cmdsize = sizeof(threado);
1165
0
        threado.flavor = my_thread_flavor;
1166
0
        threado.count =  my_thread_state_word_count;
1167
0
        threado.state.pc = pc;
1168
0
    }
1169
0
    void threado_rewrite(OutputFile *fo) override { fo->rewrite(&threado, sizeof(threado)); }
1170
0
    void   threado_write(OutputFile *fo) override { return   fo->write(&threado, sizeof(threado)); }
1171
1172
1.79k
    upx_uint64_t threadc_getPC(void const *ptr) override {
1173
1.79k
        Mach_thread_command const *tc = (Mach_thread_command const *)ptr;
1174
1.79k
        if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD
1175
1.79k
        ||  tc->cmdsize!=sizeof(threado)
1176
594
        ||  tc->flavor!=my_thread_flavor
1177
1.64k
        ||  tc->count!=my_thread_state_word_count) {
1178
1.64k
            return ~0ull;
1179
1.64k
        }
1180
149
        return tc->state.pc;
1181
1.79k
    }
1182
};
1183
1184
class PackMachARM64EL : public PackMachBase<MachClass_LE64>
1185
{
1186
    typedef PackMachBase<MachClass_LE64> super;
1187
1188
public:
1189
    PackMachARM64EL(InputFile *f);
1190
1191
23.9k
    virtual int getFormat() const override { return UPX_F_MACH_ARM64; }
1192
29
    virtual const char *getName() const override { return "macho/arm64"; }
1193
0
    virtual const char *getFullName(const options_t *) const override { return "arm64-darwin.macho"; }
1194
protected:
1195
    virtual const int *getFilters() const override;
1196
1197
    virtual void pack1_setup_threado(OutputFile *const fo) override;
1198
    virtual Linker* newLinker() const override;
1199
    virtual void addStubEntrySections(Filter const *) override;
1200
1201
    packed_struct(Mach_thread_command) {
1202
        LE32 cmd;            /* LC_THREAD or  LC_UNIXTHREAD */
1203
        LE32 cmdsize;        /* total size of this command */
1204
        LE32 flavor;
1205
        LE32 count;          /* sizeof(following_thread_state)/4 */
1206
        Mach_ARM64_thread_state state;
1207
    #define WANT_MACH_THREAD_ENUM 1
1208
    #include "p_mach_enum.h"
1209
    };
1210
1211
    Mach_thread_command threado;
1212
0
    int threado_size() const override { return sizeof(threado); }
1213
0
    void threado_setPC(upx_uint64_t pc) override {
1214
0
        memset(&threado, 0, sizeof(threado));
1215
0
        threado.cmd = Mach_segment_command::LC_UNIXTHREAD;
1216
0
        threado.cmdsize = sizeof(threado);
1217
0
        threado.flavor = my_thread_flavor;
1218
0
        threado.count =  my_thread_state_word_count;
1219
0
        threado.state.pc = pc;
1220
0
    }
1221
0
    void threado_rewrite(OutputFile *fo) override { fo->rewrite(&threado, sizeof(threado)); }
1222
0
    void   threado_write(OutputFile *fo) override {   fo->write(&threado, sizeof(threado)); }
1223
1224
422
    upx_uint64_t threadc_getPC(void const *ptr) override {
1225
422
        Mach_thread_command const *tc = (Mach_thread_command const *)ptr;
1226
422
        if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD
1227
422
        ||  tc->cmdsize!=sizeof(threado)
1228
189
        ||  tc->flavor!=my_thread_flavor
1229
397
        ||  tc->count!=my_thread_state_word_count) {
1230
397
            return ~0ull;
1231
397
        }
1232
25
        return tc->state.pc;
1233
422
    }
1234
};
1235
1236
class PackMachFat : public Packer
1237
{
1238
    typedef Packer super;
1239
public:
1240
    PackMachFat(InputFile *f);
1241
    virtual ~PackMachFat();
1242
1243
20.0k
    virtual int getVersion() const override { return 13; }
1244
40.0k
    virtual int getFormat() const override { return UPX_F_MACH_FAT; }
1245
0
    virtual const char *getName() const override { return "macho/fat"; }
1246
0
    virtual const char *getFullName(const options_t *) const override { return "fat-darwin.macho"; }
1247
    virtual const int *getCompressionMethods(int method, int level) const override;
1248
    virtual const int *getFilters() const override;
1249
1250
protected:
1251
    // implementation
1252
    virtual unsigned check_fat_head();  // number of architectures
1253
    virtual void pack(OutputFile *fo) override;
1254
    virtual void unpack(OutputFile *fo) override;
1255
    virtual void list() override;
1256
1257
public:
1258
    virtual tribool canPack() override;
1259
    virtual tribool canUnpack() override;
1260
1261
protected:
1262
    // loader core
1263
    virtual void buildLoader(const Filter *ft) override;
1264
    virtual Linker* newLinker() const override;
1265
1266
    enum { N_FAT_ARCH = 5 };
1267
protected:
1268
    packed_struct(Fat_head) {
1269
        struct Mach_fat_header fat;
1270
        struct Mach_fat_arch arch[N_FAT_ARCH];
1271
    };
1272
1273
    Fat_head fat_head;
1274
1275
    // UI handler
1276
    UiPacker *uip;
1277
1278
    // linker
1279
    Linker *linker;
1280
#define WANT_MACH_HEADER_ENUM 1
1281
#include "p_mach_enum.h"
1282
};
1283
1284
// Alignment and sizeof are independent of endianness,
1285
// so all the above template classes just complicate.
1286
// Besides, we use them only to check for valid Macho headers.
1287
// (Fie on fuzzers!)
1288
1289
struct dyld_info_command {
1290
    upx_uint32_t cmd;
1291
    upx_uint32_t cmdsize;
1292
    upx_uint32_t rebase_off;
1293
    upx_uint32_t rebase_size;
1294
    upx_uint32_t bind_off;
1295
    upx_uint32_t bind_size;
1296
    upx_uint32_t weak_bind_off;
1297
    upx_uint32_t weak_bind_size;
1298
    upx_uint32_t lazy_bind_off;
1299
    upx_uint32_t lazy_bind_size;
1300
    upx_uint32_t export_off;
1301
    upx_uint32_t export_size;
1302
};
1303
union lc_str {
1304
    upx_uint32_t offset;
1305
};
1306
1307
struct dylib {
1308
    union lc_str name;
1309
    upx_uint32_t timestamp;
1310
    upx_uint32_t current_version;
1311
    upx_uint32_t compatibility_version;
1312
};
1313
struct dylib_command {
1314
    upx_uint32_t cmd;
1315
    upx_uint32_t cmdsize;
1316
    struct dylib dylib;
1317
};
1318
struct dylinker_command {
1319
    upx_uint32_t cmd;
1320
    upx_uint32_t cmdsize;
1321
    union lc_str name;
1322
};
1323
struct encryption_info_command {
1324
    upx_uint32_t cmd;
1325
    upx_uint32_t cmdsize;
1326
    upx_uint32_t cryptoff;
1327
    upx_uint32_t cryptsize;
1328
    upx_uint32_t cryptid;
1329
};
1330
struct encryption_info_command_64 {
1331
    upx_uint32_t cmd;
1332
    upx_uint32_t cmdsize;
1333
    upx_uint32_t cryptoff;
1334
    upx_uint32_t cryptsize;
1335
    upx_uint32_t cryptid;
1336
    upx_uint32_t pad;
1337
};
1338
struct entry_point_command {
1339
    upx_uint32_t cmd;
1340
    upx_uint32_t cmdsize;
1341
    upx_uint64_t entryoff;
1342
    upx_uint64_t stacksize;
1343
};
1344
struct linkedit_data_command {
1345
    upx_uint32_t cmd;
1346
    upx_uint32_t cmdsize;
1347
    upx_uint32_t dataoff;
1348
    upx_uint32_t datasize;
1349
};
1350
struct rpath_command {
1351
    upx_uint32_t cmd;
1352
    upx_uint32_t cmdsize;
1353
    union lc_str path;
1354
};
1355
struct routines_command {
1356
    upx_uint32_t cmd;
1357
    upx_uint32_t cmdsize;
1358
    upx_uint32_t init_address;
1359
    upx_uint32_t init_module;
1360
    upx_uint32_t reserved1;
1361
    upx_uint32_t reserved2;
1362
    upx_uint32_t reserved3;
1363
    upx_uint32_t reserved4;
1364
    upx_uint32_t reserved5;
1365
    upx_uint32_t reserved6;
1366
};
1367
struct routines_command_64 {
1368
    upx_uint32_t cmd;
1369
    upx_uint32_t cmdsize;
1370
    upx_uint64_t init_address;
1371
    upx_uint64_t init_module;
1372
    upx_uint64_t reserved1;
1373
    upx_uint64_t reserved2;
1374
    upx_uint64_t reserved3;
1375
    upx_uint64_t reserved4;
1376
    upx_uint64_t reserved5;
1377
    upx_uint64_t reserved6;
1378
};
1379
struct uuid_command {
1380
    upx_uint32_t cmd;
1381
    upx_uint32_t cmdsize;
1382
    upx_uint8_t uuid[16];
1383
};
1384
struct version_min_command {
1385
    upx_uint32_t cmd;
1386
    upx_uint32_t cmdsize;
1387
    upx_uint32_t version;
1388
    upx_uint32_t sdk;
1389
};
1390
1391
/* vim:set ts=4 sw=4 et: */