Remove the dummy pthread functions and use -lpthread instead to
[wine] / libs / wine / loader.c
1 /*
2  * Win32 builtin dlls support
3  *
4  * Copyright 2000 Alexandre Julliard
5  *
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.
10  *
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.
15  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <ctype.h>
26 #include <fcntl.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #ifdef HAVE_SYS_MMAN_H
31 #include <sys/mman.h>
32 #endif
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif
36 #ifdef HAVE_STDINT_H
37 # include <stdint.h>
38 #endif
39
40 #define NONAMELESSUNION
41 #define NONAMELESSSTRUCT
42 #include "windef.h"
43 #include "wine/library.h"
44
45 /* argc/argv for the Windows application */
46 int __wine_main_argc = 0;
47 char **__wine_main_argv = NULL;
48 WCHAR **__wine_main_wargv = NULL;
49
50 #define MAX_DLLS 100
51
52 static struct
53 {
54     const IMAGE_NT_HEADERS *nt;           /* NT header */
55     const char             *filename;     /* DLL file name */
56 } builtin_dlls[MAX_DLLS];
57
58 static int nb_dlls;
59
60 static const IMAGE_NT_HEADERS *main_exe;
61
62 static load_dll_callback_t load_dll_callback;
63
64 static const char **dll_paths;
65 static int nb_dll_paths;
66 static int dll_path_maxlen;
67 static int init_done;
68
69
70 /* build the dll load path from the WINEDLLPATH variable */
71 static void build_dll_path(void)
72 {
73     static const char * const dlldir = DLLDIR;
74     int len, count = 0;
75     char *p, *path = getenv( "WINEDLLPATH" );
76
77     init_done = 1;
78
79     if (path)
80     {
81         /* count how many path elements we need */
82         path = strdup(path);
83         p = path;
84         while (*p)
85         {
86             while (*p == ':') p++;
87             if (!*p) break;
88             count++;
89             while (*p && *p != ':') p++;
90         }
91     }
92
93     dll_paths = malloc( (count+1) * sizeof(*dll_paths) );
94
95     if (count)
96     {
97         p = path;
98         nb_dll_paths = 0;
99         while (*p)
100         {
101             while (*p == ':') *p++ = 0;
102             if (!*p) break;
103             dll_paths[nb_dll_paths] = p;
104             while (*p && *p != ':') p++;
105             if (p - dll_paths[nb_dll_paths] > dll_path_maxlen)
106                 dll_path_maxlen = p - dll_paths[nb_dll_paths];
107             nb_dll_paths++;
108         }
109     }
110
111     /* append default dll dir (if not empty) to path */
112     if ((len = strlen(dlldir)))
113     {
114         if (len > dll_path_maxlen) dll_path_maxlen = len;
115         dll_paths[nb_dll_paths++] = dlldir;
116     }
117 }
118
119 /* check if a given file can be opened */
120 inline static int file_exists( const char *name )
121 {
122     int fd = open( name, O_RDONLY );
123     if (fd != -1) close( fd );
124     return (fd != -1);
125 }
126
127 /* open a library for a given dll, searching in the dll path
128  * 'name' must be the Windows dll name (e.g. "kernel32.dll") */
129 static void *dlopen_dll( const char *name, char *error, int errorsize,
130                          int test_only, int *exists )
131 {
132     int i, namelen = strlen(name);
133     char *buffer, *p;
134     void *ret = NULL;
135
136     if (!init_done) build_dll_path();
137
138     buffer = malloc( dll_path_maxlen + namelen + 5 );
139
140     /* store the name at the end of the buffer, followed by .so */
141     p = buffer + dll_path_maxlen;
142     *p++ = '/';
143     memcpy( p, name, namelen );
144     strcpy( p + namelen, ".so" );
145     *exists = 0;
146
147     for (i = 0; i < nb_dll_paths; i++)
148     {
149         int len = strlen(dll_paths[i]);
150         p = buffer + dll_path_maxlen - len;
151         memcpy( p, dll_paths[i], len );
152         if (!test_only && (ret = wine_dlopen( p, RTLD_NOW, error, errorsize ))) break;
153         if ((*exists = file_exists( p ))) break; /* exists but cannot be loaded, return the error */
154     }
155     free( buffer );
156     return ret;
157 }
158
159
160 /* adjust an array of pointers to make them into RVAs */
161 static inline void fixup_rva_ptrs( void *array, void *base, int count )
162 {
163     void **ptr = (void **)array;
164     while (count--)
165     {
166         if (*ptr) *ptr = (void *)((char *)*ptr - (char *)base);
167         ptr++;
168     }
169 }
170
171
172 /* fixup RVAs in the import directory */
173 static void fixup_imports( IMAGE_IMPORT_DESCRIPTOR *dir, DWORD size, void *base )
174 {
175     int count = size / sizeof(void *);
176     void **ptr = (void **)dir;
177
178     /* everything is either a pointer or a ordinal value below 0x10000 */
179     while (count--)
180     {
181         if (*ptr >= (void *)0x10000) *ptr = (void *)((char *)*ptr - (char *)base);
182         else if (*ptr) *ptr = (void *)(0x80000000 | (unsigned int)*ptr);
183         ptr++;
184     }
185 }
186
187
188 /* fixup RVAs in the resource directory */
189 static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, char *root, void *base )
190 {
191     IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
192     int i;
193
194     entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
195     for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++)
196     {
197         void *ptr = root + entry->u2.s3.OffsetToDirectory;
198         if (entry->u2.s3.DataIsDirectory) fixup_resources( ptr, root, base );
199         else
200         {
201             IMAGE_RESOURCE_DATA_ENTRY *data = ptr;
202             fixup_rva_ptrs( &data->OffsetToData, base, 1 );
203         }
204     }
205 }
206
207
208 /* map a builtin dll in memory and fixup RVAs */
209 static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
210 {
211 #ifdef HAVE_MMAP
212     IMAGE_DATA_DIRECTORY *dir;
213     IMAGE_DOS_HEADER *dos;
214     IMAGE_NT_HEADERS *nt;
215     IMAGE_SECTION_HEADER *sec;
216     BYTE *addr, *code_start, *data_start;
217     size_t page_size = getpagesize();
218     int nb_sections = 2;  /* code + data */
219
220     size_t size = (sizeof(IMAGE_DOS_HEADER)
221                    + sizeof(IMAGE_NT_HEADERS)
222                    + nb_sections * sizeof(IMAGE_SECTION_HEADER));
223
224     assert( size <= page_size );
225
226     /* module address must be aligned on 64K boundary */
227     addr = (BYTE *)((nt_descr->OptionalHeader.ImageBase + 0xffff) & ~0xffff);
228     if (wine_anon_mmap( addr, page_size, PROT_READ|PROT_WRITE, MAP_FIXED ) != addr) return NULL;
229
230     dos    = (IMAGE_DOS_HEADER *)addr;
231     nt     = (IMAGE_NT_HEADERS *)(dos + 1);
232     sec    = (IMAGE_SECTION_HEADER *)(nt + 1);
233     code_start = addr + page_size;
234
235     /* HACK! */
236     data_start = code_start + page_size;
237
238     /* Build the DOS and NT headers */
239
240     dos->e_magic  = IMAGE_DOS_SIGNATURE;
241     dos->e_lfanew = sizeof(*dos);
242
243     *nt = *nt_descr;
244
245     nt->FileHeader.NumberOfSections                = nb_sections;
246     nt->OptionalHeader.SizeOfCode                  = data_start - code_start;
247     nt->OptionalHeader.SizeOfInitializedData       = 0;
248     nt->OptionalHeader.SizeOfUninitializedData     = 0;
249     nt->OptionalHeader.ImageBase                   = (DWORD)addr;
250
251     fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
252
253     /* Build the code section */
254
255     strcpy( sec->Name, ".text" );
256     sec->SizeOfRawData = data_start - code_start;
257     sec->Misc.VirtualSize = sec->SizeOfRawData;
258     sec->VirtualAddress   = code_start - addr;
259     sec->PointerToRawData = code_start - addr;
260     sec->Characteristics  = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
261     sec++;
262
263     /* Build the data section */
264
265     strcpy( sec->Name, ".data" );
266     sec->SizeOfRawData = 0;
267     sec->Misc.VirtualSize = sec->SizeOfRawData;
268     sec->VirtualAddress   = data_start - addr;
269     sec->PointerToRawData = data_start - addr;
270     sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA |
271                              IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ);
272     sec++;
273
274     /* Build the import directory */
275
276     dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
277     if (dir->Size)
278     {
279         IMAGE_IMPORT_DESCRIPTOR *imports = (void *)dir->VirtualAddress;
280         fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
281         fixup_imports( imports, dir->Size, addr );
282     }
283
284     /* Build the resource directory */
285
286     dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
287     if (dir->Size)
288     {
289         void *ptr = (void *)dir->VirtualAddress;
290         fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
291         fixup_resources( ptr, ptr, addr );
292     }
293
294     /* Build the export directory */
295
296     dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
297     if (dir->Size)
298     {
299         IMAGE_EXPORT_DIRECTORY *exports = (void *)dir->VirtualAddress;
300         fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
301         fixup_rva_ptrs( (void *)exports->AddressOfFunctions, addr, exports->NumberOfFunctions );
302         fixup_rva_ptrs( (void *)exports->AddressOfNames, addr, exports->NumberOfNames );
303         fixup_rva_ptrs( &exports->Name, addr, 1 );
304         fixup_rva_ptrs( &exports->AddressOfFunctions, addr, 1 );
305         fixup_rva_ptrs( &exports->AddressOfNames, addr, 1 );
306         fixup_rva_ptrs( &exports->AddressOfNameOrdinals, addr, 1 );
307     }
308     return addr;
309 #else  /* HAVE_MMAP */
310     return NULL;
311 #endif  /* HAVE_MMAP */
312 }
313
314
315 /***********************************************************************
316  *           __wine_dll_register
317  *
318  * Register a built-in DLL descriptor.
319  */
320 void __wine_dll_register( const IMAGE_NT_HEADERS *header, const char *filename )
321 {
322     if (load_dll_callback) load_dll_callback( map_dll(header), filename );
323     else
324     {
325         if (!(header->FileHeader.Characteristics & IMAGE_FILE_DLL))
326             main_exe = header;
327         else
328         {
329             assert( nb_dlls < MAX_DLLS );
330             builtin_dlls[nb_dlls].nt = header;
331             builtin_dlls[nb_dlls].filename = filename;
332             nb_dlls++;
333         }
334     }
335 }
336
337
338 /***********************************************************************
339  *           wine_dll_set_callback
340  *
341  * Set the callback function for dll loading, and call it
342  * for all dlls that were implicitly loaded already.
343  */
344 void wine_dll_set_callback( load_dll_callback_t load )
345 {
346     int i;
347     load_dll_callback = load;
348     for (i = 0; i < nb_dlls; i++)
349     {
350         const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
351         if (!nt) continue;
352         builtin_dlls[i].nt = NULL;
353         load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
354     }
355     nb_dlls = 0;
356     if (main_exe) load_dll_callback( map_dll(main_exe), "" );
357 }
358
359
360 /***********************************************************************
361  *           wine_dll_load
362  *
363  * Load a builtin dll.
364  */
365 void *wine_dll_load( const char *filename, char *error, int errorsize, int *file_exists )
366 {
367     int i;
368
369     /* callback must have been set already */
370     assert( load_dll_callback );
371
372     /* check if we have it in the list */
373     /* this can happen when initializing pre-loaded dlls in wine_dll_set_callback */
374     for (i = 0; i < nb_dlls; i++)
375     {
376         if (!builtin_dlls[i].nt) continue;
377         if (!strcmp( builtin_dlls[i].filename, filename ))
378         {
379             const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
380             builtin_dlls[i].nt = NULL;
381             load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
382             *file_exists = 1;
383             return (void *)1;
384         }
385     }
386     return dlopen_dll( filename, error, errorsize, 0, file_exists );
387 }
388
389
390 /***********************************************************************
391  *           wine_dll_unload
392  *
393  * Unload a builtin dll.
394  */
395 void wine_dll_unload( void *handle )
396 {
397     if (handle != (void *)1)
398         wine_dlclose( handle, NULL, 0 );
399 }
400
401
402 /***********************************************************************
403  *           wine_dll_load_main_exe
404  *
405  * Try to load the .so for the main exe.
406  */
407 void *wine_dll_load_main_exe( const char *name, char *error, int errorsize,
408                               int test_only, int *file_exists )
409 {
410     return dlopen_dll( name, error, errorsize, test_only, file_exists );
411 }
412
413
414 /***********************************************************************
415  *           wine_init
416  *
417  * Main Wine initialisation.
418  */
419 void wine_init( int argc, char *argv[], char *error, int error_size )
420 {
421     int file_exists;
422     void *ntdll;
423     void (*init_func)(int, char **);
424
425     if (!(ntdll = dlopen_dll( "ntdll.dll", error, error_size, 0, &file_exists ))) return;
426     if (!(init_func = wine_dlsym( ntdll, "__wine_process_init", error, error_size ))) return;
427     init_func( argc, argv );
428 }
429
430
431 #if defined(__svr4__) || defined(__NetBSD__)
432 /***********************************************************************
433  *             try_mmap_fixed
434  *
435  * The purpose of this routine is to emulate the behaviour of
436  * the Linux mmap() routine if a non-NULL address is passed,
437  * but the MAP_FIXED flag is not set.  Linux in this case tries
438  * to place the mapping at the specified address, *unless* the
439  * range is already in use.  Solaris, however, completely ignores
440  * the address argument in this case.
441  *
442  * As Wine code occasionally relies on the Linux behaviour, e.g. to
443  * be able to map non-relocateable PE executables to their proper
444  * start addresses, or to map the DOS memory to 0, this routine
445  * emulates the Linux behaviour by checking whether the desired
446  * address range is still available, and placing the mapping there
447  * using MAP_FIXED if so.
448  */
449 static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
450                            int fildes, off_t off)
451 {
452     char * volatile result = NULL;
453     int pagesize = getpagesize();
454     pid_t pid;
455
456     /* We only try to map to a fixed address if
457        addr is non-NULL and properly aligned,
458        and MAP_FIXED isn't already specified. */
459
460     if ( !addr )
461         return 0;
462     if ( (uintptr_t)addr & (pagesize-1) )
463         return 0;
464     if ( flags & MAP_FIXED )
465         return 0;
466
467     /* We use vfork() to freeze all threads of the
468        current process.  This allows us to check without
469        race condition whether the desired memory range is
470        already in use.  Note that because vfork() shares
471        the address spaces between parent and child, we
472        can actually perform the mapping in the child. */
473
474     if ( (pid = vfork()) == -1 )
475     {
476         perror("try_mmap_fixed: vfork");
477         exit(1);
478     }
479     if ( pid == 0 )
480     {
481         int i;
482         char vec;
483
484         /* We call mincore() for every page in the desired range.
485            If any of these calls succeeds, the page is already
486            mapped and we must fail. */
487         for ( i = 0; i < len; i += pagesize )
488             if ( mincore( (caddr_t)addr + i, pagesize, &vec ) != -1 )
489                _exit(1);
490
491         /* Perform the mapping with MAP_FIXED set.  This is safe
492            now, as none of the pages is currently in use. */
493         result = mmap( addr, len, prot, flags | MAP_FIXED, fildes, off );
494         if ( result == addr )
495             _exit(0);
496
497         if ( result != (void *) -1 ) /* This should never happen ... */
498             munmap( result, len );
499
500        _exit(1);
501     }
502
503     /* vfork() lets the parent continue only after the child
504        has exited.  Furthermore, Wine sets SIGCHLD to SIG_IGN,
505        so we don't need to wait for the child. */
506
507     return result == addr;
508 }
509 #endif  /* __svr4__ || __NetBSD__ */
510
511
512 /***********************************************************************
513  *              wine_anon_mmap
514  *
515  * Portable wrapper for anonymous mmaps
516  */
517 void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
518 {
519 #ifdef HAVE_MMAP
520     static int fdzero = -1;
521
522 #ifdef MAP_ANON
523     flags |= MAP_ANON;
524 #else
525     if (fdzero == -1)
526     {
527         if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
528         {
529             perror( "/dev/zero: open" );
530             exit(1);
531         }
532     }
533 #endif  /* MAP_ANON */
534
535 #ifdef MAP_SHARED
536     flags &= ~MAP_SHARED;
537 #endif
538
539     /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
540 #ifdef MAP_PRIVATE
541     flags |= MAP_PRIVATE;
542 #endif
543
544 #if defined(__svr4__) || defined(__NetBSD__)
545     if ( try_mmap_fixed( start, size, prot, flags, fdzero, 0 ) )
546         return start;
547 #endif
548
549     return mmap( start, size, prot, flags, fdzero, 0 );
550 #else
551     return (void *)-1;
552 #endif
553 }
554
555
556 /*
557  * These functions provide wrappers around dlopen() and associated
558  * functions.  They work around a bug in glibc 2.1.x where calling
559  * a dl*() function after a previous dl*() function has failed
560  * without a dlerror() call between the two will cause a crash.
561  * They all take a pointer to a buffer that
562  * will receive the error description (from dlerror()).  This
563  * parameter may be NULL if the error description is not required.
564  */
565
566 /***********************************************************************
567  *              wine_dlopen
568  */
569 void *wine_dlopen( const char *filename, int flag, char *error, int errorsize )
570 {
571 #ifdef HAVE_DLOPEN
572     void *ret;
573     const char *s;
574     dlerror(); dlerror();
575     ret = dlopen( filename, flag );
576     s = dlerror();
577     if (error)
578     {
579         strncpy( error, s ? s : "", errorsize );
580         error[errorsize - 1] = '\0';
581     }
582     dlerror();
583     return ret;
584 #else
585     if (error)
586     {
587         strncpy( error, "dlopen interface not detected by configure", errorsize );
588         error[errorsize - 1] = '\0';
589     }
590     return NULL;
591 #endif
592 }
593
594 /***********************************************************************
595  *              wine_dlsym
596  */
597 void *wine_dlsym( void *handle, const char *symbol, char *error, int errorsize )
598 {
599 #ifdef HAVE_DLOPEN
600     void *ret;
601     const char *s;
602     dlerror(); dlerror();
603     ret = dlsym( handle, symbol );
604     s = dlerror();
605     if (error)
606     {
607         strncpy( error, s ? s : "", errorsize );
608         error[errorsize - 1] = '\0';
609     }
610     dlerror();
611     return ret;
612 #else
613     if (error)
614     {
615         strncpy( error, "dlopen interface not detected by configure", errorsize );
616         error[errorsize - 1] = '\0';
617     }
618     return NULL;
619 #endif
620 }
621
622 /***********************************************************************
623  *              wine_dlclose
624  */
625 int wine_dlclose( void *handle, char *error, int errorsize )
626 {
627 #ifdef HAVE_DLOPEN
628     int ret;
629     const char *s;
630     dlerror(); dlerror();
631     ret = dlclose( handle );
632     s = dlerror();
633     if (error)
634     {
635         strncpy( error, s ? s : "", errorsize );
636         error[errorsize - 1] = '\0';
637     }
638     dlerror();
639     return ret;
640 #else
641     if (error)
642     {
643         strncpy( error, "dlopen interface not detected by configure", errorsize );
644         error[errorsize - 1] = '\0';
645     }
646     return 1;
647 #endif
648 }