2 * Unix interface for loader functions
4 * Copyright (C) 2020 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "wine/port.h"
38 #ifdef HAVE_SYS_MMAN_H
39 # include <sys/mman.h>
41 #ifdef HAVE_SYS_PRCTL_H
42 # include <sys/prctl.h>
44 #ifdef HAVE_SYS_RESOURCE_H
45 # include <sys/resource.h>
47 #ifdef HAVE_SYS_UTSNAME_H
48 #include <sys/utsname.h>
50 #ifdef HAVE_SYS_WAIT_H
54 # include <CoreFoundation/CoreFoundation.h>
55 # define LoadResource MacLoadResource
56 # define GetCurrentThread MacGetCurrentThread
57 # include <CoreServices/CoreServices.h>
59 # undef GetCurrentThread
61 # include <mach-o/getsect.h>
62 # include <crt_externs.h>
64 # ifndef _POSIX_SPAWN_DISABLE_ASLR
65 # define _POSIX_SPAWN_DISABLE_ASLR 0x0100
70 #define WIN32_NO_STATUS
71 #define NONAMELESSUNION
72 #define NONAMELESSSTRUCT
78 #include "unix_private.h"
79 #include "wine/library.h"
80 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
84 extern IMAGE_NT_HEADERS __wine_spec_nt_header
;
85 extern void CDECL
__wine_set_unix_funcs( int version
, const struct unix_funcs
*funcs
);
88 static void fatal_error( const char *err
, ... ) __attribute__((noreturn
, format(printf
,1,2)));
91 extern int __wine_main_argc
;
92 extern char **__wine_main_argv
;
93 extern char **__wine_main_environ
;
95 #if defined(linux) || defined(__APPLE__)
96 static const BOOL use_preloader
= TRUE
;
98 static const BOOL use_preloader
= FALSE
;
101 static const BOOL is_win64
= (sizeof(void *) > sizeof(int));
103 static int main_argc
;
104 static char **main_argv
;
105 static char **main_envp
;
107 static const char *bin_dir
;
108 static const char *dll_dir
;
109 static const char **dll_paths
;
110 static SIZE_T dll_path_maxlen
;
112 const char *data_dir
= NULL
;
113 const char *build_dir
= NULL
;
114 const char *config_dir
= NULL
;
116 static CPTABLEINFO unix_table
;
118 static inline void *get_rva( const IMAGE_NT_HEADERS
*nt
, ULONG_PTR addr
)
120 return (BYTE
*)nt
+ addr
;
123 /* adjust an array of pointers to make them into RVAs */
124 static inline void fixup_rva_ptrs( void *array
, BYTE
*base
, unsigned int count
)
129 for ( ; count
; count
--, src
++, dst
++) *dst
= *src
? *src
- base
: 0;
132 /* fixup an array of RVAs by adding the specified delta */
133 static inline void fixup_rva_dwords( DWORD
*ptr
, int delta
, unsigned int count
)
135 for ( ; count
; count
--, ptr
++) if (*ptr
) *ptr
+= delta
;
139 /* fixup an array of name/ordinal RVAs by adding the specified delta */
140 static inline void fixup_rva_names( UINT_PTR
*ptr
, int delta
)
142 for ( ; *ptr
; ptr
++) if (!(*ptr
& IMAGE_ORDINAL_FLAG
)) *ptr
+= delta
;
146 /* fixup RVAs in the resource directory */
147 static void fixup_so_resources( IMAGE_RESOURCE_DIRECTORY
*dir
, BYTE
*root
, int delta
)
149 IMAGE_RESOURCE_DIRECTORY_ENTRY
*entry
= (IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(dir
+ 1);
152 for (i
= 0; i
< dir
->NumberOfNamedEntries
+ dir
->NumberOfIdEntries
; i
++, entry
++)
154 void *ptr
= root
+ entry
->u2
.s2
.OffsetToDirectory
;
155 if (entry
->u2
.s2
.DataIsDirectory
) fixup_so_resources( ptr
, root
, delta
);
156 else fixup_rva_dwords( &((IMAGE_RESOURCE_DATA_ENTRY
*)ptr
)->OffsetToData
, delta
, 1 );
160 /* die on a fatal error; use only during initialization */
161 static void fatal_error( const char *err
, ... )
165 va_start( args
, err
);
166 fprintf( stderr
, "wine: " );
167 vfprintf( stderr
, err
, args
);
172 static void set_max_limit( int limit
)
174 struct rlimit rlimit
;
176 if (!getrlimit( limit
, &rlimit
))
178 rlimit
.rlim_cur
= rlimit
.rlim_max
;
179 setrlimit( limit
, &rlimit
);
183 /* canonicalize path and return its directory name */
184 static char *realpath_dirname( const char *name
)
186 char *p
, *fullpath
= realpath( name
, NULL
);
190 p
= strrchr( fullpath
, '/' );
191 if (p
== fullpath
) p
++;
197 /* if string ends with tail, remove it */
198 static char *remove_tail( const char *str
, const char *tail
)
200 size_t len
= strlen( str
);
201 size_t tail_len
= strlen( tail
);
204 if (len
< tail_len
) return NULL
;
205 if (strcmp( str
+ len
- tail_len
, tail
)) return NULL
;
206 ret
= malloc( len
- tail_len
+ 1 );
207 memcpy( ret
, str
, len
- tail_len
);
208 ret
[len
- tail_len
] = 0;
212 /* build a path from the specified dir and name */
213 static char *build_path( const char *dir
, const char *name
)
215 size_t len
= strlen( dir
);
216 char *ret
= malloc( len
+ strlen( name
) + 2 );
218 memcpy( ret
, dir
, len
);
219 if (len
&& ret
[len
- 1] != '/') ret
[len
++] = '/';
220 strcpy( ret
+ len
, name
);
224 static void set_dll_path(void)
226 char *p
, *path
= getenv( "WINEDLLPATH" );
229 if (path
) for (p
= path
, count
= 1; *p
; p
++) if (*p
== ':') count
++;
231 dll_paths
= malloc( (count
+ 2) * sizeof(*dll_paths
) );
234 if (!build_dir
) dll_paths
[count
++] = dll_dir
;
239 for (p
= strtok( path
, ":" ); p
; p
= strtok( NULL
, ":" )) dll_paths
[count
++] = strdup( p
);
243 for (i
= 0; i
< count
; i
++) dll_path_maxlen
= max( dll_path_maxlen
, strlen(dll_paths
[i
]) );
244 dll_paths
[count
] = NULL
;
248 static void set_config_dir(void)
251 const char *prefix
= getenv( "WINEPREFIX" );
255 if (prefix
[0] != '/')
256 fatal_error( "invalid directory %s in WINEPREFIX: not an absolute path\n", prefix
);
257 config_dir
= dir
= strdup( prefix
);
258 for (p
= dir
+ strlen(dir
) - 1; p
> dir
&& *p
== '/'; p
--) *p
= 0;
262 const char *home
= getenv( "HOME" );
265 struct passwd
*pwd
= getpwuid( getuid() );
266 if (pwd
) home
= pwd
->pw_dir
;
268 if (!home
) fatal_error( "could not determine your home directory\n" );
269 if (home
[0] != '/') fatal_error( "your home directory %s is not an absolute path\n", home
);
270 config_dir
= build_path( home
, ".wine" );
274 static void init_paths( int argc
, char *argv
[], char *envp
[] )
278 __wine_main_argc
= main_argc
= argc
;
279 __wine_main_argv
= main_argv
= argv
;
280 __wine_main_environ
= main_envp
= envp
;
281 argv0
= strdup( argv
[0] );
283 if (!dladdr( init_paths
, &info
) || !(dll_dir
= realpath_dirname( info
.dli_fname
)))
284 fatal_error( "cannot get path to ntdll.so\n" );
286 if (!(build_dir
= remove_tail( dll_dir
, "/dlls/ntdll" )))
288 #if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
289 bin_dir
= realpath_dirname( "/proc/self/exe" );
290 #elif defined (__FreeBSD__) || defined(__DragonFly__)
291 bin_dir
= realpath_dirname( "/proc/curproc/file" );
293 bin_dir
= realpath_dirname( argv0
);
295 if (!bin_dir
) bin_dir
= build_path( dll_dir
, DLL_TO_BINDIR
);
296 data_dir
= build_path( bin_dir
, BIN_TO_DATADIR
);
303 #if !defined(__APPLE__) && !defined(__ANDROID__) /* these platforms always use UTF-8 */
305 /* charset to codepage map, sorted by name */
306 static const struct { const char *name
; UINT cp
; } charset_names
[] =
308 { "ANSIX341968", 20127 },
310 { "BIG5HKSCS", 950 },
326 { "GB18030", 936 /* 54936 */ },
348 { "ISO88591", 28591 },
349 { "ISO885913", 28603 },
350 { "ISO885915", 28605 },
351 { "ISO88592", 28592 },
352 { "ISO88593", 28593 },
353 { "ISO88594", 28594 },
354 { "ISO88595", 28595 },
355 { "ISO88596", 28596 },
356 { "ISO88597", 28597 },
357 { "ISO88598", 28598 },
358 { "ISO88599", 28599 },
365 static void load_unix_cptable( unsigned int cp
)
367 const char *dir
= build_dir
? build_dir
: data_dir
;
373 if (!(name
= malloc( strlen(dir
) + 22 ))) return;
374 sprintf( name
, "%s/nls/c_%03u.nls", dir
, cp
);
375 if ((fd
= open( name
, O_RDONLY
)) != -1)
378 if ((data
= malloc( st
.st_size
)) && st
.st_size
> 0x10000 &&
379 read( fd
, data
, st
.st_size
) == st
.st_size
)
381 RtlInitCodePageTable( data
, &unix_table
);
389 else ERR( "failed to load %s\n", name
);
393 static void init_unix_codepage(void)
395 char charset_name
[16];
398 int min
= 0, max
= ARRAY_SIZE(charset_names
) - 1;
400 setlocale( LC_CTYPE
, "" );
401 if (!(name
= nl_langinfo( CODESET
))) return;
403 /* remove punctuation characters from charset name */
404 for (i
= j
= 0; name
[i
] && j
< sizeof(charset_name
)-1; i
++)
406 if (name
[i
] >= '0' && name
[i
] <= '9') charset_name
[j
++] = name
[i
];
407 else if (name
[i
] >= 'A' && name
[i
] <= 'Z') charset_name
[j
++] = name
[i
];
408 else if (name
[i
] >= 'a' && name
[i
] <= 'z') charset_name
[j
++] = name
[i
] + ('A' - 'a');
414 int pos
= (min
+ max
) / 2;
415 int res
= strcmp( charset_names
[pos
].name
, charset_name
);
418 if (charset_names
[pos
].cp
!= CP_UTF8
) load_unix_cptable( charset_names
[pos
].cp
);
421 if (res
> 0) max
= pos
- 1;
424 ERR( "unrecognized charset '%s'\n", name
);
427 #else /* __APPLE__ || __ANDROID__ */
429 static void init_unix_codepage(void) { }
431 #endif /* __APPLE__ || __ANDROID__ */
434 /*********************************************************************
437 const char * CDECL
get_version(void)
439 return PACKAGE_VERSION
;
443 /*********************************************************************
446 const char * CDECL
get_build_id(void)
448 extern const char wine_build
[];
453 /*********************************************************************
456 void CDECL
get_host_version( const char **sysname
, const char **release
)
458 #ifdef HAVE_SYS_UTSNAME_H
459 static struct utsname buf
;
460 static BOOL init_done
;
467 if (sysname
) *sysname
= buf
.sysname
;
468 if (release
) *release
= buf
.release
;
470 if (sysname
) *sysname
= "";
471 if (release
) *release
= "";
476 /*************************************************************************
479 * Return the initial arguments.
481 static void CDECL
get_main_args( int *argc
, char **argv
[], char **envp
[] )
489 /*************************************************************************
492 * Return the various configuration paths.
494 static void CDECL
get_paths( const char **builddir
, const char **datadir
, const char **configdir
)
496 *builddir
= build_dir
;
498 *configdir
= config_dir
;
502 /*************************************************************************
505 * Return the various configuration paths.
507 static void CDECL
get_dll_path( const char ***paths
, SIZE_T
*maxlen
)
510 *maxlen
= dll_path_maxlen
;
514 /*************************************************************************
517 * Return the Unix codepage data.
519 static void CDECL
get_unix_codepage( CPTABLEINFO
*table
)
525 static void preloader_exec( char **argv
)
529 static const char *preloader
= "wine-preloader";
532 if (!(p
= strrchr( argv
[1], '/' ))) p
= argv
[1];
535 if (strlen(p
) > 2 && !strcmp( p
+ strlen(p
) - 2, "64" )) preloader
= "wine64-preloader";
536 argv
[0] = malloc( p
- argv
[1] + strlen(preloader
) + 1 );
537 memcpy( argv
[0], argv
[1], p
- argv
[1] );
538 strcpy( argv
[0] + (p
- argv
[1]), preloader
);
542 posix_spawnattr_t attr
;
543 posix_spawnattr_init( &attr
);
544 posix_spawnattr_setflags( &attr
, POSIX_SPAWN_SETEXEC
| _POSIX_SPAWN_DISABLE_ASLR
);
545 posix_spawn( NULL
, argv
[0], NULL
, &attr
, argv
, *_NSGetEnviron() );
546 posix_spawnattr_destroy( &attr
);
549 execv( argv
[0], argv
);
552 execv( argv
[1], argv
+ 1 );
555 static NTSTATUS
loader_exec( const char *loader
, char **argv
, int is_child_64bit
)
561 argv
[1] = build_path( build_dir
, is_child_64bit
? "loader/wine64" : "loader/wine" );
562 preloader_exec( argv
);
563 return STATUS_INVALID_IMAGE_FORMAT
;
566 if ((p
= strrchr( loader
, '/' ))) loader
= p
+ 1;
568 argv
[1] = build_path( bin_dir
, loader
);
569 preloader_exec( argv
);
571 argv
[1] = getenv( "WINELOADER" );
572 if (argv
[1]) preloader_exec( argv
);
574 if ((path
= getenv( "PATH" )))
576 for (p
= strtok( strdup( path
), ":" ); p
; p
= strtok( NULL
, ":" ))
578 argv
[1] = build_path( p
, loader
);
579 preloader_exec( argv
);
583 argv
[1] = build_path( BINDIR
, loader
);
584 preloader_exec( argv
);
585 return STATUS_INVALID_IMAGE_FORMAT
;
589 /***********************************************************************
592 * argv[0] and argv[1] must be reserved for the preloader and loader respectively.
594 static NTSTATUS CDECL
exec_wineloader( char **argv
, int socketfd
, int is_child_64bit
,
595 ULONGLONG res_start
, ULONGLONG res_end
)
597 const char *loader
= argv0
;
598 const char *loader_env
= getenv( "WINELOADER" );
599 char preloader_reserve
[64], socket_env
[64];
601 if (!is_win64
^ !is_child_64bit
)
603 /* remap WINELOADER to the alternate 32/64-bit version if necessary */
606 int len
= strlen( loader_env
);
607 char *env
= malloc( sizeof("WINELOADER=") + len
+ 2 );
609 if (!env
) return STATUS_NO_MEMORY
;
610 strcpy( env
, "WINELOADER=" );
611 strcat( env
, loader_env
);
618 len
+= sizeof("WINELOADER=") - 1;
619 if (!strcmp( env
+ len
- 2, "64" )) env
[len
- 2] = 0;
624 else loader
= is_child_64bit
? "wine64" : "wine";
627 signal( SIGPIPE
, SIG_DFL
);
629 sprintf( socket_env
, "WINESERVERSOCKET=%u", socketfd
);
630 sprintf( preloader_reserve
, "WINEPRELOADRESERVE=%x%08x-%x%08x",
631 (ULONG
)(res_start
>> 32), (ULONG
)res_start
, (ULONG
)(res_end
>> 32), (ULONG
)res_end
);
633 putenv( preloader_reserve
);
634 putenv( socket_env
);
636 return loader_exec( loader
, argv
, is_child_64bit
);
640 /***********************************************************************
643 * Exec a new wine server.
645 static void exec_wineserver( char **argv
)
651 if (!is_win64
) /* look for 64-bit server */
653 char *loader
= realpath_dirname( build_path( build_dir
, "loader/wine64" ));
656 argv
[0] = build_path( loader
, "../server/wineserver" );
657 execv( argv
[0], argv
);
660 argv
[0] = build_path( build_dir
, "server/wineserver" );
661 execv( argv
[0], argv
);
665 argv
[0] = build_path( bin_dir
, "wineserver" );
666 execv( argv
[0], argv
);
668 argv
[0] = getenv( "WINESERVER" );
669 if (argv
[0]) execv( argv
[0], argv
);
671 if ((path
= getenv( "PATH" )))
673 for (path
= strtok( strdup( path
), ":" ); path
; path
= strtok( NULL
, ":" ))
675 argv
[0] = build_path( path
, "wineserver" );
676 execvp( argv
[0], argv
);
680 argv
[0] = build_path( BINDIR
, "wineserver" );
681 execv( argv
[0], argv
);
685 /***********************************************************************
688 * Start a new wine server.
690 void start_server( BOOL debug
)
692 static BOOL started
; /* we only try once */
694 static char debug_flag
[] = "-d";
700 if (pid
== -1) fatal_error( "fork: %s", strerror(errno
) );
703 argv
[1] = debug
? debug_flag
: NULL
;
705 exec_wineserver( argv
);
706 fatal_error( "could not exec wineserver\n" );
708 waitpid( pid
, &status
, 0 );
709 status
= WIFEXITED(status
) ? WEXITSTATUS(status
) : 1;
710 if (status
== 2) return; /* server lock held by someone else, will retry later */
711 if (status
) exit(status
); /* server failed */
717 /*************************************************************************
720 * Map a builtin dll in memory and fixup RVAs.
722 static NTSTATUS CDECL
map_so_dll( const IMAGE_NT_HEADERS
*nt_descr
, HMODULE module
)
724 static const char builtin_signature
[32] = "Wine builtin DLL";
725 IMAGE_DATA_DIRECTORY
*dir
;
726 IMAGE_DOS_HEADER
*dos
;
727 IMAGE_NT_HEADERS
*nt
;
728 IMAGE_SECTION_HEADER
*sec
;
729 BYTE
*addr
= (BYTE
*)module
;
730 DWORD code_start
, code_end
, data_start
, data_end
, align_mask
;
731 int delta
, nb_sections
= 2; /* code + data */
733 DWORD size
= (sizeof(IMAGE_DOS_HEADER
)
734 + sizeof(builtin_signature
)
735 + sizeof(IMAGE_NT_HEADERS
)
736 + nb_sections
* sizeof(IMAGE_SECTION_HEADER
));
738 if (wine_anon_mmap( addr
, size
, PROT_READ
| PROT_WRITE
, MAP_FIXED
) != addr
) return STATUS_NO_MEMORY
;
740 dos
= (IMAGE_DOS_HEADER
*)addr
;
741 nt
= (IMAGE_NT_HEADERS
*)((BYTE
*)(dos
+ 1) + sizeof(builtin_signature
));
742 sec
= (IMAGE_SECTION_HEADER
*)(nt
+ 1);
744 /* build the DOS and NT headers */
746 dos
->e_magic
= IMAGE_DOS_SIGNATURE
;
749 dos
->e_cparhdr
= (sizeof(*dos
) + 0xf) / 0x10;
751 dos
->e_maxalloc
= 0xffff;
754 dos
->e_lfanew
= sizeof(*dos
) + sizeof(builtin_signature
);
758 delta
= (const BYTE
*)nt_descr
- addr
;
759 align_mask
= nt
->OptionalHeader
.SectionAlignment
- 1;
760 code_start
= (size
+ align_mask
) & ~align_mask
;
761 data_start
= delta
& ~align_mask
;
765 unsigned long data_size
;
766 /* need the mach_header, not the PE header, to give to getsegmentdata(3) */
768 code_end
= getsegmentdata(dli
.dli_fbase
, "__DATA", &data_size
) - addr
;
769 data_end
= (code_end
+ data_size
+ align_mask
) & ~align_mask
;
772 code_end
= data_start
;
773 data_end
= (nt
->OptionalHeader
.SizeOfImage
+ delta
+ align_mask
) & ~align_mask
;
776 fixup_rva_ptrs( &nt
->OptionalHeader
.AddressOfEntryPoint
, addr
, 1 );
778 nt
->FileHeader
.NumberOfSections
= nb_sections
;
779 nt
->OptionalHeader
.BaseOfCode
= code_start
;
781 nt
->OptionalHeader
.BaseOfData
= data_start
;
783 nt
->OptionalHeader
.SizeOfCode
= code_end
- code_start
;
784 nt
->OptionalHeader
.SizeOfInitializedData
= data_end
- data_start
;
785 nt
->OptionalHeader
.SizeOfUninitializedData
= 0;
786 nt
->OptionalHeader
.SizeOfImage
= data_end
;
787 nt
->OptionalHeader
.ImageBase
= (ULONG_PTR
)addr
;
789 /* build the code section */
791 memcpy( sec
->Name
, ".text", sizeof(".text") );
792 sec
->SizeOfRawData
= code_end
- code_start
;
793 sec
->Misc
.VirtualSize
= sec
->SizeOfRawData
;
794 sec
->VirtualAddress
= code_start
;
795 sec
->PointerToRawData
= code_start
;
796 sec
->Characteristics
= (IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_EXECUTE
| IMAGE_SCN_MEM_READ
);
799 /* build the data section */
801 memcpy( sec
->Name
, ".data", sizeof(".data") );
802 sec
->SizeOfRawData
= data_end
- data_start
;
803 sec
->Misc
.VirtualSize
= sec
->SizeOfRawData
;
804 sec
->VirtualAddress
= data_start
;
805 sec
->PointerToRawData
= data_start
;
806 sec
->Characteristics
= (IMAGE_SCN_CNT_INITIALIZED_DATA
|
807 IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_READ
);
810 for (i
= 0; i
< nt
->OptionalHeader
.NumberOfRvaAndSizes
; i
++)
811 fixup_rva_dwords( &nt
->OptionalHeader
.DataDirectory
[i
].VirtualAddress
, delta
, 1 );
813 /* build the import directory */
815 dir
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_IMPORT_DIRECTORY
];
818 IMAGE_IMPORT_DESCRIPTOR
*imports
= (IMAGE_IMPORT_DESCRIPTOR
*)(addr
+ dir
->VirtualAddress
);
820 while (imports
->Name
)
822 fixup_rva_dwords( &imports
->u
.OriginalFirstThunk
, delta
, 1 );
823 fixup_rva_dwords( &imports
->Name
, delta
, 1 );
824 fixup_rva_dwords( &imports
->FirstThunk
, delta
, 1 );
825 if (imports
->u
.OriginalFirstThunk
)
826 fixup_rva_names( (UINT_PTR
*)(addr
+ imports
->u
.OriginalFirstThunk
), delta
);
827 if (imports
->FirstThunk
)
828 fixup_rva_names( (UINT_PTR
*)(addr
+ imports
->FirstThunk
), delta
);
833 /* build the resource directory */
835 dir
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_RESOURCE_DIRECTORY
];
838 void *ptr
= addr
+ dir
->VirtualAddress
;
839 fixup_so_resources( ptr
, ptr
, delta
);
842 /* build the export directory */
844 dir
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_EXPORT_DIRECTORY
];
847 IMAGE_EXPORT_DIRECTORY
*exports
= (IMAGE_EXPORT_DIRECTORY
*)(addr
+ dir
->VirtualAddress
);
849 fixup_rva_dwords( &exports
->Name
, delta
, 1 );
850 fixup_rva_dwords( &exports
->AddressOfFunctions
, delta
, 1 );
851 fixup_rva_dwords( &exports
->AddressOfNames
, delta
, 1 );
852 fixup_rva_dwords( &exports
->AddressOfNameOrdinals
, delta
, 1 );
853 fixup_rva_dwords( (DWORD
*)(addr
+ exports
->AddressOfNames
), delta
, exports
->NumberOfNames
);
854 fixup_rva_ptrs( addr
+ exports
->AddressOfFunctions
, addr
, exports
->NumberOfFunctions
);
856 return STATUS_SUCCESS
;
859 static const IMAGE_EXPORT_DIRECTORY
*get_export_dir( HMODULE module
)
861 const IMAGE_DOS_HEADER
*dos
= (const IMAGE_DOS_HEADER
*)module
;
862 const IMAGE_NT_HEADERS
*nt
;
865 if (dos
->e_magic
!= IMAGE_DOS_SIGNATURE
) return NULL
;
866 nt
= (IMAGE_NT_HEADERS
*)((const BYTE
*)dos
+ dos
->e_lfanew
);
867 if (nt
->Signature
!= IMAGE_NT_SIGNATURE
) return NULL
;
868 addr
= nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_EXPORT_DIRECTORY
].VirtualAddress
;
869 if (!addr
) return NULL
;
870 return (IMAGE_EXPORT_DIRECTORY
*)((BYTE
*)module
+ addr
);
873 static ULONG_PTR
find_ordinal_export( HMODULE module
, const IMAGE_EXPORT_DIRECTORY
*exports
, DWORD ordinal
)
875 const DWORD
*functions
= (const DWORD
*)((BYTE
*)module
+ exports
->AddressOfFunctions
);
877 if (ordinal
>= exports
->NumberOfFunctions
) return 0;
878 if (!functions
[ordinal
]) return 0;
879 return (ULONG_PTR
)module
+ functions
[ordinal
];
882 static ULONG_PTR
find_named_export( HMODULE module
, const IMAGE_EXPORT_DIRECTORY
*exports
,
883 const IMAGE_IMPORT_BY_NAME
*name
)
885 const WORD
*ordinals
= (const WORD
*)((BYTE
*)module
+ exports
->AddressOfNameOrdinals
);
886 const DWORD
*names
= (const DWORD
*)((BYTE
*)module
+ exports
->AddressOfNames
);
887 int min
= 0, max
= exports
->NumberOfNames
- 1;
889 /* first check the hint */
890 if (name
->Hint
<= max
)
892 char *ename
= (char *)module
+ names
[name
->Hint
];
893 if (!strcmp( ename
, (char *)name
->Name
))
894 return find_ordinal_export( module
, exports
, ordinals
[name
->Hint
] );
897 /* then do a binary search */
900 int res
, pos
= (min
+ max
) / 2;
901 char *ename
= (char *)module
+ names
[pos
];
902 if (!(res
= strcmp( ename
, (char *)name
->Name
)))
903 return find_ordinal_export( module
, exports
, ordinals
[pos
] );
904 if (res
> 0) max
= pos
- 1;
910 static void fixup_ntdll_imports( const IMAGE_NT_HEADERS
*nt
, HMODULE ntdll_module
)
912 const IMAGE_EXPORT_DIRECTORY
*ntdll_exports
= get_export_dir( ntdll_module
);
913 const IMAGE_IMPORT_DESCRIPTOR
*descr
;
914 const IMAGE_THUNK_DATA
*import_list
;
915 IMAGE_THUNK_DATA
*thunk_list
;
917 assert( ntdll_exports
);
919 descr
= get_rva( nt
, nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_IMPORT_DIRECTORY
].VirtualAddress
);
922 /* ntdll must be the only import */
923 assert( !strcmp( get_rva( nt
, descr
->Name
), "ntdll.dll" ));
925 thunk_list
= get_rva( nt
, (DWORD
)descr
->FirstThunk
);
926 if (descr
->u
.OriginalFirstThunk
)
927 import_list
= get_rva( nt
, (DWORD
)descr
->u
.OriginalFirstThunk
);
929 import_list
= thunk_list
;
932 while (import_list
->u1
.Ordinal
)
934 if (IMAGE_SNAP_BY_ORDINAL( import_list
->u1
.Ordinal
))
936 int ordinal
= IMAGE_ORDINAL( import_list
->u1
.Ordinal
) - ntdll_exports
->Base
;
937 thunk_list
->u1
.Function
= find_ordinal_export( ntdll_module
, ntdll_exports
, ordinal
);
938 if (!thunk_list
->u1
.Function
) ERR( "ordinal %u not found\n", ordinal
);
940 else /* import by name */
942 IMAGE_IMPORT_BY_NAME
*pe_name
= get_rva( nt
, import_list
->u1
.AddressOfData
);
943 thunk_list
->u1
.Function
= find_named_export( ntdll_module
, ntdll_exports
, pe_name
);
944 if (!thunk_list
->u1
.Function
) ERR( "%s not found\n", pe_name
->Name
);
954 /***********************************************************************
957 static HMODULE
load_ntdll(void)
959 const IMAGE_NT_HEADERS
*nt
;
965 name
= build_path( dll_dir
, "ntdll.dll.so" );
966 if (!dladdr( load_ntdll
, &info
)) fatal_error( "cannot get path to ntdll.so\n" );
967 name
= malloc( strlen(info
.dli_fname
) + 5 );
968 strcpy( name
, info
.dli_fname
);
969 strcpy( name
+ strlen(info
.dli_fname
) - 3, ".dll.so" );
970 if (!(handle
= dlopen( name
, RTLD_NOW
))) fatal_error( "failed to load %s: %s\n", name
, dlerror() );
971 if (!(nt
= dlsym( handle
, "__wine_spec_nt_header" )))
972 fatal_error( "NT header not found in %s (too old?)\n", name
);
973 dll_dir
= realpath_dirname( name
);
975 module
= (HMODULE
)((nt
->OptionalHeader
.ImageBase
+ 0xffff) & ~0xffff);
976 map_so_dll( nt
, module
);
981 /***********************************************************************
984 static struct unix_funcs unix_funcs
=
986 NtAllocateVirtualMemory
,
987 NtAreMappedFilesTheSame
,
999 NtFlushVirtualMemory
,
1000 NtFreeVirtualMemory
,
1003 NtLockVirtualMemory
,
1010 NtProtectVirtualMemory
,
1017 NtQueryVirtualMemory
,
1018 NtReadVirtualMemory
,
1019 NtReleaseKeyedEvent
,
1028 NtSignalAndWaitForSingleObject
,
1029 NtUnlockVirtualMemory
,
1030 NtUnmapViewOfSection
,
1031 NtWaitForKeyedEvent
,
1032 NtWaitForMultipleObjects
,
1033 NtWaitForSingleObject
,
1034 NtWriteVirtualMemory
,
1045 virtual_map_section
,
1046 virtual_get_system_info
,
1047 virtual_create_builtin_view
,
1048 virtual_alloc_thread_stack
,
1049 virtual_handle_fault
,
1050 virtual_locked_server_call
,
1051 virtual_locked_read
,
1052 virtual_locked_pread
,
1053 virtual_locked_recvmsg
,
1054 virtual_is_valid_code_address
,
1055 virtual_handle_stack_fault
,
1056 virtual_check_buffer_for_read
,
1057 virtual_check_buffer_for_write
,
1058 virtual_uninterrupted_read_memory
,
1059 virtual_uninterrupted_write_memory
,
1060 virtual_set_force_exec
,
1061 virtual_release_address_space
,
1062 virtual_set_large_address_space
,
1069 get_thread_ldt_entry
,
1073 server_queue_process_apc
,
1076 server_fd_to_handle
,
1077 server_handle_to_fd
,
1080 server_init_process_done
,
1081 __wine_dbg_get_channel_flags
,
1089 struct apple_stack_info
1092 size_t desired_size
;
1095 static void *apple_wine_thread( void *arg
)
1097 __wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION
, &unix_funcs
);
1101 /***********************************************************************
1102 * apple_alloc_thread_stack
1104 * Callback for mmap_enum_reserved_areas to allocate space for
1105 * the secondary thread's stack.
1108 static int CDECL
apple_alloc_thread_stack( void *base
, size_t size
, void *arg
)
1110 struct apple_stack_info
*info
= arg
;
1112 /* For mysterious reasons, putting the thread stack at the very top
1113 * of the address space causes subsequent execs to fail, even on the
1114 * child side of a fork. Avoid the top 16MB. */
1115 char * const limit
= (char*)0xff000000;
1116 if ((char *)base
>= limit
) return 0;
1117 if (size
> limit
- (char*)base
)
1118 size
= limit
- (char*)base
;
1119 if (size
< info
->desired_size
) return 0;
1120 info
->stack
= wine_anon_mmap( (char *)base
+ size
- info
->desired_size
,
1121 info
->desired_size
, PROT_READ
|PROT_WRITE
, MAP_FIXED
);
1122 return (info
->stack
!= (void *)-1);
1126 /***********************************************************************
1127 * apple_create_wine_thread
1129 * Spin off a secondary thread to complete Wine initialization, leaving
1130 * the original thread for the Mac frameworks.
1132 * Invoked as a CFRunLoopSource perform callback.
1134 static void apple_create_wine_thread( void *arg
)
1138 pthread_attr_t attr
;
1140 if (!pthread_attr_init( &attr
))
1143 struct apple_stack_info info
;
1145 /* Try to put the new thread's stack in the reserved area. If this
1146 * fails, just let it go wherever. It'll be a waste of space, but we
1148 if (!pthread_attr_getstacksize( &attr
, &info
.desired_size
) &&
1149 mmap_enum_reserved_areas( apple_alloc_thread_stack
, &info
, 1 ))
1151 mmap_remove_reserved_area( info
.stack
, info
.desired_size
);
1152 pthread_attr_setstackaddr( &attr
, (char*)info
.stack
+ info
.desired_size
);
1156 if (!pthread_attr_setdetachstate( &attr
, PTHREAD_CREATE_JOINABLE
) &&
1157 !pthread_create( &thread
, &attr
, apple_wine_thread
, NULL
))
1160 pthread_attr_destroy( &attr
);
1162 if (!success
) exit(1);
1166 /***********************************************************************
1169 * Park the process's original thread in a Core Foundation run loop for
1170 * use by the Mac frameworks, especially receiving and handling
1171 * distributed notifications. Spin off a new thread for the rest of the
1172 * Wine initialization.
1174 static void apple_main_thread(void)
1176 CFRunLoopSourceContext source_context
= { 0 };
1177 CFRunLoopSourceRef source
;
1179 if (!pthread_main_np()) return;
1181 /* Multi-processing Services can get confused about the main thread if the
1182 * first time it's used is on a secondary thread. Use it here to make sure
1183 * that doesn't happen. */
1184 MPTaskIsPreemptive(MPCurrentTaskID());
1186 /* Give ourselves the best chance of having the distributed notification
1187 * center scheduled on this thread's run loop. In theory, it's scheduled
1188 * in the first thread to ask for it. */
1189 CFNotificationCenterGetDistributedCenter();
1191 /* We use this run loop source for two purposes. First, a run loop exits
1192 * if it has no more sources scheduled. So, we need at least one source
1193 * to keep the run loop running. Second, although it's not critical, it's
1194 * preferable for the Wine initialization to not proceed until we know
1195 * the run loop is running. So, we signal our source immediately after
1196 * adding it and have its callback spin off the Wine thread. */
1197 source_context
.perform
= apple_create_wine_thread
;
1198 source
= CFRunLoopSourceCreate( NULL
, 0, &source_context
);
1199 CFRunLoopAddSource( CFRunLoopGetCurrent(), source
, kCFRunLoopCommonModes
);
1200 CFRunLoopSourceSignal( source
);
1201 CFRelease( source
);
1202 CFRunLoopRun(); /* Should never return, except on error. */
1204 #endif /* __APPLE__ */
1209 static int pre_exec(void)
1211 #if defined(__i386__) || defined(__x86_64__)
1212 return 1; /* we have a preloader */
1214 return 0; /* no exec needed */
1218 #elif defined(__linux__) && (defined(__i386__) || defined(__arm__))
1220 static void check_vmsplit( void *stack
)
1222 if (stack
< (void *)0x80000000)
1224 /* if the stack is below 0x80000000, assume we can safely try a munmap there */
1225 if (munmap( (void *)0x80000000, 1 ) == -1 && errno
== EINVAL
)
1226 ERR( "Warning: memory above 0x80000000 doesn't seem to be accessible.\n"
1227 "Wine requires a 3G/1G user/kernel memory split to work properly.\n" );
1231 static int pre_exec(void)
1235 check_vmsplit( &temp
);
1237 return 1; /* we have a preloader on x86 */
1243 #elif defined(__linux__) && (defined(__x86_64__) || defined(__aarch64__))
1245 static int pre_exec(void)
1247 return 1; /* we have a preloader on x86-64/arm64 */
1250 #elif defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
1252 static int pre_exec(void)
1254 return 1; /* we have a preloader */
1257 #elif (defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__DragonFly__))
1259 static int pre_exec(void)
1263 rl
.rlim_cur
= 0x02000000;
1264 rl
.rlim_max
= 0x02000000;
1265 setrlimit( RLIMIT_DATA
, &rl
);
1271 static int pre_exec(void)
1273 return 0; /* no exec needed */
1279 /***********************************************************************
1282 * Change the process name in the ps output.
1284 static void set_process_name( int argc
, char *argv
[] )
1290 #ifdef HAVE_SETPROCTITLE
1291 setproctitle("-%s", argv
[1]);
1292 shift_strings
= FALSE
;
1296 shift_strings
= (argc
>= 2);
1297 for (i
= 1; i
< argc
; i
++)
1302 shift_strings
= FALSE
;
1310 int offset
= argv
[1] - argv
[0];
1311 char *end
= argv
[argc
-1] + strlen(argv
[argc
-1]) + 1;
1312 memmove( argv
[0], argv
[1], end
- argv
[1] );
1313 memset( end
- offset
, 0, offset
);
1314 for (i
= 1; i
< argc
; i
++)
1315 argv
[i
-1] = argv
[i
] - offset
;
1320 /* remove argv[0] */
1321 memmove( argv
, argv
+ 1, argc
* sizeof(argv
[0]) );
1325 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
1326 if ((p
= strrchr( name
, '/' ))) name
= p
+ 1;
1328 #if defined(HAVE_SETPROGNAME)
1329 setprogname( name
);
1334 # define PR_SET_NAME 15
1336 prctl( PR_SET_NAME
, name
);
1337 #endif /* HAVE_PRCTL */
1341 /***********************************************************************
1342 * check_command_line
1344 * Check if command line is one that needs to be handled specially.
1346 static void check_command_line( int argc
, char *argv
[] )
1348 static const char usage
[] =
1349 "Usage: wine PROGRAM [ARGUMENTS...] Run the specified program\n"
1350 " wine --help Display this help and exit\n"
1351 " wine --version Output version information and exit";
1355 fprintf( stderr
, "%s\n", usage
);
1358 if (!strcmp( argv
[1], "--help" ))
1360 printf( "%s\n", usage
);
1363 if (!strcmp( argv
[1], "--version" ))
1365 printf( "%s\n", get_build_id() );
1371 /***********************************************************************
1374 * Main entry point called by the wine loader.
1376 void __wine_main( int argc
, char *argv
[], char *envp
[] )
1380 init_paths( argc
, argv
, envp
);
1382 if (!getenv( "WINELOADERNOEXEC" )) /* first time around */
1384 static char noexec
[] = "WINELOADERNOEXEC=1";
1387 check_command_line( argc
, argv
);
1390 char **new_argv
= malloc( (argc
+ 2) * sizeof(*argv
) );
1391 memcpy( new_argv
+ 1, argv
, (argc
+ 1) * sizeof(*argv
) );
1392 loader_exec( argv0
, new_argv
, is_win64
);
1393 fatal_error( "could not exec the wine loader\n" );
1397 #ifdef RLIMIT_NOFILE
1398 set_max_limit( RLIMIT_NOFILE
);
1401 set_max_limit( RLIMIT_AS
);
1406 module
= load_ntdll();
1407 fixup_ntdll_imports( &__wine_spec_nt_header
, module
);
1409 set_process_name( argc
, argv
);
1410 init_unix_codepage();
1413 apple_main_thread();
1415 __wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION
, &unix_funcs
);
1419 static int add_area( void *base
, size_t size
, void *arg
)
1421 mmap_add_reserved_area( base
, size
);
1425 /***********************************************************************
1426 * __wine_init_unix_lib
1428 * Lib entry point called by ntdll.dll.so if not yet initialized.
1430 NTSTATUS __cdecl
__wine_init_unix_lib( HMODULE module
, const void *ptr_in
, void *ptr_out
)
1432 const IMAGE_NT_HEADERS
*nt
= ptr_in
;
1435 extern char **__wine_get_main_environment(void);
1436 char **envp
= __wine_get_main_environment();
1438 char **envp
= __wine_main_environ
;
1440 init_paths( __wine_main_argc
, __wine_main_argv
, envp
);
1442 map_so_dll( nt
, module
);
1443 fixup_ntdll_imports( &__wine_spec_nt_header
, module
);
1444 set_process_name( __wine_main_argc
, __wine_main_argv
);
1445 init_unix_codepage();
1446 *(struct unix_funcs
**)ptr_out
= &unix_funcs
;
1447 wine_mmap_enum_reserved_areas( add_area
, NULL
, 0 );
1448 return STATUS_SUCCESS
;
1451 BOOL WINAPI DECLSPEC_HIDDEN
DllMain( HINSTANCE inst
, DWORD reason
, LPVOID reserved
)
1453 if (reason
== DLL_PROCESS_ATTACH
) LdrDisableThreadCalloutsForDll( inst
);