ntdll/tests: Add tests for NtCompareObjects.
[wine.git] / loader / preloader_mac.c
blob23eee44975f50fd21f233dfd86df024e2fb7a8fd
1 /*
2 * Preloader for macOS
4 * Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc.
5 * Copyright (C) 2004 Mike McCormack for CodeWeavers
6 * Copyright (C) 2004 Alexandre Julliard
7 * Copyright (C) 2017 Michael Müller
8 * Copyright (C) 2017 Sebastian Lackner
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library 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 GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #ifdef __APPLE__
27 #include "config.h"
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #ifdef HAVE_SYS_MMAN_H
37 # include <sys/mman.h>
38 #endif
39 #ifdef HAVE_SYS_SYSCALL_H
40 # include <sys/syscall.h>
41 #endif
42 #include <unistd.h>
43 #include <dlfcn.h>
44 #ifdef HAVE_MACH_O_LOADER_H
45 #include <mach/thread_status.h>
46 #include <mach-o/loader.h>
47 #include <mach-o/ldsyms.h>
48 #endif
50 #include "wine/asm.h"
51 #include "main.h"
53 /* Rosetta on Apple Silicon allocates memory starting at 0x100000000 (the 4GB line)
54 * before the preloader runs, which prevents any nonrelocatable EXEs with that
55 * base address from running.
57 * This empty linker section forces Rosetta's allocations (currently ~132 MB)
58 * to start at 0x114000000, and they should end below 0x120000000.
60 #if defined(__x86_64__)
61 __asm__(".zerofill WINE_4GB_RESERVE,WINE_4GB_RESERVE,___wine_4gb_reserve,0x14000000");
62 #endif
64 #ifndef LC_MAIN
65 #define LC_MAIN 0x80000028
66 struct entry_point_command
68 uint32_t cmd;
69 uint32_t cmdsize;
70 uint64_t entryoff;
71 uint64_t stacksize;
73 #endif
75 static struct wine_preload_info preload_info[] =
77 /* On macOS, we allocate the low 64k area in two steps because PAGEZERO
78 * might not always be available. */
79 #ifdef __i386__
80 { (void *)0x00000000, 0x00001000 }, /* first page */
81 { (void *)0x00001000, 0x0000f000 }, /* low 64k */
82 { (void *)0x00010000, 0x00100000 }, /* DOS area */
83 { (void *)0x00110000, 0x67ef0000 }, /* low memory area */
84 { (void *)0x7f000000, 0x03000000 }, /* top-down allocations + shared heap + virtual heap */
85 #else /* __i386__ */
86 { (void *)0x000000010000, 0x00100000 }, /* DOS area */
87 { (void *)0x000000110000, 0x67ef0000 }, /* low memory area */
88 { (void *)0x00007ff00000, 0x000f0000 }, /* shared user data */
89 { (void *)0x000100000000, 0x14000000 }, /* WINE_4GB_RESERVE section */
90 { (void *)0x7ffd00000000, 0x01ff0000 }, /* top-down allocations + virtual heap */
91 #endif /* __i386__ */
92 { 0, 0 }, /* PE exe range set with WINEPRELOADRESERVE */
93 { 0, 0 } /* end of list */
97 * These functions are only called when file is compiled with -fstack-protector.
98 * They are normally provided by libc's startup files, but since we
99 * build the preloader with "-nostartfiles -nodefaultlibs", we have to
100 * provide our own versions, otherwise the linker fails.
102 void *__stack_chk_guard = 0;
103 void __stack_chk_fail_local(void) { return; }
104 void __stack_chk_fail(void) { return; }
106 #ifdef __i386__
108 static const size_t page_size = 0x1000;
109 static const size_t page_mask = 0xfff;
110 #define target_mach_header mach_header
111 #define target_segment_command segment_command
112 #define TARGET_LC_SEGMENT LC_SEGMENT
113 #define target_thread_state_t i386_thread_state_t
114 #ifdef __DARWIN_UNIX03
115 #define target_thread_ip(x) (x)->__eip
116 #else
117 #define target_thread_ip(x) (x)->eip
118 #endif
120 #define SYSCALL_FUNC( name, nr ) \
121 __ASM_GLOBAL_FUNC( name, \
122 "\tmovl $" #nr ",%eax\n" \
123 "\tint $0x80\n" \
124 "\tjnb 1f\n" \
125 "\tmovl $-1,%eax\n" \
126 "1:\tret\n" )
128 #define SYSCALL_NOERR( name, nr ) \
129 __ASM_GLOBAL_FUNC( name, \
130 "\tmovl $" #nr ",%eax\n" \
131 "\tint $0x80\n" \
132 "\tret\n" )
134 __ASM_GLOBAL_FUNC( start,
135 __ASM_CFI("\t.cfi_undefined %eip\n")
136 /* The first 16 bytes are used as a function signature on i386 */
137 "\t.byte 0x6a,0x00\n" /* pushl $0 */
138 "\t.byte 0x89,0xe5\n" /* movl %esp,%ebp */
139 "\t.byte 0x83,0xe4,0xf0\n" /* andl $-16,%esp */
140 "\t.byte 0x83,0xec,0x10\n" /* subl $16,%esp */
141 "\t.byte 0x8b,0x5d,0x04\n" /* movl 4(%ebp),%ebx */
142 "\t.byte 0x89,0x5c,0x24,0x00\n" /* movl %ebx,0(%esp) */
144 "\tleal 4(%ebp),%eax\n"
145 "\tmovl %eax,0(%esp)\n" /* stack */
146 "\tleal 8(%esp),%eax\n"
147 "\tmovl %eax,4(%esp)\n" /* &is_unix_thread */
148 "\tmovl $0,(%eax)\n"
149 "\tcall _wld_start\n"
151 "\tmovl 4(%ebp),%edi\n"
152 "\tdecl %edi\n" /* argc */
153 "\tleal 12(%ebp),%esi\n" /* argv */
154 "\tleal 4(%esi,%edi,4),%edx\n" /* env */
155 "\tmovl %edx,%ecx\n" /* apple data */
156 "1:\tmovl (%ecx),%ebx\n"
157 "\tadd $4,%ecx\n"
158 "\torl %ebx,%ebx\n"
159 "\tjnz 1b\n"
161 "\tcmpl $0,8(%esp)\n"
162 "\tjne 2f\n"
164 /* LC_MAIN */
165 "\tmovl %edi,0(%esp)\n" /* argc */
166 "\tmovl %esi,4(%esp)\n" /* argv */
167 "\tmovl %edx,8(%esp)\n" /* env */
168 "\tmovl %ecx,12(%esp)\n" /* apple data */
169 "\tcall *%eax\n"
170 "\tmovl %eax,(%esp)\n"
171 "\tcall _wld_exit\n"
172 "\thlt\n"
174 /* LC_UNIXTHREAD */
175 "2:\tmovl (%ecx),%ebx\n"
176 "\tadd $4,%ecx\n"
177 "\torl %ebx,%ebx\n"
178 "\tjnz 2b\n"
180 "\tsubl %ebp,%ecx\n"
181 "\tsubl $8,%ecx\n"
182 "\tleal 4(%ebp),%esp\n"
183 "\tsubl %ecx,%esp\n"
185 "\tmovl %edi,(%esp)\n" /* argc */
186 "\tleal 4(%esp),%edi\n"
187 "\tshrl $2,%ecx\n"
188 "\tcld\n"
189 "\trep; movsd\n" /* argv, ... */
191 "\tmovl $0,%ebp\n"
192 "\tjmpl *%eax\n" )
194 #elif defined(__x86_64__)
196 static const size_t page_size = 0x1000;
197 static const size_t page_mask = 0xfff;
198 #define target_mach_header mach_header_64
199 #define target_segment_command segment_command_64
200 #define TARGET_LC_SEGMENT LC_SEGMENT_64
201 #define target_thread_state_t x86_thread_state64_t
202 #ifdef __DARWIN_UNIX03
203 #define target_thread_ip(x) (x)->__rip
204 #else
205 #define target_thread_ip(x) (x)->rip
206 #endif
208 #define SYSCALL_FUNC( name, nr ) \
209 __ASM_GLOBAL_FUNC( name, \
210 "\tmovq %rcx, %r10\n" \
211 "\tmovq $(" #nr "|0x2000000),%rax\n" \
212 "\tsyscall\n" \
213 "\tjnb 1f\n" \
214 "\tmovq $-1,%rax\n" \
215 "1:\tret\n" )
217 #define SYSCALL_NOERR( name, nr ) \
218 __ASM_GLOBAL_FUNC( name, \
219 "\tmovq %rcx, %r10\n" \
220 "\tmovq $(" #nr "|0x2000000),%rax\n" \
221 "\tsyscall\n" \
222 "\tret\n" )
224 __ASM_GLOBAL_FUNC( start,
225 __ASM_CFI("\t.cfi_undefined %rip\n")
226 "\tpushq $0\n"
227 "\tmovq %rsp,%rbp\n"
228 "\tandq $-16,%rsp\n"
229 "\tsubq $16,%rsp\n"
231 "\tleaq 8(%rbp),%rdi\n" /* stack */
232 "\tmovq %rsp,%rsi\n" /* &is_unix_thread */
233 "\tmovq $0,(%rsi)\n"
234 "\tcall _wld_start\n"
236 "\tmovq 8(%rbp),%rdi\n"
237 "\tdec %rdi\n" /* argc */
238 "\tleaq 24(%rbp),%rsi\n" /* argv */
239 "\tleaq 8(%rsi,%rdi,8),%rdx\n" /* env */
240 "\tmovq %rdx,%rcx\n" /* apple data */
241 "1:\tmovq (%rcx),%r8\n"
242 "\taddq $8,%rcx\n"
243 "\torq %r8,%r8\n"
244 "\tjnz 1b\n"
246 "\tcmpl $0,0(%rsp)\n"
247 "\tjne 2f\n"
249 /* LC_MAIN */
250 "\taddq $16,%rsp\n"
251 "\tcall *%rax\n"
252 "\tmovq %rax,%rdi\n"
253 "\tcall _wld_exit\n"
254 "\thlt\n"
256 /* LC_UNIXTHREAD */
257 "2:\tmovq (%rcx),%r8\n"
258 "\taddq $8,%rcx\n"
259 "\torq %r8,%r8\n"
260 "\tjnz 2b\n"
262 "\tsubq %rbp,%rcx\n"
263 "\tsubq $16,%rcx\n"
264 "\tleaq 8(%rbp),%rsp\n"
265 "\tsubq %rcx,%rsp\n"
267 "\tmovq %rdi,(%rsp)\n" /* argc */
268 "\tleaq 8(%rsp),%rdi\n"
269 "\tshrq $3,%rcx\n"
270 "\tcld\n"
271 "\trep; movsq\n" /* argv, ... */
273 "\tmovq $0,%rbp\n"
274 "\tjmpq *%rax\n" )
276 #else
277 #error preloader not implemented for this CPU
278 #endif
280 void wld_exit( int code ) __attribute__((noreturn));
281 SYSCALL_NOERR( wld_exit, 1 /* SYS_exit */ );
283 ssize_t wld_write( int fd, const void *buffer, size_t len );
284 SYSCALL_FUNC( wld_write, 4 /* SYS_write */ );
286 void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, off_t offset );
287 SYSCALL_FUNC( wld_mmap, 197 /* SYS_mmap */ );
289 void *wld_munmap( void *start, size_t len );
290 SYSCALL_FUNC( wld_munmap, 73 /* SYS_munmap */ );
292 int wld_mincore( void *addr, size_t length, unsigned char *vec );
293 SYSCALL_FUNC( wld_mincore, 78 /* SYS_mincore */ );
295 static intptr_t (*p_dyld_get_image_slide)( const struct target_mach_header* mh );
297 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
298 MAKE_FUNCPTR(dlopen);
299 MAKE_FUNCPTR(dlsym);
300 MAKE_FUNCPTR(dladdr);
301 #undef MAKE_FUNCPTR
303 extern int _dyld_func_lookup( const char *dyld_func_name, void **address );
305 /* replacement for libc functions */
307 static int wld_strncmp( const char *str1, const char *str2, size_t len )
309 if (len <= 0) return 0;
310 while ((--len > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
311 return *str1 - *str2;
315 * wld_printf - just the basics
317 * %x prints a hex number
318 * %s prints a string
319 * %p prints a pointer
321 static int wld_vsprintf(char *buffer, const char *fmt, va_list args )
323 static const char hex_chars[16] = "0123456789abcdef";
324 const char *p = fmt;
325 char *str = buffer;
326 int i;
328 while( *p )
330 if( *p == '%' )
332 p++;
333 if( *p == 'x' )
335 unsigned int x = va_arg( args, unsigned int );
336 for (i = 2*sizeof(x) - 1; i >= 0; i--)
337 *str++ = hex_chars[(x>>(i*4))&0xf];
339 else if (p[0] == 'l' && p[1] == 'x')
341 unsigned long x = va_arg( args, unsigned long );
342 for (i = 2*sizeof(x) - 1; i >= 0; i--)
343 *str++ = hex_chars[(x>>(i*4))&0xf];
344 p++;
346 else if( *p == 'p' )
348 unsigned long x = (unsigned long)va_arg( args, void * );
349 for (i = 2*sizeof(x) - 1; i >= 0; i--)
350 *str++ = hex_chars[(x>>(i*4))&0xf];
352 else if( *p == 's' )
354 char *s = va_arg( args, char * );
355 while(*s)
356 *str++ = *s++;
358 else if( *p == 0 )
359 break;
360 p++;
362 *str++ = *p++;
364 *str = 0;
365 return str - buffer;
368 static __attribute__((format(printf,1,2))) void wld_printf(const char *fmt, ... )
370 va_list args;
371 char buffer[256];
372 int len;
374 va_start( args, fmt );
375 len = wld_vsprintf(buffer, fmt, args );
376 va_end( args );
377 wld_write(2, buffer, len);
380 static __attribute__((noreturn,format(printf,1,2))) void fatal_error(const char *fmt, ... )
382 va_list args;
383 char buffer[256];
384 int len;
386 va_start( args, fmt );
387 len = wld_vsprintf(buffer, fmt, args );
388 va_end( args );
389 wld_write(2, buffer, len);
390 wld_exit(1);
393 static int preloader_overlaps_range( const void *start, const void *end )
395 intptr_t slide = p_dyld_get_image_slide(&_mh_execute_header);
396 struct load_command *cmd = (struct load_command*)(&_mh_execute_header + 1);
397 int i;
399 for (i = 0; i < _mh_execute_header.ncmds; ++i)
401 if (cmd->cmd == TARGET_LC_SEGMENT)
403 struct target_segment_command *seg = (struct target_segment_command*)cmd;
404 const void *seg_start = (const void*)(seg->vmaddr + slide);
405 const void *seg_end = (const char*)seg_start + seg->vmsize;
406 static const char reserved_segname[] = "WINE_4GB_RESERVE";
408 if (!wld_strncmp( seg->segname, reserved_segname, sizeof(reserved_segname)-1 ))
409 continue;
411 if (end > seg_start && start <= seg_end)
413 char segname[sizeof(seg->segname) + 1];
414 memcpy(segname, seg->segname, sizeof(seg->segname));
415 segname[sizeof(segname) - 1] = 0;
416 wld_printf( "WINEPRELOADRESERVE range %p-%p overlaps preloader %s segment %p-%p\n",
417 start, end, segname, seg_start, seg_end );
418 return 1;
421 cmd = (struct load_command*)((char*)cmd + cmd->cmdsize);
424 return 0;
428 * preload_reserve
430 * Reserve a range specified in string format
432 static void preload_reserve( const char *str )
434 const char *p;
435 unsigned long result = 0;
436 void *start = NULL, *end = NULL;
437 int i, first = 1;
439 for (p = str; *p; p++)
441 if (*p >= '0' && *p <= '9') result = result * 16 + *p - '0';
442 else if (*p >= 'a' && *p <= 'f') result = result * 16 + *p - 'a' + 10;
443 else if (*p >= 'A' && *p <= 'F') result = result * 16 + *p - 'A' + 10;
444 else if (*p == '-')
446 if (!first) goto error;
447 start = (void *)(result & ~page_mask);
448 result = 0;
449 first = 0;
451 else goto error;
453 if (!first) end = (void *)((result + page_mask) & ~page_mask);
454 else if (result) goto error; /* single value '0' is allowed */
456 /* sanity checks */
457 if (end <= start || preloader_overlaps_range(start, end))
458 start = end = NULL;
460 /* check for overlap with low memory areas */
461 for (i = 0; preload_info[i].size; i++)
463 if ((char *)preload_info[i].addr > (char *)0x00110000) break;
464 if ((char *)end <= (char *)preload_info[i].addr + preload_info[i].size)
466 start = end = NULL;
467 break;
469 if ((char *)start < (char *)preload_info[i].addr + preload_info[i].size)
470 start = (char *)preload_info[i].addr + preload_info[i].size;
473 while (preload_info[i].size) i++;
474 preload_info[i].addr = start;
475 preload_info[i].size = (char *)end - (char *)start;
476 return;
478 error:
479 fatal_error( "invalid WINEPRELOADRESERVE value '%s'\n", str );
482 /* remove a range from the preload list */
483 static void remove_preload_range( int i )
485 while (preload_info[i].size)
487 preload_info[i].addr = preload_info[i+1].addr;
488 preload_info[i].size = preload_info[i+1].size;
489 i++;
493 static void *get_entry_point( struct target_mach_header *mh, intptr_t slide, int *unix_thread )
495 struct entry_point_command *entry;
496 target_thread_state_t *state;
497 struct load_command *cmd;
498 int i;
500 /* try LC_MAIN first */
501 cmd = (struct load_command *)(mh + 1);
502 for (i = 0; i < mh->ncmds; i++)
504 if (cmd->cmd == LC_MAIN)
506 *unix_thread = FALSE;
507 entry = (struct entry_point_command *)cmd;
508 return (char *)mh + entry->entryoff;
510 cmd = (struct load_command *)((char *)cmd + cmd->cmdsize);
513 /* then try LC_UNIXTHREAD */
514 cmd = (struct load_command *)(mh + 1);
515 for (i = 0; i < mh->ncmds; i++)
517 if (cmd->cmd == LC_UNIXTHREAD)
519 *unix_thread = TRUE;
520 state = (target_thread_state_t *)((char *)cmd + 16);
521 return (void *)(target_thread_ip(state) + slide);
523 cmd = (struct load_command *)((char *)cmd + cmd->cmdsize);
526 return NULL;
529 static int is_region_empty( struct wine_preload_info *info )
531 unsigned char vec[1024];
532 size_t pos, size, block = 1024 * page_size;
533 int i;
535 for (pos = 0; pos < info->size; pos += size)
537 size = (pos + block <= info->size) ? block : (info->size - pos);
538 if (wld_mincore( (char *)info->addr + pos, size, vec ) == -1)
540 if (size <= page_size) continue;
541 block = page_size; size = 0; /* retry with smaller block size */
543 else
545 for (i = 0; i < size / page_size; i++)
546 if (vec[i] & 1) return 0;
550 return 1;
553 static int map_region( struct wine_preload_info *info )
555 int flags = MAP_PRIVATE | MAP_ANON;
556 void *ret;
558 if (!info->addr) flags |= MAP_FIXED;
560 for (;;)
562 ret = wld_mmap( info->addr, info->size, PROT_NONE, flags, -1, 0 );
563 if (ret == info->addr) return 1;
564 if (ret != (void *)-1) wld_munmap( ret, info->size );
565 if (flags & MAP_FIXED) break;
567 /* Some versions of macOS ignore the address hint passed to mmap -
568 * use mincore() to check if its empty and then use MAP_FIXED */
569 if (!is_region_empty( info )) break;
570 flags |= MAP_FIXED;
573 /* don't warn for zero page */
574 if (info->addr >= (void *)0x1000)
575 wld_printf( "preloader: Warning: failed to reserve range %p-%p\n",
576 info->addr, (char *)info->addr + info->size );
577 return 0;
580 static inline void get_dyld_func( const char *name, void **func )
582 _dyld_func_lookup( name, func );
583 if (!*func) fatal_error( "Failed to get function pointer for %s\n", name );
586 #define LOAD_POSIX_DYLD_FUNC(f) get_dyld_func( "__dyld_" #f, (void **)&p##f )
587 #define LOAD_MACHO_DYLD_FUNC(f) get_dyld_func( "_" #f, (void **)&p##f )
589 void *wld_start( void *stack, int *is_unix_thread )
591 struct wine_preload_info builtin_dlls = { (void *)0x7a000000, 0x02000000 };
592 struct wine_preload_info **wine_main_preload_info;
593 char **argv, **p, *reserve = NULL;
594 struct target_mach_header *mh;
595 void *mod, *entry;
596 int *pargc, i;
597 Dl_info info;
599 pargc = stack;
600 argv = (char **)pargc + 1;
601 if (*pargc < 2) fatal_error( "Usage: %s wine_binary [args]\n", argv[0] );
603 /* skip over the parameters */
604 p = argv + *pargc + 1;
606 /* skip over the environment */
607 while (*p)
609 static const char res[] = "WINEPRELOADRESERVE=";
610 if (!wld_strncmp( *p, res, sizeof(res)-1 )) reserve = *p + sizeof(res) - 1;
611 p++;
614 LOAD_POSIX_DYLD_FUNC( dlopen );
615 LOAD_POSIX_DYLD_FUNC( dlsym );
616 LOAD_POSIX_DYLD_FUNC( dladdr );
617 LOAD_MACHO_DYLD_FUNC( _dyld_get_image_slide );
619 /* reserve memory that Wine needs */
620 if (reserve) preload_reserve( reserve );
621 for (i = 0; preload_info[i].size; i++)
623 if (!map_region( &preload_info[i] ))
625 remove_preload_range( i );
626 i--;
630 if (!map_region( &builtin_dlls ))
631 builtin_dlls.size = 0;
633 /* load the main binary */
634 if (!(mod = pdlopen( argv[1], RTLD_NOW )))
635 fatal_error( "%s: could not load binary\n", argv[1] );
637 if (builtin_dlls.size)
638 wld_munmap( builtin_dlls.addr, builtin_dlls.size );
640 /* store pointer to the preload info into the appropriate main binary variable */
641 wine_main_preload_info = pdlsym( mod, "wine_main_preload_info" );
642 if (wine_main_preload_info) *wine_main_preload_info = preload_info;
643 else wld_printf( "wine_main_preload_info not found\n" );
645 if (!pdladdr( wine_main_preload_info, &info ) || !(mh = info.dli_fbase))
646 fatal_error( "%s: could not find mach header\n", argv[1] );
647 if (!(entry = get_entry_point( mh, p_dyld_get_image_slide(mh), is_unix_thread )))
648 fatal_error( "%s: could not find entry point\n", argv[1] );
650 return entry;
653 #endif /* __APPLE__ */