File indexing completed on 2023-07-21 22:40:33
a0ab2a7b0… Seba*0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #ifdef __APPLE__
0026
0027 #include "config.h"
0028
df8c5a37e… Alex*0029 #include <stdarg.h>
a0ab2a7b0… Seba*0030 #include <stdio.h>
0031 #include <stdlib.h>
0032 #include <string.h>
0033 #include <sys/types.h>
28d7d5ba9… Alex*0034 #include <sys/stat.h>
a0ab2a7b0… Seba*0035 #include <fcntl.h>
e3001b6a7… Alex*0036 #include <sys/mman.h>
a0ab2a7b0… Seba*0037 #ifdef HAVE_SYS_SYSCALL_H
0038 # include <sys/syscall.h>
0039 #endif
28d7d5ba9… Alex*0040 #include <unistd.h>
0041 #include <dlfcn.h>
a0ab2a7b0… Seba*0042 #ifdef HAVE_MACH_O_LOADER_H
0043 #include <mach/thread_status.h>
0044 #include <mach-o/loader.h>
cc24255da… Ken *0045 #include <mach-o/ldsyms.h>
a0ab2a7b0… Seba*0046 #endif
0047
d5a372abb… Alex*0048 #include "wine/asm.h"
df8c5a37e… Alex*0049 #include "main.h"
a0ab2a7b0… Seba*0050
93941d6ec… Bren*0051 #if defined(__x86_64__)
cfa0dd9dd… Bren*0052
0053
0054
307f5d00f… Bren*0055
cfa0dd9dd… Bren*0056 __asm__(".zerofill WINE_RESERVE,WINE_RESERVE,___wine_reserve,0x1fffff000");
93941d6ec… Bren*0057
0058 static const struct wine_preload_info zerofill_sections[] =
0059 {
cfa0dd9dd… Bren*0060 { (void *)0x000000001000, 0x1fffff000 },
93941d6ec… Bren*0061 { 0, 0 }
0062 };
0063 #else
0064 static const struct wine_preload_info zerofill_sections[] =
0065 {
0066 { 0, 0 }
0067 };
307f5d00f… Bren*0068 #endif
0069
a0ab2a7b0… Seba*0070 #ifndef LC_MAIN
0071 #define LC_MAIN 0x80000028
0072 struct entry_point_command
0073 {
0074 uint32_t cmd;
0075 uint32_t cmdsize;
0076 uint64_t entryoff;
0077 uint64_t stacksize;
0078 };
0079 #endif
0080
0081 static struct wine_preload_info preload_info[] =
0082 {
0083
0084
0085 #ifdef __i386__
0086 { (void *)0x00000000, 0x00001000 },
0087 { (void *)0x00001000, 0x0000f000 },
0088 { (void *)0x00010000, 0x00100000 },
0089 { (void *)0x00110000, 0x67ef0000 },
6b0836e3f… Tim *0090 { (void *)0x7f000000, 0x03000000 },
a0ab2a7b0… Seba*0091 #else
cfa0dd9dd… Bren*0092 { (void *)0x000000001000, 0x1fffff000 },
c10207e2a… Bren*0093 { (void *)0x7ff000000000, 0x01ff0000 },
a0ab2a7b0… Seba*0094 #endif
0095 { 0, 0 },
0096 { 0, 0 }
0097 };
0098
0099
0100
0101
0102
0103
0104
0105 void *__stack_chk_guard = 0;
0106 void __stack_chk_fail_local(void) { return; }
0107 void __stack_chk_fail(void) { return; }
0108
4e6dbf3b9… Bren*0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124 int NXArgc = 0;
0125 const char** NXArgv = NULL;
0126 const char** environ = NULL;
0127 const char* __progname = NULL;
0128
0129 extern void* __dso_handle;
0130 struct ProgramVars
0131 {
0132 void* mh;
0133 int* NXArgcPtr;
0134 const char*** NXArgvPtr;
0135 const char*** environPtr;
0136 const char** __prognamePtr;
0137 };
0138 __attribute__((used)) static struct ProgramVars pvars
0139 __attribute__ ((section ("__DATA,__program_vars"))) = { &__dso_handle, &NXArgc, &NXArgv, &environ, &__progname };
0140
0141
4ec770a13… Bren*0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
a0ab2a7b0… Seba*0183 #ifdef __i386__
0184
0185 static const size_t page_mask = 0xfff;
0186 #define target_mach_header mach_header
cc24255da… Ken *0187 #define target_segment_command segment_command
0188 #define TARGET_LC_SEGMENT LC_SEGMENT
a0ab2a7b0… Seba*0189 #define target_thread_state_t i386_thread_state_t
0190 #ifdef __DARWIN_UNIX03
0191 #define target_thread_ip(x) (x)->__eip
0192 #else
0193 #define target_thread_ip(x) (x)->eip
0194 #endif
0195
0196 #define SYSCALL_FUNC( name, nr ) \
0197 __ASM_GLOBAL_FUNC( name, \
0198 "\tmovl $" #nr ",%eax\n" \
0199 "\tint $0x80\n" \
0200 "\tjnb 1f\n" \
0201 "\tmovl $-1,%eax\n" \
0202 "1:\tret\n" )
0203
0204 #define SYSCALL_NOERR( name, nr ) \
0205 __ASM_GLOBAL_FUNC( name, \
0206 "\tmovl $" #nr ",%eax\n" \
0207 "\tint $0x80\n" \
0208 "\tret\n" )
0209
0210 __ASM_GLOBAL_FUNC( start,
0211 __ASM_CFI("\t.cfi_undefined %eip\n")
0212
4ec770a13… Bren*0213 "\t.byte 0x6a,0x00\n"
0214 "\t.byte 0x89,0xe5\n"
0215 "\t.byte 0x83,0xe4,0xf0\n"
0216 "\t.byte 0x83,0xec,0x10\n"
0217 "\t.byte 0x8b,0x5d,0x04\n"
0218 "\t.byte 0x89,0x5c,0x24,0x00\n"
0219
0220
a0ab2a7b0… Seba*0221 "\tleal 4(%ebp),%eax\n"
0222 "\tmovl %eax,0(%esp)\n"
0223 "\tleal 8(%esp),%eax\n"
0224 "\tmovl %eax,4(%esp)\n"
0225 "\tmovl $0,(%eax)\n"
0226 "\tcall _wld_start\n"
0227
588e55542… Bren*0228
0229 "\tcmpl $0,8(%esp)\n"
0230 "\tjne 2f\n"
0231
0232 "\tmovl 4(%ebp),%edi\n"
0233 "\tleal 8(%ebp),%esi\n"
4ec770a13… Bren*0234 "\tleal 4(%esi,%edi,4),%edx\n"
0235 "\tmovl %edx,%ecx\n"
a0ab2a7b0… Seba*0236 "1:\tmovl (%ecx),%ebx\n"
0237 "\tadd $4,%ecx\n"
4ec770a13… Bren*0238 "\torl %ebx,%ebx\n"
0239 "\tjnz 1b\n"
a0ab2a7b0… Seba*0240
0241
0242 "\tmovl %edi,0(%esp)\n"
0243 "\tmovl %esi,4(%esp)\n"
0244 "\tmovl %edx,8(%esp)\n"
0245 "\tmovl %ecx,12(%esp)\n"
4ec770a13… Bren*0246 "\tcall *%eax\n"
0247 "\tmovl %eax,(%esp)\n"
0248 "\tcall _wld_exit\n"
a0ab2a7b0… Seba*0249 "\thlt\n"
0250
0251
588e55542… Bren*0252 "\t2:movl %ebp,%esp\n"
0253 "\taddl $4,%esp\n"
4ec770a13… Bren*0254 "\tmovl $0,%ebp\n"
0255 "\tjmpl *%eax\n" )
a0ab2a7b0… Seba*0256
0257 #elif defined(__x86_64__)
0258
0259 static const size_t page_mask = 0xfff;
0260 #define target_mach_header mach_header_64
cc24255da… Ken *0261 #define target_segment_command segment_command_64
0262 #define TARGET_LC_SEGMENT LC_SEGMENT_64
a0ab2a7b0… Seba*0263 #define target_thread_state_t x86_thread_state64_t
0264 #ifdef __DARWIN_UNIX03
0265 #define target_thread_ip(x) (x)->__rip
0266 #else
0267 #define target_thread_ip(x) (x)->rip
0268 #endif
0269
0270 #define SYSCALL_FUNC( name, nr ) \
0271 __ASM_GLOBAL_FUNC( name, \
0272 "\tmovq %rcx, %r10\n" \
0273 "\tmovq $(" #nr "|0x2000000),%rax\n" \
0274 "\tsyscall\n" \
0275 "\tjnb 1f\n" \
0276 "\tmovq $-1,%rax\n" \
0277 "1:\tret\n" )
0278
0279 #define SYSCALL_NOERR( name, nr ) \
0280 __ASM_GLOBAL_FUNC( name, \
0281 "\tmovq %rcx, %r10\n" \
0282 "\tmovq $(" #nr "|0x2000000),%rax\n" \
0283 "\tsyscall\n" \
0284 "\tret\n" )
0285
0286 __ASM_GLOBAL_FUNC( start,
0287 __ASM_CFI("\t.cfi_undefined %rip\n")
4ec770a13… Bren*0288 "\tpushq $0\n"
0289 "\tmovq %rsp,%rbp\n"
0290 "\tandq $-16,%rsp\n"
0291 "\tsubq $16,%rsp\n"
a0ab2a7b0… Seba*0292
4ec770a13… Bren*0293
a0ab2a7b0… Seba*0294 "\tleaq 8(%rbp),%rdi\n"
0295 "\tmovq %rsp,%rsi\n"
0296 "\tmovq $0,(%rsi)\n"
0297 "\tcall _wld_start\n"
0298
588e55542… Bren*0299
0300 "\tcmpl $0,0(%rsp)\n"
0301 "\tjne 2f\n"
0302
0303
0304 "\tmovq 8(%rbp),%rdi\n"
0305 "\tleaq 16(%rbp),%rsi\n"
4ec770a13… Bren*0306 "\tleaq 8(%rsi,%rdi,8),%rdx\n"
0307 "\tmovq %rdx,%rcx\n"
a0ab2a7b0… Seba*0308 "1:\tmovq (%rcx),%r8\n"
0309 "\taddq $8,%rcx\n"
4ec770a13… Bren*0310 "\torq %r8,%r8\n"
0311 "\tjnz 1b\n"
a0ab2a7b0… Seba*0312
4ec770a13… Bren*0313 "\taddq $16,%rsp\n"
0314 "\tcall *%rax\n"
0315 "\tmovq %rax,%rdi\n"
0316 "\tcall _wld_exit\n"
a0ab2a7b0… Seba*0317 "\thlt\n"
0318
0319
588e55542… Bren*0320 "\t2:movq %rbp,%rsp\n"
0321 "\taddq $8,%rsp\n"
4ec770a13… Bren*0322 "\tmovq $0,%rbp\n"
0323 "\tjmpq *%rax\n" )
a0ab2a7b0… Seba*0324
0325 #else
0326 #error preloader not implemented for this CPU
0327 #endif
0328
0329 void wld_exit( int code ) __attribute__((noreturn));
0330 SYSCALL_NOERR( wld_exit, 1 );
0331
0332 ssize_t wld_write( int fd, const void *buffer, size_t len );
0333 SYSCALL_FUNC( wld_write, 4 );
0334
0335 void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, off_t offset );
0336 SYSCALL_FUNC( wld_mmap, 197 );
0337
0338 void *wld_munmap( void *start, size_t len );
0339 SYSCALL_FUNC( wld_munmap, 73 );
0340
0341 static intptr_t (*p_dyld_get_image_slide)( const struct target_mach_header* mh );
0342
0343 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
0344 MAKE_FUNCPTR(dlopen);
0345 MAKE_FUNCPTR(dlsym);
0346 MAKE_FUNCPTR(dladdr);
0347 #undef MAKE_FUNCPTR
0348
0349 extern int _dyld_func_lookup( const char *dyld_func_name, void **address );
0350
df8c5a37e… Alex*0351
0352
588e55542… Bren*0353 void * memmove( void *dst, const void *src, size_t len )
0354 {
0355 char *d = dst;
0356 const char *s = src;
0357 if (d < s)
0358 while (len--)
0359 *d++ = *s++;
0360 else
0361 {
0362 const char *lasts = s + (len-1);
0363 char *lastd = d + (len-1);
0364 while (len--)
0365 *lastd-- = *lasts--;
0366 }
0367 return dst;
0368 }
0369
df8c5a37e… Alex*0370 static int wld_strncmp( const char *str1, const char *str2, size_t len )
0371 {
0372 if (len <= 0) return 0;
0373 while ((--len > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
0374 return *str1 - *str2;
0375 }
0376
0377
0378
0379
0380
0381
0382
0383
0384 static int wld_vsprintf(char *buffer, const char *fmt, va_list args )
0385 {
0386 static const char hex_chars[16] = "0123456789abcdef";
0387 const char *p = fmt;
0388 char *str = buffer;
0389 int i;
0390
0391 while( *p )
0392 {
0393 if( *p == '%' )
0394 {
0395 p++;
0396 if( *p == 'x' )
0397 {
0398 unsigned int x = va_arg( args, unsigned int );
0399 for (i = 2*sizeof(x) - 1; i >= 0; i--)
0400 *str++ = hex_chars[(x>>(i*4))&0xf];
0401 }
0402 else if (p[0] == 'l' && p[1] == 'x')
0403 {
0404 unsigned long x = va_arg( args, unsigned long );
0405 for (i = 2*sizeof(x) - 1; i >= 0; i--)
0406 *str++ = hex_chars[(x>>(i*4))&0xf];
0407 p++;
0408 }
0409 else if( *p == 'p' )
0410 {
0411 unsigned long x = (unsigned long)va_arg( args, void * );
0412 for (i = 2*sizeof(x) - 1; i >= 0; i--)
0413 *str++ = hex_chars[(x>>(i*4))&0xf];
0414 }
0415 else if( *p == 's' )
0416 {
0417 char *s = va_arg( args, char * );
0418 while(*s)
0419 *str++ = *s++;
0420 }
0421 else if( *p == 0 )
0422 break;
0423 p++;
0424 }
0425 *str++ = *p++;
0426 }
0427 *str = 0;
0428 return str - buffer;
0429 }
0430
0431 static __attribute__((format(printf,1,2))) void wld_printf(const char *fmt, ... )
0432 {
0433 va_list args;
0434 char buffer[256];
0435 int len;
0436
0437 va_start( args, fmt );
0438 len = wld_vsprintf(buffer, fmt, args );
0439 va_end( args );
0440 wld_write(2, buffer, len);
0441 }
0442
0443 static __attribute__((noreturn,format(printf,1,2))) void fatal_error(const char *fmt, ... )
0444 {
0445 va_list args;
0446 char buffer[256];
0447 int len;
0448
0449 va_start( args, fmt );
0450 len = wld_vsprintf(buffer, fmt, args );
0451 va_end( args );
0452 wld_write(2, buffer, len);
0453 wld_exit(1);
0454 }
0455
cc24255da… Ken *0456 static int preloader_overlaps_range( const void *start, const void *end )
0457 {
0458 intptr_t slide = p_dyld_get_image_slide(&_mh_execute_header);
0459 struct load_command *cmd = (struct load_command*)(&_mh_execute_header + 1);
0460 int i;
0461
0462 for (i = 0; i < _mh_execute_header.ncmds; ++i)
0463 {
0464 if (cmd->cmd == TARGET_LC_SEGMENT)
0465 {
0466 struct target_segment_command *seg = (struct target_segment_command*)cmd;
0467 const void *seg_start = (const void*)(seg->vmaddr + slide);
0468 const void *seg_end = (const char*)seg_start + seg->vmsize;
cfa0dd9dd… Bren*0469 static const char reserved_segname[] = "WINE_RESERVE";
307f5d00f… Bren*0470
0471 if (!wld_strncmp( seg->segname, reserved_segname, sizeof(reserved_segname)-1 ))
0472 continue;
cc24255da… Ken *0473
0474 if (end > seg_start && start <= seg_end)
0475 {
0476 char segname[sizeof(seg->segname) + 1];
0477 memcpy(segname, seg->segname, sizeof(seg->segname));
0478 segname[sizeof(segname) - 1] = 0;
0479 wld_printf( "WINEPRELOADRESERVE range %p-%p overlaps preloader %s segment %p-%p\n",
0480 start, end, segname, seg_start, seg_end );
0481 return 1;
0482 }
0483 }
0484 cmd = (struct load_command*)((char*)cmd + cmd->cmdsize);
0485 }
0486
0487 return 0;
0488 }
0489
df8c5a37e… Alex*0490
0491
0492
0493
0494
0495 static void preload_reserve( const char *str )
0496 {
0497 const char *p;
0498 unsigned long result = 0;
0499 void *start = NULL, *end = NULL;
0500 int i, first = 1;
0501
0502 for (p = str; *p; p++)
0503 {
0504 if (*p >= '0' && *p <= '9') result = result * 16 + *p - '0';
0505 else if (*p >= 'a' && *p <= 'f') result = result * 16 + *p - 'a' + 10;
0506 else if (*p >= 'A' && *p <= 'F') result = result * 16 + *p - 'A' + 10;
0507 else if (*p == '-')
0508 {
0509 if (!first) goto error;
0510 start = (void *)(result & ~page_mask);
0511 result = 0;
0512 first = 0;
0513 }
0514 else goto error;
0515 }
0516 if (!first) end = (void *)((result + page_mask) & ~page_mask);
0517 else if (result) goto error;
0518
0519
cc24255da… Ken *0520 if (end <= start || preloader_overlaps_range(start, end))
0521 start = end = NULL;
df8c5a37e… Alex*0522
0523
0524 for (i = 0; preload_info[i].size; i++)
0525 {
0526 if ((char *)preload_info[i].addr > (char *)0x00110000) break;
0527 if ((char *)end <= (char *)preload_info[i].addr + preload_info[i].size)
0528 {
0529 start = end = NULL;
0530 break;
0531 }
0532 if ((char *)start < (char *)preload_info[i].addr + preload_info[i].size)
0533 start = (char *)preload_info[i].addr + preload_info[i].size;
0534 }
0535
0536 while (preload_info[i].size) i++;
0537 preload_info[i].addr = start;
0538 preload_info[i].size = (char *)end - (char *)start;
0539 return;
0540
0541 error:
0542 fatal_error( "invalid WINEPRELOADRESERVE value '%s'\n", str );
0543 }
0544
0545
0546 static void remove_preload_range( int i )
0547 {
0548 while (preload_info[i].size)
0549 {
0550 preload_info[i].addr = preload_info[i+1].addr;
0551 preload_info[i].size = preload_info[i+1].size;
0552 i++;
0553 }
0554 }
0555
a0ab2a7b0… Seba*0556 static void *get_entry_point( struct target_mach_header *mh, intptr_t slide, int *unix_thread )
0557 {
0558 struct entry_point_command *entry;
0559 target_thread_state_t *state;
0560 struct load_command *cmd;
0561 int i;
0562
0563
0564 cmd = (struct load_command *)(mh + 1);
0565 for (i = 0; i < mh->ncmds; i++)
0566 {
0567 if (cmd->cmd == LC_MAIN)
0568 {
0569 *unix_thread = FALSE;
0570 entry = (struct entry_point_command *)cmd;
0571 return (char *)mh + entry->entryoff;
0572 }
0573 cmd = (struct load_command *)((char *)cmd + cmd->cmdsize);
0574 }
0575
0576
0577 cmd = (struct load_command *)(mh + 1);
0578 for (i = 0; i < mh->ncmds; i++)
0579 {
0580 if (cmd->cmd == LC_UNIXTHREAD)
0581 {
0582 *unix_thread = TRUE;
0583 state = (target_thread_state_t *)((char *)cmd + 16);
0584 return (void *)(target_thread_ip(state) + slide);
0585 }
0586 cmd = (struct load_command *)((char *)cmd + cmd->cmdsize);
0587 }
0588
0589 return NULL;
0590 };
0591
93941d6ec… Bren*0592 static int is_zerofill( struct wine_preload_info *info )
a0ab2a7b0… Seba*0593 {
0594 int i;
0595
93941d6ec… Bren*0596 for (i = 0; zerofill_sections[i].size; i++)
a0ab2a7b0… Seba*0597 {
93941d6ec… Bren*0598 if ((zerofill_sections[i].addr == info->addr) &&
0599 (zerofill_sections[i].size == info->size))
0600 return 1;
a0ab2a7b0… Seba*0601 }
93941d6ec… Bren*0602 return 0;
a0ab2a7b0… Seba*0603 }
0604
0605 static int map_region( struct wine_preload_info *info )
0606 {
0607 int flags = MAP_PRIVATE | MAP_ANON;
0608 void *ret;
0609
93941d6ec… Bren*0610 if (!info->addr || is_zerofill( info )) flags |= MAP_FIXED;
a0ab2a7b0… Seba*0611
93941d6ec… Bren*0612 ret = wld_mmap( info->addr, info->size, PROT_NONE, flags, -1, 0 );
0613 if (ret == info->addr) return 1;
0614 if (ret != (void *)-1) wld_munmap( ret, info->size );
a0ab2a7b0… Seba*0615
0616
0617 if (info->addr >= (void *)0x1000)
0618 wld_printf( "preloader: Warning: failed to reserve range %p-%p\n",
0619 info->addr, (char *)info->addr + info->size );
0620 return 0;
0621 }
0622
0623 static inline void get_dyld_func( const char *name, void **func )
0624 {
0625 _dyld_func_lookup( name, func );
0626 if (!*func) fatal_error( "Failed to get function pointer for %s\n", name );
0627 }
0628
0629 #define LOAD_POSIX_DYLD_FUNC(f) get_dyld_func( "__dyld_" #f, (void **)&p##f )
0630 #define LOAD_MACHO_DYLD_FUNC(f) get_dyld_func( "_" #f, (void **)&p##f )
0631
588e55542… Bren*0632 static void fixup_stack( void *stack )
0633 {
0634 int *pargc;
36bb7175c… Bren*0635 char **argv, **env_new;
0636 static char dummyvar[] = "WINEPRELOADERDUMMYVAR=1";
588e55542… Bren*0637
0638 pargc = stack;
0639 argv = (char **)pargc + 1;
0640
36bb7175c… Bren*0641
588e55542… Bren*0642 *pargc = *pargc - 1;
36bb7175c… Bren*0643 memmove( &argv[0], &argv[1], (*pargc + 1) * sizeof(char *) );
0644
0645 env_new = &argv[*pargc-1] + 2;
0646
0647
0648
0649
0650 env_new[0] = dummyvar;
588e55542… Bren*0651 }
0652
f99eef684… Bren*0653 static void set_program_vars( void *stack, void *mod )
0654 {
0655 int *pargc;
4e6dbf3b9… Bren*0656 const char **argv, **env;
f99eef684… Bren*0657 int *wine_NXArgc = pdlsym( mod, "NXArgc" );
4e6dbf3b9… Bren*0658 const char ***wine_NXArgv = pdlsym( mod, "NXArgv" );
0659 const char ***wine_environ = pdlsym( mod, "environ" );
f99eef684… Bren*0660
0661 pargc = stack;
4e6dbf3b9… Bren*0662 argv = (const char **)pargc + 1;
f99eef684… Bren*0663 env = &argv[*pargc-1] + 2;
0664
4e6dbf3b9… Bren*0665
f99eef684… Bren*0666 if (wine_NXArgc)
0667 *wine_NXArgc = *pargc;
0668 else
0669 wld_printf( "preloader: Warning: failed to set NXArgc\n" );
0670
0671 if (wine_NXArgv)
0672 *wine_NXArgv = argv;
0673 else
0674 wld_printf( "preloader: Warning: failed to set NXArgv\n" );
0675
0676 if (wine_environ)
0677 *wine_environ = env;
0678 else
0679 wld_printf( "preloader: Warning: failed to set environ\n" );
4e6dbf3b9… Bren*0680
0681
0682 NXArgc = *pargc;
0683 NXArgv = argv;
0684 environ = env;
f99eef684… Bren*0685 }
0686
a0ab2a7b0… Seba*0687 void *wld_start( void *stack, int *is_unix_thread )
0688 {
cfa0dd9dd… Bren*0689 #ifdef __i386__
a0ab2a7b0… Seba*0690 struct wine_preload_info builtin_dlls = { (void *)0x7a000000, 0x02000000 };
cfa0dd9dd… Bren*0691 #endif
a0ab2a7b0… Seba*0692 struct wine_preload_info **wine_main_preload_info;
0693 char **argv, **p, *reserve = NULL;
0694 struct target_mach_header *mh;
0695 void *mod, *entry;
0696 int *pargc, i;
0697 Dl_info info;
0698
0699 pargc = stack;
0700 argv = (char **)pargc + 1;
0701 if (*pargc < 2) fatal_error( "Usage: %s wine_binary [args]\n", argv[0] );
0702
0703
0704 p = argv + *pargc + 1;
0705
0706
0707 while (*p)
0708 {
0709 static const char res[] = "WINEPRELOADRESERVE=";
0710 if (!wld_strncmp( *p, res, sizeof(res)-1 )) reserve = *p + sizeof(res) - 1;
0711 p++;
0712 }
0713
cc24255da… Ken *0714 LOAD_POSIX_DYLD_FUNC( dlopen );
0715 LOAD_POSIX_DYLD_FUNC( dlsym );
0716 LOAD_POSIX_DYLD_FUNC( dladdr );
0717 LOAD_MACHO_DYLD_FUNC( _dyld_get_image_slide );
0718
a0ab2a7b0… Seba*0719
df8c5a37e… Alex*0720 if (reserve) preload_reserve( reserve );
a0ab2a7b0… Seba*0721 for (i = 0; preload_info[i].size; i++)
0722 {
0723 if (!map_region( &preload_info[i] ))
0724 {
df8c5a37e… Alex*0725 remove_preload_range( i );
a0ab2a7b0… Seba*0726 i--;
0727 }
0728 }
0729
cfa0dd9dd… Bren*0730 #ifdef __i386__
a0ab2a7b0… Seba*0731 if (!map_region( &builtin_dlls ))
0732 builtin_dlls.size = 0;
cfa0dd9dd… Bren*0733 #endif
a0ab2a7b0… Seba*0734
0735
0736 if (!(mod = pdlopen( argv[1], RTLD_NOW )))
0737 fatal_error( "%s: could not load binary\n", argv[1] );
0738
cfa0dd9dd… Bren*0739 #ifdef __i386__
a0ab2a7b0… Seba*0740 if (builtin_dlls.size)
0741 wld_munmap( builtin_dlls.addr, builtin_dlls.size );
cfa0dd9dd… Bren*0742 #endif
a0ab2a7b0… Seba*0743
0744
0745 wine_main_preload_info = pdlsym( mod, "wine_main_preload_info" );
0746 if (wine_main_preload_info) *wine_main_preload_info = preload_info;
0747 else wld_printf( "wine_main_preload_info not found\n" );
0748
0749 if (!pdladdr( wine_main_preload_info, &info ) || !(mh = info.dli_fbase))
0750 fatal_error( "%s: could not find mach header\n", argv[1] );
0751 if (!(entry = get_entry_point( mh, p_dyld_get_image_slide(mh), is_unix_thread )))
0752 fatal_error( "%s: could not find entry point\n", argv[1] );
0753
588e55542… Bren*0754
0755 fixup_stack(stack);
0756
f99eef684… Bren*0757
0758
0759
0760
0761
0762
9ab93415f… Bren*0763
f99eef684… Bren*0764 set_program_vars( stack, mod );
9ab93415f… Bren*0765
a0ab2a7b0… Seba*0766 return entry;
0767 }
0768
0769 #endif