1 /* amd64-darwin.macho-main.c -- loader stub for Mach-o AMD64
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 Copyright (C) 2000-2020 John F. Reiser
8 All Rights Reserved.
9
10 UPX and the UCL library are free software; you can redistribute them
11 and/or modify them under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of
13 the License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; see the file COPYING.
22 If not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25 Markus F.X.J. Oberhumer Laszlo Molnar
26 <markus@oberhumer.com> <ezerotven+github@gmail.com>
27
28 John F. Reiser
29 <jreiser@users.sourceforge.net>
30 */
31
32
33 #define __WORDSIZE 64
34 #include "include/darwin.h"
35
36 #define SIMULATE_ON_LINUX_EABI4 0
37
38 #if defined(__arm__) //{
39 #define DEBUG 0 /* __arm__ */
40 #endif //}
41
42 #if defined(__aarch64__) //{
43 #define DEBUG 0 /* __aarch64__ */
44 #endif //}
45
46 #ifndef DEBUG /*{*/
47 #define DEBUG 0
48 #endif /*}*/
49
50 /*************************************************************************
51 // configuration section
52 **************************************************************************/
53
54 // In order to make it much easier to move this code at runtime and execute
55 // it at an address different from it load address: there must be no
56 // static data, and no string constants.
57
58 #if !DEBUG //{
59 #define DPRINTF(fmt, args...) /*empty*/
60 #else //}{
61 // DPRINTF is defined as an expression using "({ ... })"
62 // so that DPRINTF can be invoked inside an expression,
63 // and then followed by a comma to ignore the return value.
64 // The only complication is that percent and backslash
65 // must be doubled in the format string, because the format
66 // string is processd twice: once at compile-time by 'asm'
67 // to produce the assembled value, and once at runtime to use it.
68 #if defined(__powerpc__) //{
69 #define DPRINTF(fmt, args...) ({ \
70 char const *r_fmt; \
71 asm("bl 0f; .string \"" fmt "\"; .balign 4; 0: mflr %0" \
72 /*out*/ : "=r"(r_fmt) \
73 /* in*/ : \
74 /*und*/ : "lr"); \
75 dprintf(r_fmt, args); \
76 })
77 #elif defined(__x86_64) //}{
78 #define DPRINTF(fmt, args...) ({ \
79 char const *r_fmt; \
80 asm("call 0f; .asciz \"" fmt "\"; 0: pop %0" \
81 /*out*/ : "=r"(r_fmt) ); \
82 dprintf(r_fmt, args); \
83 })
84 #elif defined(__aarch64__) //}{
85 #define DPRINTF(fmt, args...) ({ \
86 char const *r_fmt; \
87 asm("bl 0f; .string \"" fmt "\"; .balign 4; 0: mov %0,x30" \
88 /*out*/ : "=r"(r_fmt) \
89 /* in*/ : \
90 /*und*/ : "x30"); \
91 dprintf(r_fmt, args); \
92 })
93 #elif defined(__arm__) //}{
94 #define DPRINTF(fmt, args...) ({ \
95 char const *r_fmt; \
96 asm("bl 0f; .string \"" fmt "\"; .balign 4; 0: mov %0,lr" \
97 /*out*/ : "=r"(r_fmt) \
98 /* in*/ : \
99 /*und*/ : "lr"); \
100 dprintf(r_fmt, args); \
101 })
102 #endif //}
103
104 static int dprintf(char const *fmt, ...); // forward
105 #endif /*}*/
106
107
108 /*************************************************************************
109 // "file" util
110 **************************************************************************/
111
112 typedef struct {
113 size_t size; // must be first to match size[0] uncompressed size
114 void *buf;
115 } Extent;
116
117 static void
xread(Extent * x,void * buf,size_t count)118 xread(Extent *x, void *buf, size_t count)
119 {
120 unsigned char *p=x->buf, *q=buf;
121 size_t j;
122 DPRINTF("xread %%p(%%x %%p) %%p %%x\\n", x, x->size, x->buf, buf, count);
123 if (x->size < count) {
124 DPRINTF("xreadfail %%p(%%x %%p) %%p %%x\\n",
125 x, x->size, x->buf, buf, count);
126 exit(127);
127 }
128 for (j = count; 0!=j--; ++p, ++q) {
129 *q = *p;
130 }
131 DPRINTF(" buf: %%x %%x %%x\\n", ((int *)buf)[0], ((int *)buf)[1], ((int *)buf)[2]);
132 x->buf += count;
133 x->size -= count;
134 }
135
136
137 /*************************************************************************
138 // util
139 **************************************************************************/
140
141 #if 0 //{ save space
142 #define ERR_LAB error: exit(127);
143 #define err_exit(a) goto error
144 #else //}{ save debugging time
145 #define ERR_LAB /*empty*/
146
147 static void
err_exit(int a)148 err_exit(int a)
149 {
150 DPRINTF("err_exit %%x\\n", a);
151 (void)a; // debugging convenience
152 exit(a);
153 }
154 #endif //}
155
156
157 /*************************************************************************
158 // UPX & NRV stuff
159 **************************************************************************/
160
161 struct l_info { // 12-byte trailer for loader (after macho headers)
162 unsigned l_checksum;
163 unsigned l_magic; // UPX_MAGIC_LE32
164 unsigned short l_lsize;
165 unsigned char l_version;
166 unsigned char l_format;
167 };
168 struct p_info { // 12-byte packed program header
169 unsigned p_progid;
170 unsigned p_filesize;
171 unsigned p_blocksize;
172 };
173
174 struct b_info { // 12-byte header before each compressed block
175 unsigned sz_unc; // uncompressed_size
176 unsigned sz_cpr; // compressed_size
177 unsigned char b_method; // compression algorithm
178 unsigned char b_ftid; // filter id
179 unsigned char b_cto8; // filter parameter
180 unsigned char b_unused;
181 };
182
183 typedef void f_unfilter(
184 nrv_byte *, // also addvalue
185 nrv_uint,
186 unsigned cto8, // junk in high 24 bits
187 unsigned ftid
188 );
189 typedef int f_expand(
190 const nrv_byte *, nrv_uint,
191 nrv_byte *, size_t *, unsigned );
192
193 static void
unpackExtent(Extent * const xi,Extent * const xo,f_expand * const f_exp,f_unfilter * f_unf)194 unpackExtent(
195 Extent *const xi, // input
196 Extent *const xo, // output
197 f_expand *const f_exp,
198 f_unfilter *f_unf
199 )
200 {
201 DPRINTF("unpackExtent in=%%p(%%x %%p) out=%%p(%%x %%p) %%p %%p\\n",
202 xi, xi->size, xi->buf, xo, xo->size, xo->buf, f_exp, f_unf);
203 while (xo->size) {
204 struct b_info h;
205 // Note: if h.sz_unc == h.sz_cpr then the block was not
206 // compressible and is stored in its uncompressed form.
207
208 // Read and check block sizes.
209 xread(xi, (unsigned char *)&h, sizeof(h));
210 if (h.sz_unc == 0) { // uncompressed size 0 -> EOF
211 if (h.sz_cpr != UPX_MAGIC_LE32) // h.sz_cpr must be h->magic
212 err_exit(2);
213 if (xi->size != 0) // all bytes must be written
214 err_exit(3);
215 break;
216 }
217 if (h.sz_cpr <= 0) {
218 err_exit(4);
219 ERR_LAB
220 }
221 if (h.sz_cpr > h.sz_unc
222 || h.sz_unc > xo->size ) {
223 DPRINTF("sz_cpr=%%x sz_unc=%%x xo->size=%%x\\n",
224 h.sz_cpr, h.sz_unc, xo->size);
225 err_exit(5);
226 }
227 // Now we have:
228 // assert(h.sz_cpr <= h.sz_unc);
229 // assert(h.sz_unc > 0 && h.sz_unc <= blocksize);
230 // assert(h.sz_cpr > 0 && h.sz_cpr <= blocksize);
231
232 if (h.sz_cpr < h.sz_unc) { // Decompress block
233 size_t out_len = h.sz_unc; // EOF for lzma
234 int const j = (*f_exp)(xi->buf, h.sz_cpr,
235 xo->buf, &out_len, h.b_method);
236 if (j != 0 || out_len != (nrv_uint)h.sz_unc)
237 err_exit(7);
238 if (h.b_ftid!=0 && f_unf) { // have filter
239 (*f_unf)(xo->buf, out_len, h.b_cto8, h.b_ftid);
240 }
241 xi->buf += h.sz_cpr;
242 xi->size -= h.sz_cpr;
243 }
244 else { // copy literal block
245 xread(xi, xo->buf, h.sz_cpr);
246 }
247 xo->buf += h.sz_unc;
248 xo->size -= h.sz_unc;
249 }
250 }
251
252 static void
upx_bzero(unsigned char * p,size_t len)253 upx_bzero(unsigned char *p, size_t len)
254 {
255 if (len) do {
256 *p++= 0;
257 } while (--len);
258 }
259 #define bzero upx_bzero
260
261
262 // The PF_* and PROT_* bits are {1,2,4}; the conversion table fits in 32 bits.
263 #define REP8(x) \
264 ((x)|((x)<<4)|((x)<<8)|((x)<<12)|((x)<<16)|((x)<<20)|((x)<<24)|((x)<<28))
265 #define EXP8(y) \
266 ((1&(y)) ? 0xf0f0f0f0 : (2&(y)) ? 0xff00ff00 : (4&(y)) ? 0xffff0000 : 0)
267 #define PF_TO_PROT(pf) \
268 ((PROT_READ|PROT_WRITE|PROT_EXEC) & ( \
269 ( (REP8(PROT_EXEC ) & EXP8(PF_X)) \
270 |(REP8(PROT_READ ) & EXP8(PF_R)) \
271 |(REP8(PROT_WRITE) & EXP8(PF_W)) \
272 ) >> ((pf & (PF_R|PF_W|PF_X))<<2) ))
273
274 typedef struct {
275 unsigned magic;
276 unsigned nfat_arch;
277 } Fat_header;
278 typedef struct {
279 unsigned cputype;
280 unsigned cpusubtype;
281 unsigned offset;
282 unsigned size;
283 unsigned align; /* shift count (log base 2) */
284 } Fat_arch;
285 enum e8 {
286 FAT_MAGIC = 0xcafebabe,
287 FAT_CIGAM = 0xbebafeca
288 };
289 enum e9 {
290 CPU_TYPE_I386 = 7,
291 CPU_TYPE_AMD64 = 0x01000007,
292 CPU_TYPE_ARM = 12,
293 CPU_TYPE_POWERPC = 0x00000012,
294 CPU_TYPE_POWERPC64 = 0x01000012
295 };
296
297 typedef struct {
298 unsigned magic;
299 unsigned cputype;
300 unsigned cpysubtype;
301 unsigned filetype;
302 unsigned ncmds;
303 unsigned sizeofcmds;
304 unsigned flags;
305 #if defined(__x86_64__) || defined(__aarch64__) //{
306 unsigned reserved; // for 64-bit alignment
307 #endif //}
308 } Mach_header; // also Mach_header64 which has 4 more bytes
309 enum e0 {
310 MH_MAGIC = 0xfeedface,
311 MH_MAGIC64 = 1+0xfeedface
312 };
313 enum e2 {
314 MH_EXECUTE = 2,
315 MH_DYLINKER= 7 /* /usr/bin/dyld */
316 };
317 enum e3 {
318 MH_NOUNDEFS = 1
319 , MH_PIE = 0x200000 // ASLR
320 };
321
322 typedef struct {
323 unsigned cmd;
324 unsigned cmdsize;
325 } Mach_load_command;
326 enum e4 {
327 // LC_SEGMENT = 0x1,
328 // LC_SEGMENT_64 = 0x19,
329 LC_THREAD = 0x4,
330 LC_UNIXTHREAD = 0x5,
331 LC_LOAD_DYLINKER = 0xe
332 };
333
334 typedef struct {
335 unsigned cmd;
336 unsigned cmdsize;
337 char segname[16];
338 uint64_t vmaddr;
339 uint64_t vmsize;
340 uint64_t fileoff;
341 uint64_t filesize;
342 unsigned maxprot;
343 unsigned initprot;
344 unsigned nsects;
345 unsigned flags;
346 } Mach_segment_command;
347 enum e5 {
348 VM_PROT_READ = 1,
349 VM_PROT_WRITE = 2,
350 VM_PROT_EXECUTE = 4
351 };
352
353 typedef struct {
354 char sectname[16];
355 char segname[16];
356 uint64_t addr; /* memory address */
357 uint64_t size; /* size in bytes */
358 unsigned offset; /* file offset */
359 unsigned align; /* power of 2 */
360 unsigned reloff; /* file offset of relocation entries */
361 unsigned nreloc; /* number of relocation entries */
362 unsigned flags; /* section type and attributes */
363 unsigned reserved1; /* for offset or index */
364 unsigned reserved2; /* for count or sizeof */
365 } Mach_section_command;
366
367 typedef struct {
368 uint32_t cmd; // LC_MAIN; MH_EXECUTE only
369 uint32_t cmdsize; // 24
370 uint64_t entryoff; // file offset of main() [expected in __TEXT]
371 uint64_t stacksize; // non-default initial stack size
372 } Mach_main_command;
373
374 #if defined(__aarch64__) // {
375 typedef struct {
376 uint64_t x0, x1, x2, x3;
377 uint64_t x4, x5, x6, x7;
378 uint64_t x8, x9, x10, x11;
379 uint64_t x12, x13, x14, x15;
380 uint64_t x16, x17, x18, x19;
381 uint64_t x20, x21, x22, x23;
382 uint64_t x24, x25, x26, x27;
383 uint64_t x28, fp, lr, sp;
384 uint64_t pc;
385 uint32_t cpsr;
386 } Mach_thread_state; // Mach_ARM64_thread_state
387 enum e6 {
388 THREAD_STATE = 4 // ARM64_THREAD_STATE
389 };
390 enum e7 {
391 THREAD_STATE_COUNT = sizeof(Mach_thread_state)/4
392 };
393 enum e10 {
394 LC_SEGMENT = 0x19 // LC_SEGMENT_64
395 };
396
397 #elif defined(__arm__) //}{
398 typedef struct {
399 uint32_t r[13]; // r0-r12
400 uint32_t sp; // r13
401 uint32_t lr; // r14
402 uint32_t pc; // r15
403 uint32_t cpsr;
404 } Mach_thread_state; // Mach_ARM_thead_state;
405 enum e6 {
406 THREAD_STATE = 1 // ARM_THREAD_STATE
407 };
408 enum e7 {
409 THREAD_STATE_COUNT = sizeof(Mach_thread_state)/4
410 };
411 enum e10 {
412 LC_SEGMENT = 0x1
413 };
414
415 #elif defined(__x86_64__) //}{
416 typedef struct {
417 uint64_t rax, rbx, rcx, rdx;
418 uint64_t rdi, rsi, rbp, rsp;
419 uint64_t r8, r9, r10, r11;
420 uint64_t r12, r13, r14, r15;
421 uint64_t rip, rflags;
422 uint64_t cs, fs, gs;
423 } Mach_thread_state; // Mach_AMD64_thread_state;
424 enum e6 {
425 THREAD_STATE = 4 // AMD_THREAD_STATE
426 };
427 enum e7 {
428 THREAD_STATE_COUNT = sizeof(Mach_thread_state)/4
429 };
430 enum e10 {
431 LC_SEGMENT = 0x19 // LC_SEGMENT_64
432 };
433
434 #endif //}
435
436 typedef struct {
437 unsigned cmd; /* LC_THREAD or LC_UNIXTHREAD */
438 unsigned cmdsize; /* total size of this command */
439 unsigned flavor;
440 unsigned count; /* sizeof(following_thread_state)/4 */
441 Mach_thread_state state;
442 } Mach_thread_command;
443
444 typedef union {
445 unsigned offset; /* from start of load command to string */
446 } Mach_lc_str;
447
448 #define MAP_FIXED 0x10
449 #define MAP_PRIVATE 0x02
450
451 #if SIMULATE_ON_LINUX_EABI4 //{
452 #define MAP_ANON 0x20 /* SIMULATE_ON_LINUX_EABI4 */
453 #else //}{
454 #define MAP_ANON 0x1000 /* native darwin usual case */
455 #endif //}
456 #define MAP_ANON_FD -1
457
458 #define PROT_NONE 0
459 #define PROT_READ 1
460 #define PROT_WRITE 2
461 #define PROT_EXEC 4
462
463 extern void *mmap(void *, size_t, unsigned, unsigned, int, off_t_upx_stub);
464 ssize_t pread(int, void *, size_t, off_t_upx_stub);
465 extern void bswap(void *, unsigned);
466
467 typedef size_t Addr; // this source file is used by 32-bit and 64-bit machines
468
469 // Find convex hull of PT_LOAD (the minimal interval which covers all PT_LOAD),
470 // and mmap that much, to be sure that a kernel using exec-shield-randomize
471 // won't place the first piece in a way that leaves no room for the rest.
472 static Addr // returns relocation constant
xfind_pages(Mach_header const * const mhdr,Mach_segment_command const * sc,int const ncmds,Addr addr)473 xfind_pages(
474 Mach_header const *const mhdr,
475 Mach_segment_command const *sc,
476 int const ncmds,
477 Addr addr
478 )
479 {
480 Addr lo= ~(Addr)0, hi= 0;
481 int j;
482 unsigned mflags = ((mhdr->filetype == MH_DYLINKER || mhdr->flags & MH_PIE) ? 0 : MAP_FIXED);
483 mflags += MAP_PRIVATE | MAP_ANON; // '+' can optimize better than '|'
484 DPRINTF("xfind_pages mhdr=%%p sc=%%p ncmds=%%d addr=%%p mflags=%%x\\n",
485 mhdr, sc, ncmds, addr, mflags);
486 for (j=0; j < ncmds; ++j,
487 (sc = (Mach_segment_command const *)((sc->cmdsize>>2) + (unsigned const *)sc))
488 ) if (LC_SEGMENT==sc->cmd) {
489 DPRINTF(" #%%d cmd=%%x cmdsize=%%x vmaddr=%%p vmsize==%%p lo=%%p mflags=%%x\\n",
490 j, sc->cmd, sc->cmdsize, sc->vmaddr, sc->vmsize, lo, mflags);
491 if (sc->vmsize // theoretically occupies address space
492 && !(sc->vmaddr==0 && (MAP_FIXED & mflags)) // but ignore PAGEZERO when MAP_FIXED
493 ) {
494 if (mhdr->filetype == MH_DYLINKER // /usr/lib/dyld
495 && 0==(1+ lo) // 1st LC_SEGMENT
496 && sc->vmaddr != 0 // non-floating address
497 ) {
498 // "pre-linked" dyld on MacOS 10.11.x El Capitan
499 mflags |= MAP_FIXED;
500 }
501 if (lo > sc->vmaddr) {
502 lo = sc->vmaddr;
503 }
504 if (hi < (sc->vmsize + sc->vmaddr)) {
505 hi = sc->vmsize + sc->vmaddr;
506 }
507 }
508 }
509 lo -= ~PAGE_MASK & lo; // round down to page boundary
510 hi = PAGE_MASK & (hi - lo - PAGE_MASK -1); // page length
511 DPRINTF(" addr=%%p lo=%%p len=%%p mflags=%%x\\n", addr, lo, hi, mflags);
512 if (MAP_FIXED & mflags) {
513 addr = lo;
514 int rv = munmap((void *)addr, hi);
515 if (rv) {
516 DPRINTF("munmap addr=%%p len=%%p, rv=%%x\\n", addr, hi, rv);
517 }
518 }
519 addr = (Addr)mmap((void *)addr, hi, PROT_NONE, mflags, MAP_ANON_FD, 0);
520 DPRINTF(" addr=%%p\\n", addr);
521 if (~PAGE_MASK & addr) {
522 err_exit(6);
523 }
524 return (Addr)(addr - lo);
525 }
526
527 unsigned * // &hatch if main; &Mach_thread_state if dyld
do_xmap(Mach_header * const mhdr,off_t_upx_stub const fat_offset,Extent * const xi,int const fdi,Mach_header ** mhdrpp,f_expand * const f_exp,f_unfilter * const f_unf)528 do_xmap(
529 Mach_header *const mhdr,
530 off_t_upx_stub const fat_offset,
531 Extent *const xi,
532 int const fdi,
533 Mach_header **mhdrpp,
534 f_expand *const f_exp,
535 f_unfilter *const f_unf
536 )
537 {
538 DPRINTF("do_xmap fdi=%%x mhdr=%%p *mhdrpp=%%p xi=%%p(%%x %%p) f_unf=%%p\\n",
539 fdi, mhdr, (mhdrpp ? *mhdrpp : 0), xi, (xi? xi->size: 0), (xi? xi->buf: 0), f_unf);
540
541 unsigned *rv = 0;
542 Mach_segment_command *sc = (Mach_segment_command *)(1+ mhdr);
543 Addr const reloc = xfind_pages(mhdr, sc, mhdr->ncmds, 0);
544 DPRINTF("do_xmap reloc=%%p\\n", reloc);
545 unsigned j;
546 for ( j=0; j < mhdr->ncmds; ++j,
547 (sc = (Mach_segment_command *)((sc->cmdsize>>2) + (unsigned *)sc))
548 ) {
549 DPRINTF(" #%%d cmd=%%x cmdsize=%%x vmsize=%%x\\n",
550 j, sc->cmd, sc->cmdsize, sc->vmsize);
551 if (LC_SEGMENT==sc->cmd && !sc->vmsize) {
552 // Typical __DWARF info segment for 'rust'
553 struct b_info h;
554 xread(xi, (unsigned char *)&h, sizeof(h));
555 DPRINTF(" 0==.vmsize; skipping %%x\\n", h.sz_cpr);
556 xi->buf += h.sz_cpr;
557 }
558 if (LC_SEGMENT==sc->cmd && sc->vmsize) {
559 Extent xo;
560 size_t mlen = xo.size = sc->filesize;
561 xo.buf = (void *)(reloc + sc->vmaddr);
562 Addr addr = (Addr)xo.buf;
563 Addr haddr = sc->vmsize + addr;
564 size_t frag = addr &~ PAGE_MASK;
565 addr -= frag;
566 mlen += frag;
567
568 DPRINTF(" mlen=%%p frag=%%p addr=%%p\\n", mlen, frag, addr);
569 if (0!=mlen) {
570 size_t const mlen3 = mlen
571 #if defined(__x86_64__) //{
572 // Decompressor can overrun the destination by 3 bytes. [x86 only]
573 + (xi ? 3 : 0)
574 #endif //}
575 ;
576 unsigned const prot = VM_PROT_READ | VM_PROT_WRITE;
577 // MAP_FIXED: xfind_pages() reserved them, so use them!
578 unsigned const flags = MAP_FIXED | MAP_PRIVATE |
579 ((xi || 0==sc->filesize) ? MAP_ANON : 0);
580 int const fdm = ((xi || 0==sc->filesize) ? MAP_ANON_FD : fdi);
581 off_t_upx_stub const offset = sc->fileoff + fat_offset;
582
583 DPRINTF("mmap addr=%%p len=%%p prot=%%x flags=%%x fd=%%d off=%%p reloc=%%p\\n",
584 addr, mlen3, prot, flags, fdm, offset, reloc);
585 {
586 Addr maddr = (Addr)mmap((void *)addr, mlen3, prot, flags, fdm, offset);
587 DPRINTF("maddr=%%p\\n", maddr);
588 if (maddr != addr) {
589 err_exit(8);
590 }
591 addr = maddr;
592 }
593 if (!*mhdrpp) { // MH_DYLINKER
594 *mhdrpp = (Mach_header*)addr;
595 }
596 }
597 if (xi && 0!=sc->filesize) {
598 if (0==sc->fileoff /*&& 0!=mhdrpp*/) {
599 *mhdrpp = (Mach_header *)(void *)addr;
600 }
601 unpackExtent(xi, &xo, f_exp, f_unf);
602 }
603 DPRINTF("xi=%%p mlen=%%p fileoff=%%p nsects=%%d\\n",
604 xi, mlen, sc->fileoff, sc->nsects);
605 if (xi && mlen && !sc->fileoff && sc->nsects) {
606 // main target __TEXT segment at beginning of file with sections (__text)
607 // Use upto 2 words of header padding for the escape hatch.
608 // fold.S could do this easier, except PROT_WRITE is missing then.
609 union {
610 unsigned char *p0;
611 unsigned short *p1;
612 unsigned int *p2;
613 unsigned long *p3;
614 } u;
615 u.p0 = (unsigned char *)addr;
616 Mach_segment_command *segp = (Mach_segment_command *)((((char *)sc - (char *)mhdr)>>2) + u.p2);
617 Mach_section_command *const secp = (Mach_section_command *)(1+ segp);
618 #if defined(__aarch64__) //{
619 unsigned *hatch= -2+ (secp->offset>>2) + u.p2;
620 hatch[0] = 0xd4000001; // svc #0 // syscall
621 hatch[1] = 0xd65f03c0; // ret
622 #elif defined(__arm__) //}{
623 unsigned *hatch= -2+ (secp->offset>>2) + u.p2;
624 hatch[0] = 0xef000000; // svc 0x0 // syscall
625 hatch[1] = 0xe12fff1e; // bx lr
626 #elif defined(__x86_64__) //}{
627 unsigned *hatch= -1+ (secp->offset>>2) + u.p2;
628 hatch[0] = 0xc3050f90; // nop; syscall; ret
629 #endif //}
630 DPRINTF("hatch=%%p secp=%%p segp=%%p mhdr=%%p\\n", hatch, secp, segp, addr);
631 rv = hatch;
632 }
633 /*bzero(addr, frag);*/ // fragment at lo end
634 frag = (-mlen) &~ PAGE_MASK; // distance to next page boundary
635 bzero((void *)(mlen+addr), frag); // fragment at hi end
636 if (0!=mlen && 0!=mprotect((void *)addr, mlen, sc->initprot)) {
637 err_exit(10);
638 ERR_LAB
639 }
640 addr += mlen + frag; /* page boundary on hi end */
641 if (
642 #if SIMULATE_ON_LINUX_EABI4 /*{*/
643 0!=addr &&
644 #endif /*}*/
645 addr < haddr) { // need pages for .bss
646 if (0!=addr && addr != (Addr)mmap((void *)addr, haddr - addr, sc->initprot,
647 MAP_FIXED | MAP_PRIVATE | MAP_ANON, MAP_ANON_FD, 0 ) ) {
648 err_exit(9);
649 }
650 }
651 else if (xi) { // cleanup if decompressor overrun crosses page boundary
652 mlen = ~PAGE_MASK & (3+ mlen);
653 if (mlen<=3) { // page fragment was overrun buffer only
654 DPRINTF("munmap %%x %%x\\n", addr, mlen);
655 munmap((char *)addr, mlen);
656 }
657 }
658 }
659 else if (!xi // dyld
660 && (LC_UNIXTHREAD==sc->cmd || LC_THREAD==sc->cmd)) {
661 Mach_thread_command *const thrc = (Mach_thread_command *)sc;
662 DPRINTF("thread_command= %%p\\n", sc);
663 if (1
664 // FIXME THREAD_STATE ==thrc->flavor
665 // && THREAD_STATE_COUNT==thrc->count
666 ) {
667 DPRINTF("thread_state= %%p flavor=%%d count=%%x reloc=%%p\\n",
668 &thrc->state, thrc->flavor, thrc->count, reloc);
669 #if defined(__aarch64__) //{
670 thrc->state.pc += reloc;
671 #elif defined(__arm__) //}{
672 thrc->state.pc += reloc;
673 #elif defined(__x86_64__) //}{
674 thrc->state.rip += reloc;
675 #endif //}
676 rv = (unsigned *)&thrc->state;
677 }
678 }
679 }
680 DPRINTF("do_xmap= %%p\\n", rv);
681 return rv;
682 }
683
684
685 /*************************************************************************
686 // upx_main - called by our unfolded entry code
687 //
688 **************************************************************************/
689 Mach_thread_state const *
upx_main(struct l_info const * const li,size_t volatile sz_compressed,Mach_header * const mhdr,size_t const sz_mhdr,f_expand * const f_exp,f_unfilter * const f_unf,Mach_header ** const mhdrpp)690 upx_main(
691 struct l_info const *const li,
692 size_t volatile sz_compressed, // total length
693 Mach_header *const mhdr, // temp char[sz_mhdr] for decompressing
694 size_t const sz_mhdr,
695 f_expand *const f_exp,
696 f_unfilter *const f_unf,
697 Mach_header **const mhdrpp // Out: *mhdrpp= &real Mach_header
698 )
699 {
700 Mach_thread_state *ts = 0;
701 unsigned *hatch;
702 off_t_upx_stub fat_offset = 0;
703 Extent xi, xo, xi0;
704 xi.buf = CONST_CAST(unsigned char *, 1+ (struct p_info const *)(1+ li)); // &b_info
705 xi.size = sz_compressed - (sizeof(struct l_info) + sizeof(struct p_info));
706 xo.buf = (unsigned char *)mhdr;
707 xo.size = ((struct b_info const *)(void const *)xi.buf)->sz_unc;
708 xi0 = xi;
709
710 DPRINTF("upx_main szc=%%x f_exp=%%p f_unf=%%p "
711 " xo=%%p(%%x %%p) xi=%%p(%%x %%p) mhdrpp=%%p mhdrp=%%p\\n",
712 sz_compressed, f_exp, f_unf, &xo, xo.size, xo.buf,
713 &xi, xi.size, xi.buf, mhdrpp, *mhdrpp);
714
715 // Uncompress Macho headers
716 unpackExtent(&xi, &xo, f_exp, 0); // never filtered?
717
718 // Overwrite the OS-chosen address space at *mhdrpp.
719 hatch = do_xmap(mhdr, fat_offset, &xi0, MAP_ANON_FD, mhdrpp, f_exp, f_unf);
720
721 { // Map dyld dynamic loader
722 Mach_load_command const *lc = (Mach_load_command const *)(1+ mhdr);
723 unsigned j;
724
725 for (j=0; j < mhdr->ncmds; ++j,
726 (lc = (Mach_load_command const *)(lc->cmdsize + (void const *)lc))
727 ) if (LC_LOAD_DYLINKER==lc->cmd) {
728 char const *const dyld_name = ((Mach_lc_str const *)(1+ lc))->offset +
729 (char const *)lc;
730 DPRINTF("dyld= %%s\\n", dyld_name);
731 int const fdi = open(dyld_name, O_RDONLY, 0);
732 if (0 > fdi) {
733 err_exit(18);
734 }
735 fat:
736 if ((ssize_t)sz_mhdr!=pread(fdi, (void *)mhdr, sz_mhdr, fat_offset)) {
737 ERR_LAB
738 err_exit(19);
739 }
740 switch (mhdr->magic) {
741 case MH_MAGIC: break;
742 case MH_MAGIC64: break;
743 case FAT_CIGAM:
744 case FAT_MAGIC: {
745 // stupid Apple: waste code and a page fault on EVERY execve
746 Fat_header *const fh = (Fat_header *)mhdr;
747 Fat_arch *fa = (Fat_arch *)(1+ fh);
748 bswap(fh, sizeof(*fh) + (fh->nfat_arch>>24)*sizeof(*fa));
749 for (j= 0; j < fh->nfat_arch; ++j, ++fa) {
750 if (CPU_TYPE_AMD64==fa->cputype) {
751 fat_offset= fa->offset;
752 goto fat;
753 }
754 }
755 } break;
756 } // switch
757 Mach_header *dyhdr = 0;
758 ts = (Mach_thread_state *)do_xmap(mhdr, fat_offset, 0, fdi, &dyhdr, 0, 0);
759 DPRINTF("ts= %%p hatch=%%p\\n", ts, hatch);
760 #if defined(__aarch64__) // {
761 ts->x0 = (uint64_t)hatch;
762 #elif defined(__arm__) //}{
763 ts->r[0] = (uint32_t)hatch;
764 #elif defined(__x86_64__) //}{
765 ts->rax = (uint64_t)hatch;
766 #endif //}
767 close(fdi);
768 break;
769 }
770 }
771
772 return ts;
773 }
774
775 #if DEBUG //{
776
777 static int
unsimal(unsigned x,char * ptr,int n)778 unsimal(unsigned x, char *ptr, int n)
779 {
780 unsigned m = 10;
781 while (10 <= (x / m)) m *= 10;
782 while (10 <= x) {
783 unsigned d = x / m;
784 x -= m * d;
785 m /= 10;
786 ptr[n++] = '0' + d;
787 }
788 ptr[n++] = '0' + x;
789 return n;
790 }
791
792 static int
decimal(int x,char * ptr,int n)793 decimal(int x, char *ptr, int n)
794 {
795 if (x < 0) {
796 x = -x;
797 ptr[n++] = '-';
798 }
799 return unsimal(x, ptr, n);
800 }
801
802 static int
heximal(unsigned long x,char * ptr,int n)803 heximal(unsigned long x, char *ptr, int n)
804 {
805 unsigned j = -1+ 2*sizeof(unsigned long);
806 unsigned long m = 0xful << (4 * j);
807 for (; j; --j, m >>= 4) { // omit leading 0 digits
808 if (m & x) break;
809 }
810 for (; m; --j, m >>= 4) {
811 unsigned d = 0xf & (x >> (4 * j));
812 ptr[n++] = ((10<=d) ? ('a' - 10) : '0') + d;
813 }
814 return n;
815 }
816
817 #define va_arg __builtin_va_arg
818 #define va_end __builtin_va_end
819 #define va_list __builtin_va_list
820 #define va_start __builtin_va_start
821
822 static int
dprintf(char const * fmt,...)823 dprintf(char const *fmt, ...)
824 {
825 int n= 0;
826 char const *literal = 0; // NULL
827 char buf[24]; // ~0ull == 18446744073709551615 ==> 20 chars
828 va_list va; va_start(va, fmt);
829 for (;;) {
830 char c = *fmt++;
831 if (!c) { // end of fmt
832 if (literal) {
833 goto finish;
834 }
835 break; // goto done
836 }
837 if ('%'!=c) {
838 if (!literal) {
839 literal = fmt; // 1 beyond start of literal
840 }
841 continue;
842 }
843 // '%' == c
844 if (literal) {
845 finish:
846 n += write(2, -1+ literal, fmt - literal);
847 literal = 0; // NULL
848 if (!c) { // fmt already ended
849 break; // goto done
850 }
851 }
852 switch (c= *fmt++) { // deficiency: does not handle _long_
853 default: { // un-implemented conversion
854 n+= write(2, -1+ fmt, 1);
855 } break;
856 case 0: { // fmt ends with "%\0" ==> ignore
857 goto done;
858 } break;
859 case 'u': {
860 n+= write(2, buf, unsimal(va_arg(va, unsigned), buf, 0));
861 } break;
862 case 'd': {
863 n+= write(2, buf, decimal(va_arg(va, int), buf, 0));
864 } break;
865 case 'p': {
866 buf[0] = '0';
867 buf[1] = 'x';
868 n+= write(2, buf, heximal((unsigned long)va_arg(va, void *), buf, 2));
869 } break;
870 case 'x': {
871 buf[0] = '0';
872 buf[1] = 'x';
873 n+= write(2, buf, heximal(va_arg(va, unsigned int), buf, 2));
874 } break;
875 case 's': {
876 char *s0= (char *)va_arg(va, unsigned char *), *s= s0;
877 if (s) while (*s) ++s;
878 n+= write(2, s0, s - s0);
879 } break;
880 } // 'switch'
881 }
882 done:
883 va_end(va);
884 return n;
885 }
886
887 #endif //}
888
889 /* vim:set ts=4 sw=4 et: */
890