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