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