import.c 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557
  1. /*
  2. * DLL imports support
  3. *
  4. * Copyright 2000, 2004 Alexandre Julliard
  5. * Copyright 2000 Eric Pouech
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  20. */
  21. #include "config.h"
  22. #include "wine/port.h"
  23. #include <assert.h>
  24. #include <ctype.h>
  25. #include <fcntl.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <stdarg.h>
  29. #ifdef HAVE_SYS_STAT_H
  30. # include <sys/stat.h>
  31. #endif
  32. #ifdef HAVE_UNISTD_H
  33. # include <unistd.h>
  34. #endif
  35. #include "wine/list.h"
  36. #include "build.h"
  37. /* standard C functions that are also exported from ntdll */
  38. static const char *stdc_names[] =
  39. {
  40. "abs",
  41. "atan",
  42. "atoi",
  43. "atol",
  44. "bsearch",
  45. "ceil",
  46. "cos",
  47. "fabs",
  48. "floor",
  49. "isalnum",
  50. "isalpha",
  51. "iscntrl",
  52. "isdigit",
  53. "isgraph",
  54. "islower",
  55. "isprint",
  56. "ispunct",
  57. "isspace",
  58. "isupper",
  59. "iswalpha",
  60. "iswctype",
  61. "iswdigit",
  62. "iswlower",
  63. "iswspace",
  64. "iswxdigit",
  65. "isxdigit",
  66. "labs",
  67. "log",
  68. "mbstowcs",
  69. "memchr",
  70. "memcmp",
  71. "memcpy",
  72. "memmove",
  73. "memset",
  74. "pow",
  75. "qsort",
  76. "sin",
  77. "sprintf",
  78. "sqrt",
  79. "sscanf",
  80. "strcat",
  81. "strchr",
  82. "strcmp",
  83. "strcpy",
  84. "strcspn",
  85. "strlen",
  86. "strncat",
  87. "strncmp",
  88. "strncpy",
  89. "strnlen",
  90. "strpbrk",
  91. "strrchr",
  92. "strspn",
  93. "strstr",
  94. "strtol",
  95. "strtoul",
  96. "swprintf",
  97. "tan",
  98. "tolower",
  99. "toupper",
  100. "towlower",
  101. "towupper",
  102. "vsprintf",
  103. "wcscat",
  104. "wcschr",
  105. "wcscmp",
  106. "wcscpy",
  107. "wcscspn",
  108. "wcslen",
  109. "wcsncat",
  110. "wcsncmp",
  111. "wcsncpy",
  112. "wcspbrk",
  113. "wcsrchr",
  114. "wcsspn",
  115. "wcsstr",
  116. "wcstok",
  117. "wcstol",
  118. "wcstombs",
  119. "wcstoul"
  120. };
  121. static struct strarray stdc_functions = { stdc_names, ARRAY_SIZE(stdc_names), ARRAY_SIZE(stdc_names) };
  122. struct import_func
  123. {
  124. const char *name;
  125. const char *export_name;
  126. int ordinal;
  127. int hint;
  128. };
  129. struct import
  130. {
  131. struct list entry; /* entry in global dll list */
  132. char *dll_name; /* exported file name of the dll */
  133. char *c_name; /* dll name as a C-compatible identifier */
  134. char *full_name; /* full name of the input file */
  135. dev_t dev; /* device/inode of the input file */
  136. ino_t ino;
  137. ORDDEF **exports; /* functions exported from this dll */
  138. int nb_exports; /* number of exported functions */
  139. struct import_func *imports; /* functions we want to import from this dll */
  140. int nb_imports; /* number of imported functions */
  141. int max_imports; /* size of imports array */
  142. };
  143. static struct strarray undef_symbols; /* list of undefined symbols */
  144. static struct strarray extra_ld_symbols; /* list of extra symbols that ld should resolve */
  145. static struct strarray delayed_imports; /* list of delayed import dlls */
  146. static struct strarray ext_link_imports; /* list of external symbols to link to */
  147. static struct list dll_imports = LIST_INIT( dll_imports );
  148. static struct list dll_delayed = LIST_INIT( dll_delayed );
  149. static struct strarray as_files;
  150. static const char import_func_prefix[] = "__wine$func$";
  151. static const char import_ord_prefix[] = "__wine$ord$";
  152. static inline const char *ppc_reg( int reg )
  153. {
  154. static const char * const ppc_regs[32] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  155. "r8", "r9", "r10","r11","r12","r13","r14","r15",
  156. "r16","r17","r18","r19","r20","r21","r22","r23",
  157. "r24","r25","r26","r27","r28","r29","r30","r31" };
  158. if (target_platform == PLATFORM_APPLE) return ppc_regs[reg];
  159. return ppc_regs[reg] + 1; /* skip the 'r' */
  160. }
  161. /* compare function names; helper for resolve_imports */
  162. static int name_cmp( const void *name, const void *entry )
  163. {
  164. return strcmp( *(const char* const *)name, *(const char* const *)entry );
  165. }
  166. /* compare function names; helper for resolve_imports */
  167. static int func_cmp( const void *func1, const void *func2 )
  168. {
  169. const ORDDEF *odp1 = *(const ORDDEF * const *)func1;
  170. const ORDDEF *odp2 = *(const ORDDEF * const *)func2;
  171. return strcmp( odp1->name ? odp1->name : odp1->export_name,
  172. odp2->name ? odp2->name : odp2->export_name );
  173. }
  174. /* remove a name from a name table */
  175. static inline void remove_name( struct strarray *table, unsigned int idx )
  176. {
  177. assert( idx < table->count );
  178. memmove( table->str + idx, table->str + idx + 1,
  179. (table->count - idx - 1) * sizeof(*table->str) );
  180. table->count--;
  181. }
  182. /* locate a name in a (sorted) list */
  183. static inline const char *find_name( const char *name, const struct strarray *table )
  184. {
  185. char **res = NULL;
  186. if (table->count) res = bsearch( &name, table->str, table->count, sizeof(*table->str), name_cmp );
  187. return res ? *res : NULL;
  188. }
  189. /* sort a name table */
  190. static inline void sort_names( struct strarray *table )
  191. {
  192. if (table->count) qsort( table->str, table->count, sizeof(*table->str), name_cmp );
  193. }
  194. /* locate an export in a (sorted) export list */
  195. static inline ORDDEF *find_export( const char *name, ORDDEF **table, int size )
  196. {
  197. ORDDEF func, *odp, **res = NULL;
  198. func.name = xstrdup(name);
  199. func.ordinal = -1;
  200. odp = &func;
  201. if (table) res = bsearch( &odp, table, size, sizeof(*table), func_cmp );
  202. free( func.name );
  203. return res ? *res : NULL;
  204. }
  205. /* free an import structure */
  206. static void free_imports( struct import *imp )
  207. {
  208. free( imp->exports );
  209. free( imp->imports );
  210. free( imp->dll_name );
  211. free( imp->c_name );
  212. free( imp->full_name );
  213. free( imp );
  214. }
  215. /* check whether a given dll is imported in delayed mode */
  216. static int is_delayed_import( const char *name )
  217. {
  218. unsigned int i;
  219. for (i = 0; i < delayed_imports.count; i++)
  220. {
  221. if (!strcmp( delayed_imports.str[i], name )) return 1;
  222. }
  223. return 0;
  224. }
  225. /* find an imported dll from its name */
  226. static struct import *find_import_dll( const char *name )
  227. {
  228. struct import *import;
  229. LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
  230. if (!strcasecmp( import->dll_name, name )) return import;
  231. LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
  232. if (!strcasecmp( import->dll_name, name )) return import;
  233. return NULL;
  234. }
  235. /* open the .so library for a given dll in a specified path */
  236. static char *try_library_path( const char *path, const char *name )
  237. {
  238. char *buffer;
  239. int fd;
  240. buffer = strmake( "%s/lib%s.def", path, name );
  241. /* check if the file exists */
  242. if ((fd = open( buffer, O_RDONLY )) != -1)
  243. {
  244. close( fd );
  245. return buffer;
  246. }
  247. free( buffer );
  248. return NULL;
  249. }
  250. /* find the .def import library for a given dll */
  251. static char *find_library( const char *name )
  252. {
  253. char *fullname;
  254. unsigned int i;
  255. for (i = 0; i < lib_path.count; i++)
  256. {
  257. if ((fullname = try_library_path( lib_path.str[i], name ))) return fullname;
  258. }
  259. fatal_error( "could not open .def file for %s\n", name );
  260. return NULL;
  261. }
  262. /* read in the list of exported symbols of an import library */
  263. static DLLSPEC *read_import_lib( struct import *imp )
  264. {
  265. FILE *f;
  266. int i;
  267. struct stat stat;
  268. struct import *prev_imp;
  269. DLLSPEC *spec = alloc_dll_spec();
  270. f = open_input_file( NULL, imp->full_name );
  271. fstat( fileno(f), &stat );
  272. imp->dev = stat.st_dev;
  273. imp->ino = stat.st_ino;
  274. if (!parse_def_file( f, spec )) exit( 1 );
  275. close_input_file( f );
  276. /* check if we already imported that library from a different file */
  277. if ((prev_imp = find_import_dll( spec->file_name )))
  278. {
  279. if (prev_imp->dev != imp->dev || prev_imp->ino != imp->ino)
  280. fatal_error( "%s and %s have the same export name '%s'\n",
  281. prev_imp->full_name, imp->full_name, spec->file_name );
  282. free_dll_spec( spec );
  283. return NULL; /* the same file was already loaded, ignore this one */
  284. }
  285. if (spec->nb_entry_points)
  286. {
  287. imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) );
  288. for (i = 0; i < spec->nb_entry_points; i++)
  289. imp->exports[imp->nb_exports++] = &spec->entry_points[i];
  290. qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp );
  291. }
  292. return spec;
  293. }
  294. /* build the dll exported name from the import lib name or path */
  295. static char *get_dll_name( const char *name, const char *filename )
  296. {
  297. char *ret;
  298. if (filename)
  299. {
  300. const char *basename = strrchr( filename, '/' );
  301. if (!basename) basename = filename;
  302. else basename++;
  303. if (!strncmp( basename, "lib", 3 )) basename += 3;
  304. ret = xmalloc( strlen(basename) + 5 );
  305. strcpy( ret, basename );
  306. if (strendswith( ret, ".def" )) ret[strlen(ret)-4] = 0;
  307. }
  308. else
  309. {
  310. ret = xmalloc( strlen(name) + 5 );
  311. strcpy( ret, name );
  312. }
  313. if (!strchr( ret, '.' )) strcat( ret, ".dll" );
  314. return ret;
  315. }
  316. /* add a dll to the list of imports */
  317. void add_import_dll( const char *name, const char *filename )
  318. {
  319. DLLSPEC *spec;
  320. char *dll_name = get_dll_name( name, filename );
  321. struct import *imp = xmalloc( sizeof(*imp) );
  322. memset( imp, 0, sizeof(*imp) );
  323. if (filename) imp->full_name = xstrdup( filename );
  324. else imp->full_name = find_library( name );
  325. if (!(spec = read_import_lib( imp )))
  326. {
  327. free_imports( imp );
  328. return;
  329. }
  330. imp->dll_name = spec->file_name ? spec->file_name : dll_name;
  331. imp->c_name = make_c_identifier( imp->dll_name );
  332. if (is_delayed_import( imp->dll_name ))
  333. list_add_tail( &dll_delayed, &imp->entry );
  334. else
  335. list_add_tail( &dll_imports, &imp->entry );
  336. }
  337. /* add a library to the list of delayed imports */
  338. void add_delayed_import( const char *name )
  339. {
  340. struct import *imp;
  341. char *fullname = get_dll_name( name, NULL );
  342. strarray_add( &delayed_imports, fullname, NULL );
  343. if ((imp = find_import_dll( fullname )))
  344. {
  345. list_remove( &imp->entry );
  346. list_add_tail( &dll_delayed, &imp->entry );
  347. }
  348. }
  349. /* add a symbol to the list of extra symbols that ld must resolve */
  350. void add_extra_ld_symbol( const char *name )
  351. {
  352. strarray_add( &extra_ld_symbols, name, NULL );
  353. }
  354. /* retrieve an imported dll, adding one if necessary */
  355. struct import *add_static_import_dll( const char *name )
  356. {
  357. struct import *import;
  358. char *dll_name = get_dll_name( name, NULL );
  359. if ((import = find_import_dll( dll_name ))) return import;
  360. import = xmalloc( sizeof(*import) );
  361. memset( import, 0, sizeof(*import) );
  362. import->dll_name = dll_name;
  363. import->full_name = xstrdup( dll_name );
  364. import->c_name = make_c_identifier( dll_name );
  365. if (is_delayed_import( dll_name ))
  366. list_add_tail( &dll_delayed, &import->entry );
  367. else
  368. list_add_tail( &dll_imports, &import->entry );
  369. return import;
  370. }
  371. /* add a function to the list of imports from a given dll */
  372. static void add_import_func( struct import *imp, const char *name, const char *export_name,
  373. int ordinal, int hint )
  374. {
  375. if (imp->nb_imports == imp->max_imports)
  376. {
  377. imp->max_imports *= 2;
  378. if (imp->max_imports < 32) imp->max_imports = 32;
  379. imp->imports = xrealloc( imp->imports, imp->max_imports * sizeof(*imp->imports) );
  380. }
  381. imp->imports[imp->nb_imports].name = name;
  382. imp->imports[imp->nb_imports].export_name = export_name;
  383. imp->imports[imp->nb_imports].ordinal = ordinal;
  384. imp->imports[imp->nb_imports].hint = hint;
  385. imp->nb_imports++;
  386. }
  387. /* add an import for an undefined function of the form __wine$func$ */
  388. static void add_undef_import( const char *name, int is_ordinal )
  389. {
  390. char *p, *dll_name = xstrdup( name );
  391. int ordinal = 0;
  392. struct import *import;
  393. if (!(p = strchr( dll_name, '$' ))) return;
  394. *p++ = 0;
  395. while (*p >= '0' && *p <= '9') ordinal = 10 * ordinal + *p++ - '0';
  396. if (*p != '$') return;
  397. p++;
  398. import = add_static_import_dll( dll_name );
  399. if (is_ordinal)
  400. add_import_func( import, NULL, xstrdup( p ), ordinal, 0 );
  401. else
  402. add_import_func( import, xstrdup( p ), NULL, ordinal, 0 );
  403. }
  404. /* check if the spec file exports any stubs */
  405. static int has_stubs( const DLLSPEC *spec )
  406. {
  407. int i;
  408. for (i = 0; i < spec->nb_entry_points; i++)
  409. {
  410. ORDDEF *odp = &spec->entry_points[i];
  411. if (odp->type == TYPE_STUB) return 1;
  412. }
  413. return 0;
  414. }
  415. /* add the extra undefined symbols that will be contained in the generated spec file itself */
  416. static void add_extra_undef_symbols( DLLSPEC *spec )
  417. {
  418. add_extra_ld_symbol( spec->init_func );
  419. if (has_stubs( spec )) add_extra_ld_symbol( "__wine_spec_unimplemented_stub" );
  420. if (delayed_imports.count) add_extra_ld_symbol( "__wine_spec_delay_load" );
  421. }
  422. /* check if a given imported dll is not needed, taking forwards into account */
  423. static int check_unused( const struct import* imp, const DLLSPEC *spec )
  424. {
  425. int i;
  426. const char *file_name = imp->dll_name;
  427. size_t len = strlen( file_name );
  428. const char *p = strchr( file_name, '.' );
  429. if (p && !strcasecmp( p, ".dll" )) len = p - file_name;
  430. for (i = spec->base; i <= spec->limit; i++)
  431. {
  432. ORDDEF *odp = spec->ordinals[i];
  433. if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
  434. if (!strncasecmp( odp->link_name, file_name, len ) &&
  435. odp->link_name[len] == '.')
  436. return 0; /* found a forward, it is used */
  437. }
  438. return 1;
  439. }
  440. /* check if a given forward does exist in one of the imported dlls */
  441. static void check_undefined_forwards( DLLSPEC *spec )
  442. {
  443. struct import *imp;
  444. char *link_name, *api_name, *dll_name, *p;
  445. int i;
  446. for (i = 0; i < spec->nb_entry_points; i++)
  447. {
  448. ORDDEF *odp = &spec->entry_points[i];
  449. if (!(odp->flags & FLAG_FORWARD)) continue;
  450. link_name = xstrdup( odp->link_name );
  451. p = strrchr( link_name, '.' );
  452. *p = 0;
  453. api_name = p + 1;
  454. dll_name = get_dll_name( link_name, NULL );
  455. if ((imp = find_import_dll( dll_name )))
  456. {
  457. if (!find_export( api_name, imp->exports, imp->nb_exports ))
  458. warning( "%s:%d: forward '%s' not found in %s\n",
  459. spec->src_name, odp->lineno, odp->link_name, imp->dll_name );
  460. }
  461. else warning( "%s:%d: forward '%s' not found in the imported dll list\n",
  462. spec->src_name, odp->lineno, odp->link_name );
  463. free( link_name );
  464. free( dll_name );
  465. }
  466. }
  467. /* flag the dll exports that link to an undefined symbol */
  468. static void check_undefined_exports( DLLSPEC *spec )
  469. {
  470. const char *name;
  471. int i;
  472. for (i = 0; i < spec->nb_entry_points; i++)
  473. {
  474. ORDDEF *odp = &spec->entry_points[i];
  475. if (odp->type == TYPE_STUB || odp->type == TYPE_ABS || odp->type == TYPE_VARIABLE) continue;
  476. if (odp->flags & FLAG_FORWARD) continue;
  477. name = odp->impl_name ? odp->impl_name : odp->link_name;
  478. if (find_name( name, &undef_symbols ))
  479. {
  480. switch(odp->type)
  481. {
  482. case TYPE_PASCAL:
  483. case TYPE_STDCALL:
  484. case TYPE_CDECL:
  485. case TYPE_VARARGS:
  486. if (link_ext_symbols)
  487. {
  488. odp->flags |= FLAG_EXT_LINK;
  489. strarray_add( &ext_link_imports, name, NULL );
  490. }
  491. else error( "%s:%d: function '%s' not defined\n",
  492. spec->src_name, odp->lineno, name );
  493. break;
  494. default:
  495. error( "%s:%d: external symbol '%s' is not a function\n",
  496. spec->src_name, odp->lineno, name );
  497. break;
  498. }
  499. }
  500. }
  501. }
  502. /* create a .o file that references all the undefined symbols we want to resolve */
  503. static char *create_undef_symbols_file( DLLSPEC *spec )
  504. {
  505. char *as_file, *obj_file;
  506. int i;
  507. unsigned int j;
  508. as_file = open_temp_output_file( ".s" );
  509. output( "\t.data\n" );
  510. for (i = 0; i < spec->nb_entry_points; i++)
  511. {
  512. ORDDEF *odp = &spec->entry_points[i];
  513. if (odp->type == TYPE_STUB || odp->type == TYPE_ABS || odp->type == TYPE_VARIABLE) continue;
  514. if (odp->flags & FLAG_FORWARD) continue;
  515. output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name( get_link_name( odp )));
  516. }
  517. for (j = 0; j < extra_ld_symbols.count; j++)
  518. output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name(extra_ld_symbols.str[j]) );
  519. fclose( output_file );
  520. obj_file = get_temp_file_name( output_file_name, ".o" );
  521. assemble_file( as_file, obj_file );
  522. return obj_file;
  523. }
  524. /* combine a list of object files with ld into a single object file */
  525. /* returns the name of the combined file */
  526. static const char *ldcombine_files( DLLSPEC *spec, char **argv )
  527. {
  528. char *ld_tmp_file, *undef_file;
  529. struct strarray args = get_ld_command();
  530. undef_file = create_undef_symbols_file( spec );
  531. ld_tmp_file = get_temp_file_name( output_file_name, ".o" );
  532. strarray_add( &args, "-r", "-o", ld_tmp_file, undef_file, NULL );
  533. strarray_addv( &args, argv );
  534. spawn( args );
  535. return ld_tmp_file;
  536. }
  537. /* read in the list of undefined symbols */
  538. void read_undef_symbols( DLLSPEC *spec, char **argv )
  539. {
  540. size_t prefix_len;
  541. FILE *f;
  542. const char *prog = get_nm_command();
  543. char *cmd, buffer[1024], name_prefix[16];
  544. int err;
  545. const char *name;
  546. if (!argv[0]) return;
  547. add_extra_undef_symbols( spec );
  548. strcpy( name_prefix, asm_name("") );
  549. prefix_len = strlen( name_prefix );
  550. name = ldcombine_files( spec, argv );
  551. cmd = strmake( "%s -u %s", prog, name );
  552. if (verbose)
  553. fprintf( stderr, "%s\n", cmd );
  554. if (!(f = popen( cmd, "r" )))
  555. fatal_error( "Cannot execute '%s'\n", cmd );
  556. while (fgets( buffer, sizeof(buffer), f ))
  557. {
  558. char *p = buffer + strlen(buffer) - 1;
  559. if (p < buffer) continue;
  560. if (*p == '\n') *p-- = 0;
  561. p = buffer;
  562. while (*p == ' ') p++;
  563. if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
  564. if (prefix_len && !strncmp( p, name_prefix, prefix_len )) p += prefix_len;
  565. if (!strncmp( p, import_func_prefix, strlen(import_func_prefix) ))
  566. add_undef_import( p + strlen( import_func_prefix ), 0 );
  567. else if (!strncmp( p, import_ord_prefix, strlen(import_ord_prefix) ))
  568. add_undef_import( p + strlen( import_ord_prefix ), 1 );
  569. else if (!unix_lib || !find_name( p, &stdc_functions ))
  570. strarray_add( &undef_symbols, xstrdup( p ), NULL );
  571. }
  572. if ((err = pclose( f ))) warning( "%s failed with status %d\n", cmd, err );
  573. free( cmd );
  574. }
  575. void resolve_dll_imports( DLLSPEC *spec, struct list *list )
  576. {
  577. unsigned int j;
  578. struct import *imp, *next;
  579. ORDDEF *odp;
  580. LIST_FOR_EACH_ENTRY_SAFE( imp, next, list, struct import, entry )
  581. {
  582. for (j = 0; j < undef_symbols.count; j++)
  583. {
  584. odp = find_export( undef_symbols.str[j], imp->exports, imp->nb_exports );
  585. if (odp)
  586. {
  587. if (odp->flags & FLAG_PRIVATE) continue;
  588. if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL)
  589. warning( "winebuild: Data export '%s' cannot be imported from %s\n",
  590. odp->link_name, imp->dll_name );
  591. else
  592. {
  593. add_import_func( imp, (odp->flags & FLAG_NONAME) ? NULL : odp->name,
  594. odp->export_name, odp->ordinal, odp->hint );
  595. remove_name( &undef_symbols, j-- );
  596. }
  597. }
  598. }
  599. if (!imp->nb_imports)
  600. {
  601. /* the dll is not used, get rid of it */
  602. if (check_unused( imp, spec ))
  603. warning( "winebuild: %s imported but no symbols used\n", imp->dll_name );
  604. list_remove( &imp->entry );
  605. free_imports( imp );
  606. }
  607. }
  608. }
  609. /* resolve the imports for a Win32 module */
  610. void resolve_imports( DLLSPEC *spec )
  611. {
  612. check_undefined_forwards( spec );
  613. resolve_dll_imports( spec, &dll_imports );
  614. resolve_dll_imports( spec, &dll_delayed );
  615. sort_names( &undef_symbols );
  616. check_undefined_exports( spec );
  617. }
  618. /* check if symbol is still undefined */
  619. int is_undefined( const char *name )
  620. {
  621. return find_name( name, &undef_symbols ) != NULL;
  622. }
  623. /* output the get_pc thunk if needed */
  624. void output_get_pc_thunk(void)
  625. {
  626. assert( target_cpu == CPU_x86 );
  627. output( "\n\t.text\n" );
  628. output( "\t.align %d\n", get_alignment(4) );
  629. output( "\t%s\n", func_declaration("__wine_spec_get_pc_thunk_eax") );
  630. output( "%s:\n", asm_name("__wine_spec_get_pc_thunk_eax") );
  631. output_cfi( ".cfi_startproc" );
  632. output( "\tmovl (%%esp),%%eax\n" );
  633. output( "\tret\n" );
  634. output_cfi( ".cfi_endproc" );
  635. output_function_size( "__wine_spec_get_pc_thunk_eax" );
  636. }
  637. /* output a single import thunk */
  638. static void output_import_thunk( const char *name, const char *table, int pos )
  639. {
  640. output( "\n\t.align %d\n", get_alignment(4) );
  641. output( "\t%s\n", func_declaration(name) );
  642. output( "%s\n", asm_globl(name) );
  643. output_cfi( ".cfi_startproc" );
  644. switch(target_cpu)
  645. {
  646. case CPU_x86:
  647. if (!UsePIC)
  648. {
  649. output( "\tjmp *(%s+%d)\n", table, pos );
  650. }
  651. else
  652. {
  653. output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
  654. output( "1:\tjmp *%s+%d-1b(%%eax)\n", table, pos );
  655. needs_get_pc_thunk = 1;
  656. }
  657. break;
  658. case CPU_x86_64:
  659. output( "\tjmpq *%s+%d(%%rip)\n", table, pos );
  660. break;
  661. case CPU_ARM:
  662. output( "\tldr IP,1f\n");
  663. output( "\tldr PC,[PC,IP]\n" );
  664. output( "1:\t.long %s+%u-(1b+4)\n", table, pos );
  665. break;
  666. case CPU_ARM64:
  667. output( "\tadrp x9, %s\n", table );
  668. output( "\tadd x9, x9, #:lo12:%s\n", table );
  669. if (pos & 0xf000) output( "\tadd x9, x9, #%u\n", pos & 0xf000 );
  670. if (pos & 0x0f00) output( "\tadd x9, x9, #%u\n", pos & 0x0f00 );
  671. if (pos & 0x00f0) output( "\tadd x9, x9, #%u\n", pos & 0x00f0 );
  672. if (pos & 0x000f) output( "\tadd x9, x9, #%u\n", pos & 0x000f );
  673. output( "\tldur x9, [x9, #0]\n" );
  674. output( "\tbr x9\n" );
  675. break;
  676. case CPU_POWERPC:
  677. output( "\tmr %s, %s\n", ppc_reg(0), ppc_reg(31) );
  678. if (target_platform == PLATFORM_APPLE)
  679. {
  680. output( "\tlis %s, ha16(%s+%d+32768)\n", ppc_reg(31), table, pos );
  681. output( "\tla %s, lo16(%s+%d)(%s)\n", ppc_reg(31), table, pos, ppc_reg(31) );
  682. }
  683. else
  684. {
  685. output( "\tlis %s, (%s+%d+32768)@h\n", ppc_reg(31), table, pos );
  686. output( "\tla %s, (%s+%d)@l(%s)\n", ppc_reg(31), table, pos, ppc_reg(31) );
  687. }
  688. output( "\tlwz %s, 0(%s)\n", ppc_reg(31), ppc_reg(31) );
  689. output( "\tmtctr %s\n", ppc_reg(31) );
  690. output( "\tmr %s, %s\n", ppc_reg(31), ppc_reg(0) );
  691. output( "\tbctr\n" );
  692. break;
  693. }
  694. output_cfi( ".cfi_endproc" );
  695. output_function_size( name );
  696. }
  697. /* check if we need an import directory */
  698. int has_imports(void)
  699. {
  700. return !list_empty( &dll_imports );
  701. }
  702. /* output the import table of a Win32 module */
  703. static void output_immediate_imports(void)
  704. {
  705. int i, j;
  706. struct import *import;
  707. if (list_empty( &dll_imports )) return; /* no immediate imports */
  708. /* main import header */
  709. output( "\n/* import table */\n" );
  710. output( "\n\t.data\n" );
  711. output( "\t.align %d\n", get_alignment(4) );
  712. output( ".L__wine_spec_imports:\n" );
  713. /* list of dlls */
  714. j = 0;
  715. LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
  716. {
  717. output_rva( ".L__wine_spec_import_data_names + %d", j * get_ptr_size() ); /* OriginalFirstThunk */
  718. output( "\t.long 0\n" ); /* TimeDateStamp */
  719. output( "\t.long 0\n" ); /* ForwarderChain */
  720. output_rva( ".L__wine_spec_import_name_%s", import->c_name ); /* Name */
  721. output_rva( ".L__wine_spec_import_data_ptrs + %d", j * get_ptr_size() ); /* FirstThunk */
  722. j += import->nb_imports + 1;
  723. }
  724. output( "\t.long 0\n" ); /* OriginalFirstThunk */
  725. output( "\t.long 0\n" ); /* TimeDateStamp */
  726. output( "\t.long 0\n" ); /* ForwarderChain */
  727. output( "\t.long 0\n" ); /* Name */
  728. output( "\t.long 0\n" ); /* FirstThunk */
  729. output( "\n\t.align %d\n", get_alignment(get_ptr_size()) );
  730. /* output the names twice, once for OriginalFirstThunk and once for FirstThunk */
  731. for (i = 0; i < 2; i++)
  732. {
  733. output( ".L__wine_spec_import_data_%s:\n", i ? "ptrs" : "names" );
  734. LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
  735. {
  736. for (j = 0; j < import->nb_imports; j++)
  737. {
  738. struct import_func *func = &import->imports[j];
  739. if (i)
  740. {
  741. if (func->name) output( "__imp_%s:\n", asm_name( func->name ));
  742. else if (func->export_name) output( "__imp_%s:\n", asm_name( func->export_name ));
  743. }
  744. if (func->name)
  745. output( "\t%s .L__wine_spec_import_data_%s_%s-.L__wine_spec_rva_base\n",
  746. get_asm_ptr_keyword(), import->c_name, func->name );
  747. else
  748. {
  749. if (get_ptr_size() == 8)
  750. output( "\t.quad 0x800000000000%04x\n", func->ordinal );
  751. else
  752. output( "\t.long 0x8000%04x\n", func->ordinal );
  753. }
  754. }
  755. output( "\t%s 0\n", get_asm_ptr_keyword() );
  756. }
  757. }
  758. output( ".L__wine_spec_imports_end:\n" );
  759. LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
  760. {
  761. for (j = 0; j < import->nb_imports; j++)
  762. {
  763. struct import_func *func = &import->imports[j];
  764. if (!func->name) continue;
  765. output( "\t.align %d\n", get_alignment(2) );
  766. output( ".L__wine_spec_import_data_%s_%s:\n", import->c_name, func->name );
  767. output( "\t.short %d\n", func->hint );
  768. output( "\t%s \"%s\"\n", get_asm_string_keyword(), func->name );
  769. }
  770. }
  771. LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
  772. {
  773. output( ".L__wine_spec_import_name_%s:\n\t%s \"%s\"\n",
  774. import->c_name, get_asm_string_keyword(), import->dll_name );
  775. }
  776. }
  777. /* output the import thunks of a Win32 module */
  778. static void output_immediate_import_thunks(void)
  779. {
  780. int j, pos;
  781. struct import *import;
  782. static const char import_thunks[] = "__wine_spec_import_thunks";
  783. if (list_empty( &dll_imports )) return;
  784. output( "\n/* immediate import thunks */\n\n" );
  785. output( "\t.text\n" );
  786. output( "\t.align %d\n", get_alignment(8) );
  787. output( "%s:\n", asm_name(import_thunks));
  788. pos = 0;
  789. LIST_FOR_EACH_ENTRY( import, &dll_imports, struct import, entry )
  790. {
  791. for (j = 0; j < import->nb_imports; j++, pos += get_ptr_size())
  792. {
  793. struct import_func *func = &import->imports[j];
  794. output_import_thunk( func->name ? func->name : func->export_name,
  795. ".L__wine_spec_import_data_ptrs", pos );
  796. }
  797. pos += get_ptr_size();
  798. }
  799. output_function_size( import_thunks );
  800. }
  801. /* output the delayed import table of a Win32 module */
  802. static void output_delayed_imports( const DLLSPEC *spec )
  803. {
  804. int j, mod;
  805. struct import *import;
  806. if (list_empty( &dll_delayed )) return;
  807. output( "\n/* delayed imports */\n\n" );
  808. output( "\t.data\n" );
  809. output( "\t.align %d\n", get_alignment(get_ptr_size()) );
  810. output( "%s\n", asm_globl("__wine_spec_delay_imports") );
  811. /* list of dlls */
  812. j = mod = 0;
  813. LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
  814. {
  815. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* grAttrs */
  816. output( "\t%s .L__wine_delay_name_%s\n", /* szName */
  817. get_asm_ptr_keyword(), import->c_name );
  818. output( "\t%s .L__wine_delay_modules+%d\n", /* phmod */
  819. get_asm_ptr_keyword(), mod * get_ptr_size() );
  820. output( "\t%s .L__wine_delay_IAT+%d\n", /* pIAT */
  821. get_asm_ptr_keyword(), j * get_ptr_size() );
  822. output( "\t%s .L__wine_delay_INT+%d\n", /* pINT */
  823. get_asm_ptr_keyword(), j * get_ptr_size() );
  824. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pBoundIAT */
  825. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pUnloadIAT */
  826. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* dwTimeStamp */
  827. j += import->nb_imports;
  828. mod++;
  829. }
  830. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* grAttrs */
  831. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* szName */
  832. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* phmod */
  833. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pIAT */
  834. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pINT */
  835. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pBoundIAT */
  836. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pUnloadIAT */
  837. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* dwTimeStamp */
  838. output( "\n.L__wine_delay_IAT:\n" );
  839. LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
  840. {
  841. for (j = 0; j < import->nb_imports; j++)
  842. {
  843. struct import_func *func = &import->imports[j];
  844. const char *name = func->name ? func->name : func->export_name;
  845. output( "\t%s .L__wine_delay_imp_%s_%s\n",
  846. get_asm_ptr_keyword(), import->c_name, name );
  847. }
  848. }
  849. output( "\n.L__wine_delay_INT:\n" );
  850. LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
  851. {
  852. for (j = 0; j < import->nb_imports; j++)
  853. {
  854. struct import_func *func = &import->imports[j];
  855. if (!func->name)
  856. output( "\t%s %d\n", get_asm_ptr_keyword(), func->ordinal );
  857. else
  858. output( "\t%s .L__wine_delay_data_%s_%s\n",
  859. get_asm_ptr_keyword(), import->c_name, func->name );
  860. }
  861. }
  862. output( "\n.L__wine_delay_modules:\n" );
  863. LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
  864. {
  865. output( "\t%s 0\n", get_asm_ptr_keyword() );
  866. }
  867. LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
  868. {
  869. output( ".L__wine_delay_name_%s:\n", import->c_name );
  870. output( "\t%s \"%s\"\n", get_asm_string_keyword(), import->dll_name );
  871. }
  872. LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
  873. {
  874. for (j = 0; j < import->nb_imports; j++)
  875. {
  876. struct import_func *func = &import->imports[j];
  877. if (!func->name) continue;
  878. output( ".L__wine_delay_data_%s_%s:\n", import->c_name, func->name );
  879. output( "\t%s \"%s\"\n", get_asm_string_keyword(), func->name );
  880. }
  881. }
  882. output_function_size( "__wine_spec_delay_imports" );
  883. }
  884. /* output the delayed import thunks of a Win32 module */
  885. static void output_delayed_import_thunks( const DLLSPEC *spec )
  886. {
  887. int idx, j, pos, extra_stack_storage = 0;
  888. struct import *import;
  889. static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders";
  890. static const char delayed_import_thunks[] = "__wine_spec_delayed_import_thunks";
  891. if (list_empty( &dll_delayed )) return;
  892. output( "\n/* delayed import thunks */\n\n" );
  893. output( "\t.text\n" );
  894. output( "\t.align %d\n", get_alignment(8) );
  895. output( "%s:\n", asm_name(delayed_import_loaders));
  896. output( "\t%s\n", func_declaration("__wine_delay_load_asm") );
  897. output( "%s:\n", asm_name("__wine_delay_load_asm") );
  898. output_cfi( ".cfi_startproc" );
  899. switch(target_cpu)
  900. {
  901. case CPU_x86:
  902. output( "\tpushl %%ecx\n" );
  903. output_cfi( ".cfi_adjust_cfa_offset 4" );
  904. output( "\tpushl %%edx\n" );
  905. output_cfi( ".cfi_adjust_cfa_offset 4" );
  906. output( "\tpushl %%eax\n" );
  907. output_cfi( ".cfi_adjust_cfa_offset 4" );
  908. output( "\tcall %s\n", asm_name("__wine_spec_delay_load") );
  909. output_cfi( ".cfi_adjust_cfa_offset -4" );
  910. output( "\tpopl %%edx\n" );
  911. output_cfi( ".cfi_adjust_cfa_offset -4" );
  912. output( "\tpopl %%ecx\n" );
  913. output_cfi( ".cfi_adjust_cfa_offset -4" );
  914. output( "\tjmp *%%eax\n" );
  915. break;
  916. case CPU_x86_64:
  917. output( "\tsubq $0x98,%%rsp\n" );
  918. output_cfi( ".cfi_adjust_cfa_offset 0x98" );
  919. output( "\tmovq %%rdx,0x88(%%rsp)\n" );
  920. output( "\tmovq %%rcx,0x80(%%rsp)\n" );
  921. output( "\tmovq %%r8,0x78(%%rsp)\n" );
  922. output( "\tmovq %%r9,0x70(%%rsp)\n" );
  923. output( "\tmovq %%r10,0x68(%%rsp)\n" );
  924. output( "\tmovq %%r11,0x60(%%rsp)\n" );
  925. output( "\tmovups %%xmm0,0x50(%%rsp)\n" );
  926. output( "\tmovups %%xmm1,0x40(%%rsp)\n" );
  927. output( "\tmovups %%xmm2,0x30(%%rsp)\n" );
  928. output( "\tmovups %%xmm3,0x20(%%rsp)\n" );
  929. output( "\tmovq %%rax,%%rcx\n" );
  930. output( "\tcall %s\n", asm_name("__wine_spec_delay_load") );
  931. output( "\tmovups 0x20(%%rsp),%%xmm3\n" );
  932. output( "\tmovups 0x30(%%rsp),%%xmm2\n" );
  933. output( "\tmovups 0x40(%%rsp),%%xmm1\n" );
  934. output( "\tmovups 0x50(%%rsp),%%xmm0\n" );
  935. output( "\tmovq 0x60(%%rsp),%%r11\n" );
  936. output( "\tmovq 0x68(%%rsp),%%r10\n" );
  937. output( "\tmovq 0x70(%%rsp),%%r9\n" );
  938. output( "\tmovq 0x78(%%rsp),%%r8\n" );
  939. output( "\tmovq 0x80(%%rsp),%%rcx\n" );
  940. output( "\tmovq 0x88(%%rsp),%%rdx\n" );
  941. output( "\taddq $0x98,%%rsp\n" );
  942. output_cfi( ".cfi_adjust_cfa_offset -0x98" );
  943. output( "\tjmp *%%rax\n" );
  944. break;
  945. case CPU_ARM:
  946. output( "\tpush {r0-r3,FP,LR}\n" );
  947. output( "\tmov r0,IP\n" );
  948. output( "\tldr IP,2f\n");
  949. output( "\tadd IP,PC\n");
  950. output( "\tblx IP\n");
  951. output( "1:\tmov IP,r0\n");
  952. output( "\tpop {r0-r3,FP,LR}\n" );
  953. output( "\tbx IP\n");
  954. output( "2:\t.long %s-1b\n", asm_name("__wine_spec_delay_load") );
  955. break;
  956. case CPU_ARM64:
  957. output( "\tstp x29, x30, [sp,#-16]!\n" );
  958. output( "\tmov x29, sp\n" );
  959. output( "\tadrp x9, %s\n", asm_name("__wine_spec_delay_load") );
  960. output( "\tadd x9, x9, #:lo12:%s\n", asm_name("__wine_spec_delay_load") );
  961. output( "\tblr x9\n" );
  962. output( "\tmov x9, x0\n" );
  963. output( "\tldp x29, x30, [sp],#16\n" );
  964. output( "\tldp x0, x1, [sp,#16]\n" );
  965. output( "\tldp x2, x3, [sp,#32]\n" );
  966. output( "\tldp x4, x5, [sp,#48]\n" );
  967. output( "\tldp x6, x7, [sp],#80\n" );
  968. output( "\tbr x9\n" ); /* or "ret x9" */
  969. break;
  970. case CPU_POWERPC:
  971. if (target_platform == PLATFORM_APPLE) extra_stack_storage = 56;
  972. /* Save all callee saved registers into a stackframe. */
  973. output( "\tstwu %s, -%d(%s)\n",ppc_reg(1), 48+extra_stack_storage, ppc_reg(1));
  974. output( "\tstw %s, %d(%s)\n", ppc_reg(3), 4+extra_stack_storage, ppc_reg(1));
  975. output( "\tstw %s, %d(%s)\n", ppc_reg(4), 8+extra_stack_storage, ppc_reg(1));
  976. output( "\tstw %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
  977. output( "\tstw %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
  978. output( "\tstw %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
  979. output( "\tstw %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
  980. output( "\tstw %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
  981. output( "\tstw %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
  982. output( "\tstw %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
  983. output( "\tstw %s, %d(%s)\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
  984. /* r0 -> r3 (arg1) */
  985. output( "\tmr %s, %s\n", ppc_reg(3), ppc_reg(0));
  986. /* save return address */
  987. output( "\tmflr %s\n", ppc_reg(0));
  988. output( "\tstw %s, %d(%s)\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
  989. /* Call the __wine_delay_load function, arg1 is arg1. */
  990. output( "\tbl %s\n", asm_name("__wine_spec_delay_load") );
  991. /* Load return value from call into ctr register */
  992. output( "\tmtctr %s\n", ppc_reg(3));
  993. /* restore all saved registers and drop stackframe. */
  994. output( "\tlwz %s, %d(%s)\n", ppc_reg(3), 4+extra_stack_storage, ppc_reg(1));
  995. output( "\tlwz %s, %d(%s)\n", ppc_reg(4), 8+extra_stack_storage, ppc_reg(1));
  996. output( "\tlwz %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
  997. output( "\tlwz %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
  998. output( "\tlwz %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
  999. output( "\tlwz %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
  1000. output( "\tlwz %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
  1001. output( "\tlwz %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
  1002. output( "\tlwz %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
  1003. output( "\tlwz %s, %d(%s)\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
  1004. /* Load return value from call into return register */
  1005. output( "\tlwz %s, %d(%s)\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
  1006. output( "\tmtlr %s\n", ppc_reg(0));
  1007. output( "\taddi %s, %s, %d\n", ppc_reg(1), ppc_reg(1), 48+extra_stack_storage);
  1008. /* branch to ctr register. */
  1009. output( "\tbctr\n");
  1010. break;
  1011. }
  1012. output_cfi( ".cfi_endproc" );
  1013. output_function_size( "__wine_delay_load_asm" );
  1014. output( "\n" );
  1015. idx = 0;
  1016. LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
  1017. {
  1018. for (j = 0; j < import->nb_imports; j++)
  1019. {
  1020. struct import_func *func = &import->imports[j];
  1021. const char *name = func->name ? func->name : func->export_name;
  1022. output( ".L__wine_delay_imp_%s_%s:\n", import->c_name, name );
  1023. output_cfi( ".cfi_startproc" );
  1024. switch(target_cpu)
  1025. {
  1026. case CPU_x86:
  1027. output( "\tmovl $%d, %%eax\n", (idx << 16) | j );
  1028. output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
  1029. break;
  1030. case CPU_x86_64:
  1031. output( "\tmovq $%d,%%rax\n", (idx << 16) | j );
  1032. output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
  1033. break;
  1034. case CPU_ARM:
  1035. {
  1036. unsigned int mask, count = 0, val = (idx << 16) | j;
  1037. for (mask = 0xff; mask; mask <<= 8)
  1038. if (val & mask) output( "\t%s IP,#%u\n", count++ ? "add" : "mov", val & mask );
  1039. if (!count) output( "\tmov IP,#0\n" );
  1040. output( "\tb %s\n", asm_name("__wine_delay_load_asm") );
  1041. break;
  1042. }
  1043. case CPU_ARM64:
  1044. output( "\tstp x6, x7, [sp,#-80]!\n" );
  1045. output( "\tstp x4, x5, [sp,#48]\n" );
  1046. output( "\tstp x2, x3, [sp,#32]\n" );
  1047. output( "\tstp x0, x1, [sp,#16]\n" );
  1048. output( "\tmov x0, #%d\n", idx );
  1049. output( "\tmov x1, #16384\n" );
  1050. output( "\tmul x1, x0, x1\n" );
  1051. output( "\tmov x0, x1\n" );
  1052. output( "\tmov x1, #4\n" );
  1053. output( "\tmul x1, x0, x1\n" );
  1054. output( "\tmov x0, x1\n" );
  1055. output( "\tadd x0, x0, #%d\n", j );
  1056. output( "\tadr x9, %s\n", asm_name("__wine_delay_load_asm") );
  1057. output( "\tbr x9\n" );
  1058. break;
  1059. case CPU_POWERPC:
  1060. switch(target_platform)
  1061. {
  1062. case PLATFORM_APPLE:
  1063. /* On Darwin we can use r0 and r2 */
  1064. /* Upper part in r2 */
  1065. output( "\tlis %s, %d\n", ppc_reg(2), idx);
  1066. /* Lower part + r2 -> r0, Note we can't use r0 directly */
  1067. output( "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(2), j);
  1068. output( "\tb %s\n", asm_name("__wine_delay_load_asm") );
  1069. break;
  1070. default:
  1071. /* On linux we can't use r2 since r2 is not a scratch register (hold the TOC) */
  1072. /* Save r13 on the stack */
  1073. output( "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1));
  1074. output( "\tstw %s, 0(%s)\n", ppc_reg(13), ppc_reg(1));
  1075. /* Upper part in r13 */
  1076. output( "\tlis %s, %d\n", ppc_reg(13), idx);
  1077. /* Lower part + r13 -> r0, Note we can't use r0 directly */
  1078. output( "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(13), j);
  1079. /* Restore r13 */
  1080. output( "\tstw %s, 0(%s)\n", ppc_reg(13), ppc_reg(1));
  1081. output( "\taddic %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1));
  1082. output( "\tb %s\n", asm_name("__wine_delay_load_asm") );
  1083. break;
  1084. }
  1085. break;
  1086. }
  1087. output_cfi( ".cfi_endproc" );
  1088. }
  1089. idx++;
  1090. }
  1091. output_function_size( delayed_import_loaders );
  1092. output( "\n\t.align %d\n", get_alignment(get_ptr_size()) );
  1093. output( "%s:\n", asm_name(delayed_import_thunks));
  1094. pos = 0;
  1095. LIST_FOR_EACH_ENTRY( import, &dll_delayed, struct import, entry )
  1096. {
  1097. for (j = 0; j < import->nb_imports; j++, pos += get_ptr_size())
  1098. {
  1099. struct import_func *func = &import->imports[j];
  1100. output_import_thunk( func->name ? func->name : func->export_name,
  1101. ".L__wine_delay_IAT", pos );
  1102. }
  1103. }
  1104. output_function_size( delayed_import_thunks );
  1105. }
  1106. /* output import stubs for exported entry points that link to external symbols */
  1107. static void output_external_link_imports( DLLSPEC *spec )
  1108. {
  1109. unsigned int i, pos;
  1110. if (!ext_link_imports.count) return; /* nothing to do */
  1111. sort_names( &ext_link_imports );
  1112. /* get rid of duplicate names */
  1113. for (i = 1; i < ext_link_imports.count; i++)
  1114. {
  1115. if (!strcmp( ext_link_imports.str[i-1], ext_link_imports.str[i] ))
  1116. remove_name( &ext_link_imports, i-- );
  1117. }
  1118. output( "\n/* external link thunks */\n\n" );
  1119. output( "\t.data\n" );
  1120. output( "\t.align %d\n", get_alignment(get_ptr_size()) );
  1121. output( ".L__wine_spec_external_links:\n" );
  1122. for (i = 0; i < ext_link_imports.count; i++)
  1123. output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name(ext_link_imports.str[i]) );
  1124. output( "\n\t.text\n" );
  1125. output( "\t.align %d\n", get_alignment(get_ptr_size()) );
  1126. output( "%s:\n", asm_name("__wine_spec_external_link_thunks") );
  1127. for (i = pos = 0; i < ext_link_imports.count; i++)
  1128. {
  1129. char *buffer = strmake( "__wine_spec_ext_link_%s", ext_link_imports.str[i] );
  1130. output_import_thunk( buffer, ".L__wine_spec_external_links", pos );
  1131. free( buffer );
  1132. pos += get_ptr_size();
  1133. }
  1134. output_function_size( "__wine_spec_external_link_thunks" );
  1135. }
  1136. /*******************************************************************
  1137. * output_stubs
  1138. *
  1139. * Output the functions for stub entry points
  1140. */
  1141. void output_stubs( DLLSPEC *spec )
  1142. {
  1143. const char *name, *exp_name;
  1144. int i;
  1145. if (!has_stubs( spec )) return;
  1146. output( "\n/* stub functions */\n\n" );
  1147. output( "\t.text\n" );
  1148. for (i = 0; i < spec->nb_entry_points; i++)
  1149. {
  1150. ORDDEF *odp = &spec->entry_points[i];
  1151. if (odp->type != TYPE_STUB) continue;
  1152. name = get_stub_name( odp, spec );
  1153. exp_name = odp->name ? odp->name : odp->export_name;
  1154. output( "\t.align %d\n", get_alignment(4) );
  1155. output( "\t%s\n", func_declaration(name) );
  1156. output( "%s:\n", asm_name(name) );
  1157. output_cfi( ".cfi_startproc" );
  1158. switch (target_cpu)
  1159. {
  1160. case CPU_x86:
  1161. /* flesh out the stub a bit to make safedisc happy */
  1162. output(" \tnop\n" );
  1163. output(" \tnop\n" );
  1164. output(" \tnop\n" );
  1165. output(" \tnop\n" );
  1166. output(" \tnop\n" );
  1167. output(" \tnop\n" );
  1168. output(" \tnop\n" );
  1169. output(" \tnop\n" );
  1170. output(" \tnop\n" );
  1171. output( "\tsubl $12,%%esp\n" );
  1172. output_cfi( ".cfi_adjust_cfa_offset 12" );
  1173. if (UsePIC)
  1174. {
  1175. output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
  1176. output( "1:" );
  1177. needs_get_pc_thunk = 1;
  1178. if (exp_name)
  1179. {
  1180. output( "\tleal .L%s_string-1b(%%eax),%%ecx\n", name );
  1181. output( "\tmovl %%ecx,4(%%esp)\n" );
  1182. }
  1183. else
  1184. output( "\tmovl $%d,4(%%esp)\n", odp->ordinal );
  1185. output( "\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
  1186. output( "\tmovl %%ecx,(%%esp)\n" );
  1187. }
  1188. else
  1189. {
  1190. if (exp_name)
  1191. output( "\tmovl $.L%s_string,4(%%esp)\n", name );
  1192. else
  1193. output( "\tmovl $%d,4(%%esp)\n", odp->ordinal );
  1194. output( "\tmovl $.L__wine_spec_file_name,(%%esp)\n" );
  1195. }
  1196. output( "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
  1197. break;
  1198. case CPU_x86_64:
  1199. output( "\tsubq $0x28,%%rsp\n" );
  1200. output_cfi( ".cfi_adjust_cfa_offset 8" );
  1201. output( "\tleaq .L__wine_spec_file_name(%%rip),%%rcx\n" );
  1202. if (exp_name)
  1203. output( "leaq .L%s_string(%%rip),%%rdx\n", name );
  1204. else
  1205. output( "\tmovq $%d,%%rdx\n", odp->ordinal );
  1206. output( "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
  1207. break;
  1208. case CPU_ARM:
  1209. output( "\tldr r0,2f\n");
  1210. output( "\tadd r0,PC\n");
  1211. output( "\tldr r1,2f+4\n");
  1212. output( "1:" );
  1213. if (exp_name) output( "\tadd r1,PC\n");
  1214. output( "\tbl %s\n", asm_name("__wine_spec_unimplemented_stub") );
  1215. output( "2:\t.long .L__wine_spec_file_name-1b\n" );
  1216. if (exp_name) output( "\t.long .L%s_string-2b\n", name );
  1217. else output( "\t.long %u\n", odp->ordinal );
  1218. break;
  1219. case CPU_ARM64:
  1220. output( "\tadrp x0, .L__wine_spec_file_name\n" );
  1221. output( "\tadd x0, x0, #:lo12:.L__wine_spec_file_name\n" );
  1222. if (exp_name)
  1223. {
  1224. output( "\tadrp x1, .L%s_string\n", name );
  1225. output( "\tadd x1, x1, #:lo12:.L%s_string\n", name );
  1226. }
  1227. else
  1228. output( "\tmov x1, %u\n", odp->ordinal );
  1229. output( "\tadrp x2, %s\n", asm_name("__wine_spec_unimplemented_stub") );
  1230. output( "\tadd x2, x2, #:lo12:%s\n", asm_name("__wine_spec_unimplemented_stub") );
  1231. output( "\tblr x2\n" );
  1232. break;
  1233. default:
  1234. assert(0);
  1235. }
  1236. output_cfi( ".cfi_endproc" );
  1237. output_function_size( name );
  1238. }
  1239. output( "\t%s\n", get_asm_string_section() );
  1240. output( ".L__wine_spec_file_name:\n" );
  1241. output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
  1242. for (i = 0; i < spec->nb_entry_points; i++)
  1243. {
  1244. ORDDEF *odp = &spec->entry_points[i];
  1245. if (odp->type != TYPE_STUB) continue;
  1246. exp_name = odp->name ? odp->name : odp->export_name;
  1247. if (exp_name)
  1248. {
  1249. name = get_stub_name( odp, spec );
  1250. output( ".L%s_string:\n", name );
  1251. output( "\t%s \"%s\"\n", get_asm_string_keyword(), exp_name );
  1252. }
  1253. }
  1254. }
  1255. /* output the import and delayed import tables of a Win32 module */
  1256. void output_imports( DLLSPEC *spec )
  1257. {
  1258. if (target_platform == PLATFORM_WINDOWS) return;
  1259. output_immediate_imports();
  1260. output_delayed_imports( spec );
  1261. output_immediate_import_thunks();
  1262. output_delayed_import_thunks( spec );
  1263. output_external_link_imports( spec );
  1264. }
  1265. /* create a new asm temp file */
  1266. static void new_output_as_file(void)
  1267. {
  1268. char *name;
  1269. if (output_file) fclose( output_file );
  1270. name = open_temp_output_file( ".s" );
  1271. strarray_add( &as_files, name, NULL );
  1272. }
  1273. /* assemble all the asm files */
  1274. static void assemble_files( const char *prefix )
  1275. {
  1276. unsigned int i;
  1277. if (output_file) fclose( output_file );
  1278. output_file = NULL;
  1279. for (i = 0; i < as_files.count; i++)
  1280. {
  1281. char *obj = get_temp_file_name( prefix, ".o" );
  1282. assemble_file( as_files.str[i], obj );
  1283. as_files.str[i] = obj;
  1284. }
  1285. }
  1286. /* build a library from the current asm files and any additional object files in argv */
  1287. static void build_library( const char *output_name, char **argv, int create )
  1288. {
  1289. struct strarray args = find_tool( "ar", NULL );
  1290. struct strarray ranlib = find_tool( "ranlib", NULL );
  1291. strarray_add( &args, create ? "rc" : "r", output_name, NULL );
  1292. strarray_addall( &args, as_files );
  1293. strarray_addv( &args, argv );
  1294. if (create) unlink( output_name );
  1295. spawn( args );
  1296. strarray_add( &ranlib, output_name, NULL );
  1297. spawn( ranlib );
  1298. }
  1299. /* create a Windows-style import library */
  1300. static void build_windows_import_lib( DLLSPEC *spec )
  1301. {
  1302. struct strarray args;
  1303. char *def_file;
  1304. const char *as_flags, *m_flag;
  1305. def_file = open_temp_output_file( ".def" );
  1306. output_def_file( spec, 1 );
  1307. fclose( output_file );
  1308. args = find_tool( "dlltool", NULL );
  1309. switch (target_cpu)
  1310. {
  1311. case CPU_x86:
  1312. m_flag = "i386";
  1313. as_flags = "--as-flags=--32";
  1314. break;
  1315. case CPU_x86_64:
  1316. m_flag = "i386:x86-64";
  1317. as_flags = "--as-flags=--64";
  1318. break;
  1319. default:
  1320. m_flag = NULL;
  1321. break;
  1322. }
  1323. strarray_add( &args, "-k", strendswith( output_file_name, ".delay.a" ) ? "-y" : "-l",
  1324. output_file_name, "-d", def_file, NULL );
  1325. if (m_flag)
  1326. strarray_add( &args, "-m", m_flag, as_flags, NULL );
  1327. spawn( args );
  1328. }
  1329. /* create a Unix-style import library */
  1330. static void build_unix_import_lib( DLLSPEC *spec )
  1331. {
  1332. static const char valid_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._@";
  1333. int i, total;
  1334. const char *name, *prefix;
  1335. char *dll_name = xstrdup( spec->file_name );
  1336. if (strendswith( dll_name, ".dll" )) dll_name[strlen(dll_name) - 4] = 0;
  1337. if (strspn( dll_name, valid_chars ) < strlen( dll_name ))
  1338. fatal_error( "%s contains invalid characters\n", spec->file_name );
  1339. /* entry points */
  1340. for (i = total = 0; i < spec->nb_entry_points; i++)
  1341. {
  1342. const ORDDEF *odp = &spec->entry_points[i];
  1343. if (odp->name) name = odp->name;
  1344. else if (odp->export_name) name = odp->export_name;
  1345. else continue;
  1346. if (odp->flags & FLAG_PRIVATE) continue;
  1347. total++;
  1348. /* C++ mangled names cannot be imported */
  1349. if (strpbrk( name, "?@" )) continue;
  1350. switch(odp->type)
  1351. {
  1352. case TYPE_VARARGS:
  1353. case TYPE_CDECL:
  1354. case TYPE_STDCALL:
  1355. prefix = (!odp->name || (odp->flags & FLAG_ORDINAL)) ? import_ord_prefix : import_func_prefix;
  1356. new_output_as_file();
  1357. output( "\t.text\n" );
  1358. output( "\n\t.align %d\n", get_alignment( get_ptr_size() ));
  1359. output( "\t%s\n", func_declaration( name ) );
  1360. output( "%s\n", asm_globl( name ) );
  1361. output( "\t%s %s%s$%u$%s\n", get_asm_ptr_keyword(),
  1362. asm_name( prefix ), dll_name, odp->ordinal, name );
  1363. output_function_size( name );
  1364. output_gnu_stack_note();
  1365. break;
  1366. default:
  1367. break;
  1368. }
  1369. }
  1370. if (!total) warning( "%s: Import library doesn't export anything\n", spec->file_name );
  1371. if (!as_files.count) /* create a dummy file to avoid empty import libraries */
  1372. {
  1373. new_output_as_file();
  1374. output( "\t.text\n" );
  1375. }
  1376. assemble_files( spec->file_name );
  1377. free( dll_name );
  1378. }
  1379. /* output an import library for a Win32 module and additional object files */
  1380. void output_static_lib( DLLSPEC *spec, char **argv )
  1381. {
  1382. if (target_platform == PLATFORM_WINDOWS)
  1383. {
  1384. if (spec) build_windows_import_lib( spec );
  1385. if (argv[0] || !spec) build_library( output_file_name, argv, !spec );
  1386. }
  1387. else
  1388. {
  1389. if (spec) build_unix_import_lib( spec );
  1390. build_library( output_file_name, argv, 1 );
  1391. }
  1392. }