loader.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include "config.h"
  21. #include <assert.h>
  22. #include <ctype.h>
  23. #include <fcntl.h>
  24. #include <limits.h>
  25. #include <stdarg.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <sys/types.h>
  29. #include <sys/mman.h>
  30. #ifdef HAVE_SYS_RESOURCE_H
  31. # include <sys/resource.h>
  32. #endif
  33. #include <unistd.h>
  34. #include <dlfcn.h>
  35. #ifdef __APPLE__
  36. #include <crt_externs.h>
  37. #define environ (*_NSGetEnviron())
  38. #include <CoreFoundation/CoreFoundation.h>
  39. #define LoadResource MacLoadResource
  40. #define GetCurrentThread MacGetCurrentThread
  41. #include <CoreServices/CoreServices.h>
  42. #undef LoadResource
  43. #undef GetCurrentThread
  44. #include <pthread.h>
  45. #include <mach-o/getsect.h>
  46. #else
  47. extern char **environ;
  48. #endif
  49. #define NONAMELESSUNION
  50. #define NONAMELESSSTRUCT
  51. #include "windef.h"
  52. #include "winbase.h"
  53. #include "wine/asm.h"
  54. /* argc/argv for the Windows application */
  55. int __wine_main_argc = 0;
  56. char **__wine_main_argv = NULL;
  57. WCHAR **__wine_main_wargv = NULL;
  58. char **__wine_main_environ = NULL;
  59. #define MAX_DLLS 100
  60. static struct
  61. {
  62. const IMAGE_NT_HEADERS *nt; /* NT header */
  63. const char *filename; /* DLL file name */
  64. } builtin_dlls[MAX_DLLS];
  65. static int nb_dlls;
  66. static const IMAGE_NT_HEADERS *main_exe;
  67. typedef void (*load_dll_callback_t)( void *, const char * );
  68. static load_dll_callback_t load_dll_callback;
  69. extern void *wine_anon_mmap( void *start, size_t size, int prot, int flags );
  70. #ifdef __ASM_OBSOLETE
  71. struct dll_path_context
  72. {
  73. unsigned int index; /* current index in the dll path list */
  74. char *buffer; /* buffer used for storing path names */
  75. char *name; /* start of file name part in buffer (including leading slash) */
  76. int namelen; /* length of file name without .so extension */
  77. int win16; /* 16-bit dll search */
  78. };
  79. static const char *default_dlldir;
  80. static const char **dll_paths;
  81. static unsigned int nb_dll_paths;
  82. static int dll_path_maxlen;
  83. extern const char *build_dir;
  84. extern void wine_init_argv0_path_obsolete( const char *argv0 );
  85. extern void mmap_init(void);
  86. extern const char *get_dlldir( const char **default_dlldir );
  87. /* build the dll load path from the WINEDLLPATH variable */
  88. static void build_dll_path(void)
  89. {
  90. int len, count = 0;
  91. char *p, *path = getenv( "WINEDLLPATH" );
  92. const char *dlldir = get_dlldir( &default_dlldir );
  93. if (path)
  94. {
  95. /* count how many path elements we need */
  96. path = strdup(path);
  97. p = path;
  98. while (*p)
  99. {
  100. while (*p == ':') p++;
  101. if (!*p) break;
  102. count++;
  103. while (*p && *p != ':') p++;
  104. }
  105. }
  106. dll_paths = malloc( (count+2) * sizeof(*dll_paths) );
  107. nb_dll_paths = 0;
  108. if (dlldir)
  109. {
  110. dll_path_maxlen = strlen(dlldir);
  111. dll_paths[nb_dll_paths++] = dlldir;
  112. }
  113. else if (build_dir)
  114. {
  115. dll_path_maxlen = strlen(build_dir) + sizeof("/programs");
  116. }
  117. if (count)
  118. {
  119. p = path;
  120. while (*p)
  121. {
  122. while (*p == ':') *p++ = 0;
  123. if (!*p) break;
  124. dll_paths[nb_dll_paths] = p;
  125. while (*p && *p != ':') p++;
  126. if (p - dll_paths[nb_dll_paths] > dll_path_maxlen)
  127. dll_path_maxlen = p - dll_paths[nb_dll_paths];
  128. nb_dll_paths++;
  129. }
  130. }
  131. /* append default dll dir (if not empty) to path */
  132. if ((len = strlen(default_dlldir)) > 0)
  133. {
  134. if (len > dll_path_maxlen) dll_path_maxlen = len;
  135. dll_paths[nb_dll_paths++] = default_dlldir;
  136. }
  137. }
  138. static inline char *prepend( char *buffer, const char *str, size_t len )
  139. {
  140. return memcpy( buffer - len, str, len );
  141. }
  142. /* get a filename from the next entry in the dll path */
  143. static char *next_dll_path( struct dll_path_context *context )
  144. {
  145. unsigned int index = context->index++;
  146. int namelen = context->namelen;
  147. char *path = context->name;
  148. switch(index)
  149. {
  150. case 0: /* try dlls dir with subdir prefix */
  151. if (namelen > 4 && !memcmp( context->name + namelen - 4, ".dll", 4 )) namelen -= 4;
  152. if (!context->win16) path = prepend( path, context->name, namelen );
  153. path = prepend( path, "/dlls", sizeof("/dlls") - 1 );
  154. path = prepend( path, build_dir, strlen(build_dir) );
  155. return path;
  156. case 1: /* try programs dir with subdir prefix */
  157. if (!context->win16)
  158. {
  159. if (namelen > 4 && !memcmp( context->name + namelen - 4, ".exe", 4 )) namelen -= 4;
  160. path = prepend( path, context->name, namelen );
  161. path = prepend( path, "/programs", sizeof("/programs") - 1 );
  162. path = prepend( path, build_dir, strlen(build_dir) );
  163. return path;
  164. }
  165. context->index++;
  166. /* fall through */
  167. default:
  168. index -= 2;
  169. if (index >= nb_dll_paths) return NULL;
  170. path = prepend( path, dll_paths[index], strlen( dll_paths[index] ));
  171. return path;
  172. }
  173. }
  174. /* get a filename from the first entry in the dll path */
  175. static char *first_dll_path( const char *name, int win16, struct dll_path_context *context )
  176. {
  177. char *p;
  178. int namelen = strlen( name );
  179. const char *ext = win16 ? "16" : ".so";
  180. context->buffer = malloc( dll_path_maxlen + 2 * namelen + strlen(ext) + 3 );
  181. context->index = build_dir ? 0 : 2; /* if no build dir skip all the build dir magic cases */
  182. context->name = context->buffer + dll_path_maxlen + namelen + 1;
  183. context->namelen = namelen + 1;
  184. context->win16 = win16;
  185. /* store the name at the end of the buffer, followed by extension */
  186. p = context->name;
  187. *p++ = '/';
  188. memcpy( p, name, namelen );
  189. strcpy( p + namelen, ext );
  190. return next_dll_path( context );
  191. }
  192. /* free the dll path context created by first_dll_path */
  193. static inline void free_dll_path( struct dll_path_context *context )
  194. {
  195. free( context->buffer );
  196. }
  197. #endif /* __ASM_OBSOLETE */
  198. /* adjust an array of pointers to make them into RVAs */
  199. static inline void fixup_rva_ptrs( void *array, BYTE *base, unsigned int count )
  200. {
  201. void **src = (void **)array;
  202. DWORD *dst = (DWORD *)array;
  203. while (count--)
  204. {
  205. *dst++ = *src ? (BYTE *)*src - base : 0;
  206. src++;
  207. }
  208. }
  209. /* fixup an array of RVAs by adding the specified delta */
  210. static inline void fixup_rva_dwords( DWORD *ptr, int delta, unsigned int count )
  211. {
  212. while (count--)
  213. {
  214. if (*ptr) *ptr += delta;
  215. ptr++;
  216. }
  217. }
  218. /* fixup an array of name/ordinal RVAs by adding the specified delta */
  219. static inline void fixup_rva_names( UINT_PTR *ptr, int delta )
  220. {
  221. while (*ptr)
  222. {
  223. if (!(*ptr & IMAGE_ORDINAL_FLAG)) *ptr += delta;
  224. ptr++;
  225. }
  226. }
  227. /* fixup RVAs in the import directory */
  228. static void fixup_imports( IMAGE_IMPORT_DESCRIPTOR *dir, BYTE *base, int delta )
  229. {
  230. while (dir->Name)
  231. {
  232. fixup_rva_dwords( &dir->u.OriginalFirstThunk, delta, 1 );
  233. fixup_rva_dwords( &dir->Name, delta, 1 );
  234. fixup_rva_dwords( &dir->FirstThunk, delta, 1 );
  235. if (dir->u.OriginalFirstThunk) fixup_rva_names( (UINT_PTR *)(base + dir->u.OriginalFirstThunk), delta );
  236. if (dir->FirstThunk) fixup_rva_names( (UINT_PTR *)(base + dir->FirstThunk), delta );
  237. dir++;
  238. }
  239. }
  240. /* fixup RVAs in the export directory */
  241. static void fixup_exports( IMAGE_EXPORT_DIRECTORY *dir, BYTE *base, int delta )
  242. {
  243. fixup_rva_dwords( &dir->Name, delta, 1 );
  244. fixup_rva_dwords( &dir->AddressOfFunctions, delta, 1 );
  245. fixup_rva_dwords( &dir->AddressOfNames, delta, 1 );
  246. fixup_rva_dwords( &dir->AddressOfNameOrdinals, delta, 1 );
  247. fixup_rva_dwords( (DWORD *)(base + dir->AddressOfNames), delta, dir->NumberOfNames );
  248. fixup_rva_ptrs( (base + dir->AddressOfFunctions), base, dir->NumberOfFunctions );
  249. }
  250. /* fixup RVAs in the resource directory */
  251. static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, BYTE *root, int delta )
  252. {
  253. IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
  254. int i;
  255. entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
  256. for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++)
  257. {
  258. void *ptr = root + entry->u2.s2.OffsetToDirectory;
  259. if (entry->u2.s2.DataIsDirectory) fixup_resources( ptr, root, delta );
  260. else
  261. {
  262. IMAGE_RESOURCE_DATA_ENTRY *data = ptr;
  263. fixup_rva_dwords( &data->OffsetToData, delta, 1 );
  264. }
  265. }
  266. }
  267. /* map a builtin dll in memory and fixup RVAs */
  268. static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
  269. {
  270. IMAGE_DATA_DIRECTORY *dir;
  271. IMAGE_DOS_HEADER *dos;
  272. IMAGE_NT_HEADERS *nt;
  273. IMAGE_SECTION_HEADER *sec;
  274. BYTE *addr;
  275. DWORD code_start, code_end, data_start, data_end;
  276. const size_t page_size = sysconf( _SC_PAGESIZE );
  277. const size_t page_mask = page_size - 1;
  278. int delta, nb_sections = 2; /* code + data */
  279. unsigned int i;
  280. #ifdef __APPLE__
  281. Dl_info dli;
  282. unsigned long data_size;
  283. #endif
  284. size_t size = (sizeof(IMAGE_DOS_HEADER)
  285. + sizeof(IMAGE_NT_HEADERS)
  286. + nb_sections * sizeof(IMAGE_SECTION_HEADER));
  287. assert( size <= page_size );
  288. /* module address must be aligned on 64K boundary */
  289. addr = (BYTE *)((nt_descr->OptionalHeader.ImageBase + 0xffff) & ~0xffff);
  290. if (wine_anon_mmap( addr, page_size, PROT_READ|PROT_WRITE, MAP_FIXED ) != addr) return NULL;
  291. dos = (IMAGE_DOS_HEADER *)addr;
  292. nt = (IMAGE_NT_HEADERS *)(dos + 1);
  293. sec = (IMAGE_SECTION_HEADER *)(nt + 1);
  294. /* Build the DOS and NT headers */
  295. dos->e_magic = IMAGE_DOS_SIGNATURE;
  296. dos->e_cblp = 0x90;
  297. dos->e_cp = 3;
  298. dos->e_cparhdr = (sizeof(*dos)+0xf)/0x10;
  299. dos->e_minalloc = 0;
  300. dos->e_maxalloc = 0xffff;
  301. dos->e_ss = 0x0000;
  302. dos->e_sp = 0x00b8;
  303. dos->e_lfarlc = sizeof(*dos);
  304. dos->e_lfanew = sizeof(*dos);
  305. *nt = *nt_descr;
  306. delta = (const BYTE *)nt_descr - addr;
  307. code_start = page_size;
  308. data_start = delta & ~page_mask;
  309. #ifdef __APPLE__
  310. /* Need the mach_header, not the PE header, to give to getsegmentdata(3) */
  311. dladdr(addr, &dli);
  312. code_end = getsegmentdata(dli.dli_fbase, "__DATA", &data_size) - addr;
  313. data_end = (code_end + data_size + page_mask) & ~page_mask;
  314. #else
  315. code_end = data_start;
  316. data_end = (nt->OptionalHeader.SizeOfImage + delta + page_mask) & ~page_mask;
  317. #endif
  318. fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
  319. nt->FileHeader.NumberOfSections = nb_sections;
  320. nt->OptionalHeader.BaseOfCode = code_start;
  321. #ifndef _WIN64
  322. nt->OptionalHeader.BaseOfData = data_start;
  323. #endif
  324. nt->OptionalHeader.SizeOfCode = code_end - code_start;
  325. nt->OptionalHeader.SizeOfInitializedData = data_end - data_start;
  326. nt->OptionalHeader.SizeOfUninitializedData = 0;
  327. nt->OptionalHeader.SizeOfImage = data_end;
  328. nt->OptionalHeader.ImageBase = (ULONG_PTR)addr;
  329. /* Build the code section */
  330. memcpy( sec->Name, ".text", sizeof(".text") );
  331. sec->SizeOfRawData = code_end - code_start;
  332. sec->Misc.VirtualSize = sec->SizeOfRawData;
  333. sec->VirtualAddress = code_start;
  334. sec->PointerToRawData = code_start;
  335. sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
  336. sec++;
  337. /* Build the data section */
  338. memcpy( sec->Name, ".data", sizeof(".data") );
  339. sec->SizeOfRawData = data_end - data_start;
  340. sec->Misc.VirtualSize = sec->SizeOfRawData;
  341. sec->VirtualAddress = data_start;
  342. sec->PointerToRawData = data_start;
  343. sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA |
  344. IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ);
  345. sec++;
  346. for (i = 0; i < nt->OptionalHeader.NumberOfRvaAndSizes; i++)
  347. fixup_rva_dwords( &nt->OptionalHeader.DataDirectory[i].VirtualAddress, delta, 1 );
  348. /* Build the import directory */
  349. dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
  350. if (dir->Size)
  351. {
  352. IMAGE_IMPORT_DESCRIPTOR *imports = (void *)(addr + dir->VirtualAddress);
  353. fixup_imports( imports, addr, delta );
  354. }
  355. /* Build the resource directory */
  356. dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
  357. if (dir->Size)
  358. {
  359. void *ptr = (void *)(addr + dir->VirtualAddress);
  360. fixup_resources( ptr, ptr, delta );
  361. }
  362. /* Build the export directory */
  363. dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
  364. if (dir->Size)
  365. {
  366. IMAGE_EXPORT_DIRECTORY *exports = (void *)(addr + dir->VirtualAddress);
  367. fixup_exports( exports, addr, delta );
  368. }
  369. return addr;
  370. }
  371. /***********************************************************************
  372. * __wine_get_main_environment
  373. *
  374. * Return an environment pointer to work around lack of environ variable.
  375. * Only exported on Mac OS.
  376. */
  377. char **__wine_get_main_environment(void)
  378. {
  379. return environ;
  380. }
  381. /***********************************************************************
  382. * __wine_dll_register
  383. *
  384. * Register a built-in DLL descriptor.
  385. */
  386. void __wine_dll_register( const IMAGE_NT_HEADERS *header, const char *filename )
  387. {
  388. if (load_dll_callback) load_dll_callback( map_dll(header), filename );
  389. else
  390. {
  391. if (!(header->FileHeader.Characteristics & IMAGE_FILE_DLL))
  392. main_exe = header;
  393. else
  394. {
  395. assert( nb_dlls < MAX_DLLS );
  396. builtin_dlls[nb_dlls].nt = header;
  397. builtin_dlls[nb_dlls].filename = filename;
  398. nb_dlls++;
  399. }
  400. }
  401. }
  402. /***********************************************************************
  403. * wine_dll_set_callback
  404. *
  405. * Set the callback function for dll loading, and call it
  406. * for all dlls that were implicitly loaded already.
  407. */
  408. void wine_dll_set_callback( load_dll_callback_t load )
  409. {
  410. int i;
  411. load_dll_callback = load;
  412. for (i = 0; i < nb_dlls; i++)
  413. {
  414. const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
  415. if (!nt) continue;
  416. builtin_dlls[i].nt = NULL;
  417. load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
  418. }
  419. nb_dlls = 0;
  420. if (main_exe) load_dll_callback( map_dll(main_exe), "" );
  421. }
  422. #ifdef __ASM_OBSOLETE
  423. /***********************************************************************
  424. * wine_dll_enum_load_path
  425. *
  426. * Enumerate the dll load path.
  427. */
  428. const char *wine_dll_enum_load_path_obsolete( unsigned int index )
  429. {
  430. if (index >= nb_dll_paths) return NULL;
  431. return dll_paths[index];
  432. }
  433. /*
  434. * These functions provide wrappers around dlopen() and associated
  435. * functions. They work around a bug in glibc 2.1.x where calling
  436. * a dl*() function after a previous dl*() function has failed
  437. * without a dlerror() call between the two will cause a crash.
  438. * They all take a pointer to a buffer that
  439. * will receive the error description (from dlerror()). This
  440. * parameter may be NULL if the error description is not required.
  441. */
  442. #ifndef RTLD_FIRST
  443. #define RTLD_FIRST 0
  444. #endif
  445. /***********************************************************************
  446. * wine_dlopen
  447. */
  448. void *wine_dlopen_obsolete( const char *filename, int flag, char *error, size_t errorsize )
  449. {
  450. void *ret;
  451. const char *s;
  452. #ifdef __APPLE__
  453. /* the Mac OS loader pretends to be able to load PE files, so avoid them here */
  454. unsigned char magic[2];
  455. int fd = open( filename, O_RDONLY );
  456. if (fd != -1)
  457. {
  458. if (pread( fd, magic, 2, 0 ) == 2 && magic[0] == 'M' && magic[1] == 'Z')
  459. {
  460. if (error && errorsize)
  461. {
  462. static const char msg[] = "MZ format";
  463. size_t len = min( errorsize, sizeof(msg) );
  464. memcpy( error, msg, len );
  465. error[len - 1] = 0;
  466. }
  467. close( fd );
  468. return NULL;
  469. }
  470. close( fd );
  471. }
  472. #endif
  473. dlerror(); dlerror();
  474. #ifdef __sun
  475. if (strchr( filename, ':' ))
  476. {
  477. char path[PATH_MAX];
  478. /* Solaris' brain damaged dlopen() treats ':' as a path separator */
  479. realpath( filename, path );
  480. ret = dlopen( path, flag | RTLD_FIRST );
  481. }
  482. else
  483. #endif
  484. ret = dlopen( filename, flag | RTLD_FIRST );
  485. s = dlerror();
  486. if (error && errorsize)
  487. {
  488. if (s)
  489. {
  490. size_t len = strlen(s);
  491. if (len >= errorsize) len = errorsize - 1;
  492. memcpy( error, s, len );
  493. error[len] = 0;
  494. }
  495. else error[0] = 0;
  496. }
  497. dlerror();
  498. return ret;
  499. }
  500. /***********************************************************************
  501. * wine_dlsym
  502. */
  503. void *wine_dlsym_obsolete( void *handle, const char *symbol, char *error, size_t errorsize )
  504. {
  505. void *ret;
  506. const char *s;
  507. dlerror(); dlerror();
  508. ret = dlsym( handle, symbol );
  509. s = dlerror();
  510. if (error && errorsize)
  511. {
  512. if (s)
  513. {
  514. size_t len = strlen(s);
  515. if (len >= errorsize) len = errorsize - 1;
  516. memcpy( error, s, len );
  517. error[len] = 0;
  518. }
  519. else error[0] = 0;
  520. }
  521. dlerror();
  522. return ret;
  523. }
  524. /***********************************************************************
  525. * wine_dlclose
  526. */
  527. int wine_dlclose_obsolete( void *handle, char *error, size_t errorsize )
  528. {
  529. int ret;
  530. const char *s;
  531. dlerror(); dlerror();
  532. ret = dlclose( handle );
  533. s = dlerror();
  534. if (error && errorsize)
  535. {
  536. if (s)
  537. {
  538. size_t len = strlen(s);
  539. if (len >= errorsize) len = errorsize - 1;
  540. memcpy( error, s, len );
  541. error[len] = 0;
  542. }
  543. else error[0] = 0;
  544. }
  545. dlerror();
  546. return ret;
  547. }
  548. /* check if the library is the correct architecture */
  549. /* only returns false for a valid library of the wrong arch */
  550. static int check_library_arch( int fd )
  551. {
  552. #ifdef __APPLE__
  553. struct /* Mach-O header */
  554. {
  555. unsigned int magic;
  556. unsigned int cputype;
  557. } header;
  558. if (read( fd, &header, sizeof(header) ) != sizeof(header)) return 1;
  559. if (header.magic != 0xfeedface) return 1;
  560. if (sizeof(void *) == sizeof(int)) return !(header.cputype >> 24);
  561. else return (header.cputype >> 24) == 1; /* CPU_ARCH_ABI64 */
  562. #else
  563. struct /* ELF header */
  564. {
  565. unsigned char magic[4];
  566. unsigned char class;
  567. unsigned char data;
  568. unsigned char version;
  569. } header;
  570. if (read( fd, &header, sizeof(header) ) != sizeof(header)) return 1;
  571. if (memcmp( header.magic, "\177ELF", 4 )) return 1;
  572. if (header.version != 1 /* EV_CURRENT */) return 1;
  573. #ifdef WORDS_BIGENDIAN
  574. if (header.data != 2 /* ELFDATA2MSB */) return 1;
  575. #else
  576. if (header.data != 1 /* ELFDATA2LSB */) return 1;
  577. #endif
  578. if (sizeof(void *) == sizeof(int)) return header.class == 1; /* ELFCLASS32 */
  579. else return header.class == 2; /* ELFCLASS64 */
  580. #endif
  581. }
  582. /* check if a given file can be opened */
  583. static int file_exists( const char *name )
  584. {
  585. int ret = 0;
  586. int fd = open( name, O_RDONLY );
  587. if (fd != -1)
  588. {
  589. ret = check_library_arch( fd );
  590. close( fd );
  591. }
  592. return ret;
  593. }
  594. /* open a library for a given dll, searching in the dll path
  595. * 'name' must be the Windows dll name (e.g. "kernel32.dll") */
  596. static void *dlopen_dll( const char *name, char *error, int errorsize,
  597. int test_only, int *exists )
  598. {
  599. struct dll_path_context context;
  600. char *path;
  601. void *ret = NULL;
  602. *exists = 0;
  603. for (path = first_dll_path( name, 0, &context ); path; path = next_dll_path( &context ))
  604. {
  605. if (!test_only && (ret = wine_dlopen_obsolete( path, RTLD_NOW, error, errorsize ))) break;
  606. if ((*exists = file_exists( path ))) break; /* exists but cannot be loaded, return the error */
  607. }
  608. free_dll_path( &context );
  609. return ret;
  610. }
  611. /***********************************************************************
  612. * wine_dll_load
  613. *
  614. * Load a builtin dll.
  615. */
  616. void *wine_dll_load_obsolete( const char *filename, char *error, int errorsize, int *file_exists )
  617. {
  618. int i;
  619. /* callback must have been set already */
  620. assert( load_dll_callback );
  621. /* check if we have it in the list */
  622. /* this can happen when initializing pre-loaded dlls in wine_dll_set_callback */
  623. for (i = 0; i < nb_dlls; i++)
  624. {
  625. if (!builtin_dlls[i].nt) continue;
  626. if (!strcmp( builtin_dlls[i].filename, filename ))
  627. {
  628. const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
  629. builtin_dlls[i].nt = NULL;
  630. load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
  631. *file_exists = 1;
  632. return (void *)1;
  633. }
  634. }
  635. return dlopen_dll( filename, error, errorsize, 0, file_exists );
  636. }
  637. /***********************************************************************
  638. * wine_dll_unload
  639. *
  640. * Unload a builtin dll.
  641. */
  642. void wine_dll_unload_obsolete( void *handle )
  643. {
  644. if (handle != (void *)1)
  645. wine_dlclose_obsolete( handle, NULL, 0 );
  646. }
  647. /***********************************************************************
  648. * wine_dll_load_main_exe
  649. *
  650. * Try to load the .so for the main exe.
  651. */
  652. void *wine_dll_load_main_exe_obsolete( const char *name, char *error, int errorsize,
  653. int test_only, int *file_exists )
  654. {
  655. return dlopen_dll( name, error, errorsize, test_only, file_exists );
  656. }
  657. /***********************************************************************
  658. * wine_dll_get_owner
  659. *
  660. * Retrieve the name of the 32-bit owner dll for a 16-bit dll.
  661. * Return 0 if OK, -1 on error.
  662. */
  663. int wine_dll_get_owner_obsolete( const char *name, char *buffer, int size, int *exists )
  664. {
  665. int ret = -1;
  666. char *path;
  667. struct dll_path_context context;
  668. *exists = 0;
  669. for (path = first_dll_path( name, 1, &context ); path; path = next_dll_path( &context ))
  670. {
  671. int fd = open( path, O_RDONLY );
  672. if (fd != -1)
  673. {
  674. int res = read( fd, buffer, size - 1 );
  675. while (res > 0 && (buffer[res-1] == '\n' || buffer[res-1] == '\r')) res--;
  676. buffer[res] = 0;
  677. close( fd );
  678. *exists = 1;
  679. ret = 0;
  680. break;
  681. }
  682. }
  683. free_dll_path( &context );
  684. return ret;
  685. }
  686. /***********************************************************************
  687. * set_max_limit
  688. *
  689. * Set a user limit to the maximum allowed value.
  690. */
  691. static void set_max_limit( int limit )
  692. {
  693. struct rlimit rlimit;
  694. if (!getrlimit( limit, &rlimit ))
  695. {
  696. rlimit.rlim_cur = rlimit.rlim_max;
  697. if (setrlimit( limit, &rlimit ) != 0)
  698. {
  699. #if defined(__APPLE__) && defined(RLIMIT_NOFILE) && defined(OPEN_MAX)
  700. /* On Leopard, setrlimit(RLIMIT_NOFILE, ...) fails on attempts to set
  701. * rlim_cur above OPEN_MAX (even if rlim_max > OPEN_MAX). */
  702. if (limit == RLIMIT_NOFILE && rlimit.rlim_cur > OPEN_MAX)
  703. {
  704. rlimit.rlim_cur = OPEN_MAX;
  705. setrlimit( limit, &rlimit );
  706. }
  707. #endif
  708. }
  709. }
  710. }
  711. #ifdef __APPLE__
  712. struct apple_stack_info
  713. {
  714. void *stack;
  715. size_t desired_size;
  716. };
  717. /***********************************************************************
  718. * apple_alloc_thread_stack
  719. *
  720. * Callback for wine_mmap_enum_reserved_areas to allocate space for
  721. * the secondary thread's stack.
  722. */
  723. #ifndef _WIN64
  724. static int apple_alloc_thread_stack( void *base, size_t size, void *arg )
  725. {
  726. struct apple_stack_info *info = arg;
  727. /* For mysterious reasons, putting the thread stack at the very top
  728. * of the address space causes subsequent execs to fail, even on the
  729. * child side of a fork. Avoid the top 16MB. */
  730. char * const limit = (char*)0xff000000;
  731. if ((char *)base >= limit) return 0;
  732. if (size > limit - (char*)base)
  733. size = limit - (char*)base;
  734. if (size < info->desired_size) return 0;
  735. info->stack = wine_anon_mmap( (char *)base + size - info->desired_size,
  736. info->desired_size, PROT_READ|PROT_WRITE, MAP_FIXED );
  737. return (info->stack != (void *)-1);
  738. }
  739. #endif
  740. /***********************************************************************
  741. * apple_create_wine_thread
  742. *
  743. * Spin off a secondary thread to complete Wine initialization, leaving
  744. * the original thread for the Mac frameworks.
  745. *
  746. * Invoked as a CFRunLoopSource perform callback.
  747. */
  748. static void apple_create_wine_thread( void *init_func )
  749. {
  750. int success = 0;
  751. pthread_t thread;
  752. pthread_attr_t attr;
  753. if (!pthread_attr_init( &attr ))
  754. {
  755. #ifndef _WIN64
  756. struct apple_stack_info info;
  757. /* Try to put the new thread's stack in the reserved area. If this
  758. * fails, just let it go wherever. It'll be a waste of space, but we
  759. * can go on. */
  760. if (!pthread_attr_getstacksize( &attr, &info.desired_size ) &&
  761. wine_mmap_enum_reserved_areas_obsolete( apple_alloc_thread_stack, &info, 1 ))
  762. {
  763. wine_mmap_remove_reserved_area_obsolete( info.stack, info.desired_size, 0 );
  764. pthread_attr_setstackaddr( &attr, (char*)info.stack + info.desired_size );
  765. }
  766. #endif
  767. if (!pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ) &&
  768. !pthread_create( &thread, &attr, init_func, NULL ))
  769. success = 1;
  770. pthread_attr_destroy( &attr );
  771. }
  772. /* Failure is indicated by returning from wine_init(). Stopping
  773. * the run loop allows apple_main_thread() and thus wine_init() to
  774. * return. */
  775. if (!success)
  776. CFRunLoopStop( CFRunLoopGetCurrent() );
  777. }
  778. /***********************************************************************
  779. * apple_main_thread
  780. *
  781. * Park the process's original thread in a Core Foundation run loop for
  782. * use by the Mac frameworks, especially receiving and handling
  783. * distributed notifications. Spin off a new thread for the rest of the
  784. * Wine initialization.
  785. */
  786. static void apple_main_thread( void (*init_func)(void) )
  787. {
  788. CFRunLoopSourceContext source_context = { 0 };
  789. CFRunLoopSourceRef source;
  790. if (!pthread_main_np())
  791. {
  792. init_func();
  793. return;
  794. }
  795. /* Multi-processing Services can get confused about the main thread if the
  796. * first time it's used is on a secondary thread. Use it here to make sure
  797. * that doesn't happen. */
  798. MPTaskIsPreemptive(MPCurrentTaskID());
  799. /* Give ourselves the best chance of having the distributed notification
  800. * center scheduled on this thread's run loop. In theory, it's scheduled
  801. * in the first thread to ask for it. */
  802. CFNotificationCenterGetDistributedCenter();
  803. /* We use this run loop source for two purposes. First, a run loop exits
  804. * if it has no more sources scheduled. So, we need at least one source
  805. * to keep the run loop running. Second, although it's not critical, it's
  806. * preferable for the Wine initialization to not proceed until we know
  807. * the run loop is running. So, we signal our source immediately after
  808. * adding it and have its callback spin off the Wine thread. */
  809. source_context.info = init_func;
  810. source_context.perform = apple_create_wine_thread;
  811. source = CFRunLoopSourceCreate( NULL, 0, &source_context );
  812. if (source)
  813. {
  814. CFRunLoopAddSource( CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes );
  815. CFRunLoopSourceSignal( source );
  816. CFRelease( source );
  817. CFRunLoopRun(); /* Should never return, except on error. */
  818. }
  819. /* If we get here (i.e. return), that indicates failure to our caller. */
  820. }
  821. #endif
  822. /***********************************************************************
  823. * wine_init
  824. *
  825. * Main Wine initialisation.
  826. */
  827. void wine_init_obsolete( int argc, char *argv[], char *error, int error_size )
  828. {
  829. struct dll_path_context context;
  830. char *path;
  831. void *ntdll = NULL;
  832. void (*init_func)(void);
  833. /* force a few limits that are set too low on some platforms */
  834. #ifdef RLIMIT_NOFILE
  835. set_max_limit( RLIMIT_NOFILE );
  836. #endif
  837. #ifdef RLIMIT_AS
  838. set_max_limit( RLIMIT_AS );
  839. #endif
  840. wine_init_argv0_path_obsolete( argv[0] );
  841. build_dll_path();
  842. __wine_main_argc = argc;
  843. __wine_main_argv = argv;
  844. __wine_main_environ = __wine_get_main_environment();
  845. mmap_init();
  846. for (path = first_dll_path( "ntdll.dll", 0, &context ); path; path = next_dll_path( &context ))
  847. {
  848. if ((ntdll = dlopen( path, RTLD_NOW )))
  849. {
  850. /* if we didn't use the default dll dir, remove it from the search path */
  851. if (default_dlldir[0] && context.index < nb_dll_paths + 2) nb_dll_paths--;
  852. break;
  853. }
  854. }
  855. free_dll_path( &context );
  856. if (!ntdll || !(init_func = dlsym( ntdll, "__wine_process_init" )))
  857. {
  858. if (error && error_size)
  859. {
  860. const char *s = dlerror();
  861. if (s)
  862. {
  863. size_t len = min( strlen(s), error_size - 1 );
  864. memcpy( error, s, len );
  865. error[len] = 0;
  866. }
  867. else error[0] = 0;
  868. }
  869. return;
  870. }
  871. #ifdef __APPLE__
  872. apple_main_thread( init_func );
  873. #else
  874. init_func();
  875. #endif
  876. }
  877. __ASM_OBSOLETE(wine_dlopen);
  878. __ASM_OBSOLETE(wine_dlsym);
  879. __ASM_OBSOLETE(wine_dlclose);
  880. __ASM_OBSOLETE(wine_dll_enum_load_path);
  881. __ASM_OBSOLETE(wine_dll_get_owner);
  882. __ASM_OBSOLETE(wine_dll_load);
  883. __ASM_OBSOLETE(wine_dll_load_main_exe);
  884. __ASM_OBSOLETE(wine_dll_unload);
  885. __ASM_OBSOLETE(wine_init);
  886. #endif /* __ASM_OBSOLETE */