spec32.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  1. /*
  2. * 32-bit spec files
  3. *
  4. * Copyright 1993 Robert J. Amstadt
  5. * Copyright 1995 Martin von Loewis
  6. * Copyright 1995, 1996, 1997 Alexandre Julliard
  7. * Copyright 1997 Eric Youngdale
  8. * Copyright 1999 Ulrich Weigand
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation; either
  13. * version 2.1 of the License, or (at your option) any later version.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #include "config.h"
  25. #include "wine/port.h"
  26. #include <assert.h>
  27. #include <ctype.h>
  28. #include <stdarg.h>
  29. #include <string.h>
  30. #include "build.h"
  31. #define IMAGE_FILE_MACHINE_UNKNOWN 0
  32. #define IMAGE_FILE_MACHINE_I386 0x014c
  33. #define IMAGE_FILE_MACHINE_POWERPC 0x01f0
  34. #define IMAGE_FILE_MACHINE_AMD64 0x8664
  35. #define IMAGE_FILE_MACHINE_ARMNT 0x01C4
  36. #define IMAGE_FILE_MACHINE_ARM64 0xaa64
  37. #define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224
  38. #define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240
  39. #define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
  40. #define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
  41. #define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
  42. int needs_get_pc_thunk = 0;
  43. static const char builtin_signature[32] = "Wine builtin DLL";
  44. static const char fakedll_signature[32] = "Wine placeholder DLL";
  45. /* check if entry point needs a relay thunk */
  46. static inline int needs_relay( const ORDDEF *odp )
  47. {
  48. /* skip nonexistent entry points */
  49. if (!odp) return 0;
  50. /* skip non-functions */
  51. switch (odp->type)
  52. {
  53. case TYPE_STDCALL:
  54. case TYPE_CDECL:
  55. break;
  56. case TYPE_STUB:
  57. if (odp->u.func.nb_args != -1) break;
  58. /* fall through */
  59. default:
  60. return 0;
  61. }
  62. /* skip norelay and forward entry points */
  63. if (odp->flags & (FLAG_NORELAY|FLAG_FORWARD)) return 0;
  64. return 1;
  65. }
  66. static int is_float_arg( const ORDDEF *odp, int arg )
  67. {
  68. if (arg >= odp->u.func.nb_args) return 0;
  69. return (odp->u.func.args[arg] == ARG_FLOAT || odp->u.func.args[arg] == ARG_DOUBLE);
  70. }
  71. /* check if dll will output relay thunks */
  72. static int has_relays( DLLSPEC *spec )
  73. {
  74. int i;
  75. if (target_cpu != CPU_x86 && target_cpu != CPU_x86_64 &&
  76. target_cpu != CPU_ARM && target_cpu != CPU_ARM64)
  77. return 0;
  78. for (i = spec->base; i <= spec->limit; i++)
  79. {
  80. ORDDEF *odp = spec->ordinals[i];
  81. if (needs_relay( odp )) return 1;
  82. }
  83. return 0;
  84. }
  85. static int cmp_func_args( const void *p1, const void *p2 )
  86. {
  87. const ORDDEF *odp1 = *(const ORDDEF **)p1;
  88. const ORDDEF *odp2 = *(const ORDDEF **)p2;
  89. return odp2->u.func.nb_args - odp1->u.func.nb_args;
  90. }
  91. static void get_arg_string( ORDDEF *odp, char str[MAX_ARGUMENTS + 1] )
  92. {
  93. int i;
  94. for (i = 0; i < odp->u.func.nb_args; i++)
  95. {
  96. switch (odp->u.func.args[i])
  97. {
  98. case ARG_STR: str[i] = 's'; break;
  99. case ARG_WSTR: str[i] = 'w'; break;
  100. case ARG_FLOAT: str[i] = 'f'; break;
  101. case ARG_DOUBLE: str[i] = 'd'; break;
  102. case ARG_INT64:
  103. case ARG_INT128:
  104. if (get_ptr_size() == 4)
  105. {
  106. str[i] = (odp->u.func.args[i] == ARG_INT64) ? 'j' : 'k';
  107. break;
  108. }
  109. /* fall through */
  110. case ARG_LONG:
  111. case ARG_PTR:
  112. default:
  113. str[i] = 'i';
  114. break;
  115. }
  116. }
  117. if (odp->flags & (FLAG_THISCALL | FLAG_FASTCALL)) str[0] = 't';
  118. if ((odp->flags & FLAG_FASTCALL) && odp->u.func.nb_args > 1) str[1] = 't';
  119. /* append return value */
  120. if (get_ptr_size() == 4 && (odp->flags & FLAG_RET64))
  121. strcpy( str + i, "J" );
  122. else
  123. strcpy( str + i, "I" );
  124. }
  125. static void output_data_directories( const char *names[16] )
  126. {
  127. int i;
  128. for (i = 0; i < 16; i++)
  129. {
  130. if (names[i])
  131. {
  132. output_rva( "%s", names[i] );
  133. output( "\t.long %s_end - %s\n", names[i], names[i] );
  134. }
  135. else output( "\t.long 0,0\n" );
  136. }
  137. }
  138. /*******************************************************************
  139. * build_args_string
  140. */
  141. static char *build_args_string( DLLSPEC *spec )
  142. {
  143. int i, count = 0, len = 1;
  144. char *p, *buffer;
  145. char str[MAX_ARGUMENTS + 2];
  146. ORDDEF **funcs;
  147. funcs = xmalloc( (spec->limit + 1 - spec->base) * sizeof(*funcs) );
  148. for (i = spec->base; i <= spec->limit; i++)
  149. {
  150. ORDDEF *odp = spec->ordinals[i];
  151. if (!needs_relay( odp )) continue;
  152. funcs[count++] = odp;
  153. len += odp->u.func.nb_args + 1;
  154. }
  155. /* sort functions by decreasing number of arguments */
  156. qsort( funcs, count, sizeof(*funcs), cmp_func_args );
  157. buffer = xmalloc( len );
  158. buffer[0] = 0;
  159. /* build the arguments string, reusing substrings where possible */
  160. for (i = 0; i < count; i++)
  161. {
  162. get_arg_string( funcs[i], str );
  163. if (!(p = strstr( buffer, str )))
  164. {
  165. p = buffer + strlen( buffer );
  166. strcpy( p, str );
  167. }
  168. funcs[i]->u.func.args_str_offset = p - buffer;
  169. }
  170. free( funcs );
  171. return buffer;
  172. }
  173. /*******************************************************************
  174. * output_relay_debug
  175. *
  176. * Output entry points for relay debugging
  177. */
  178. static void output_relay_debug( DLLSPEC *spec )
  179. {
  180. int i;
  181. /* first the table of entry point offsets */
  182. output( "\t%s\n", get_asm_rodata_section() );
  183. output( "\t.align %d\n", get_alignment(4) );
  184. output( ".L__wine_spec_relay_entry_point_offsets:\n" );
  185. for (i = spec->base; i <= spec->limit; i++)
  186. {
  187. ORDDEF *odp = spec->ordinals[i];
  188. if (needs_relay( odp ))
  189. output( "\t.long .L__wine_spec_relay_entry_point_%d-__wine_spec_relay_entry_points\n", i );
  190. else
  191. output( "\t.long 0\n" );
  192. }
  193. /* then the strings of argument types */
  194. output( ".L__wine_spec_relay_args_string:\n" );
  195. output( "\t%s \"%s\"\n", get_asm_string_keyword(), build_args_string( spec ));
  196. /* then the relay thunks */
  197. output( "\t.text\n" );
  198. output( "__wine_spec_relay_entry_points:\n" );
  199. output( "\tnop\n" ); /* to avoid 0 offset */
  200. for (i = spec->base; i <= spec->limit; i++)
  201. {
  202. ORDDEF *odp = spec->ordinals[i];
  203. if (!needs_relay( odp )) continue;
  204. switch (target_cpu)
  205. {
  206. case CPU_x86:
  207. output( "\t.align %d\n", get_alignment(4) );
  208. output( "\t.long 0x90909090,0x90909090\n" );
  209. output( ".L__wine_spec_relay_entry_point_%d:\n", i );
  210. output_cfi( ".cfi_startproc" );
  211. output( "\t.byte 0x8b,0xff,0x55,0x8b,0xec,0x5d\n" ); /* hotpatch prolog */
  212. if (odp->flags & (FLAG_THISCALL | FLAG_FASTCALL)) /* add the register arguments */
  213. {
  214. output( "\tpopl %%eax\n" );
  215. if ((odp->flags & FLAG_FASTCALL) && get_args_size( odp ) > 4) output( "\tpushl %%edx\n" );
  216. output( "\tpushl %%ecx\n" );
  217. output( "\tpushl %%eax\n" );
  218. }
  219. output( "\tpushl $%u\n", (odp->u.func.args_str_offset << 16) | (i - spec->base) );
  220. output_cfi( ".cfi_adjust_cfa_offset 4" );
  221. if (UsePIC)
  222. {
  223. output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
  224. output( "1:\tleal .L__wine_spec_relay_descr-1b(%%eax),%%eax\n" );
  225. needs_get_pc_thunk = 1;
  226. }
  227. else output( "\tmovl $.L__wine_spec_relay_descr,%%eax\n" );
  228. output( "\tpushl %%eax\n" );
  229. output_cfi( ".cfi_adjust_cfa_offset 4" );
  230. output( "\tcall *4(%%eax)\n" );
  231. output_cfi( ".cfi_adjust_cfa_offset -8" );
  232. if (odp->type == TYPE_STDCALL)
  233. output( "\tret $%u\n", get_args_size( odp ));
  234. else
  235. output( "\tret\n" );
  236. output_cfi( ".cfi_endproc" );
  237. break;
  238. case CPU_ARM:
  239. {
  240. unsigned int mask, val, count = 0;
  241. int j, has_float = 0;
  242. if (strcmp( float_abi_option, "soft" ))
  243. for (j = 0; j < odp->u.func.nb_args && !has_float; j++)
  244. has_float = is_float_arg( odp, j );
  245. val = (odp->u.func.args_str_offset << 16) | (i - spec->base);
  246. output( "\t.align %d\n", get_alignment(4) );
  247. output( ".L__wine_spec_relay_entry_point_%d:\n", i );
  248. output_cfi( ".cfi_startproc" );
  249. output( "\tpush {r0-r3}\n" );
  250. output( "\tmov r2, SP\n");
  251. if (has_float) output( "\tvpush {s0-s15}\n" );
  252. output( "\tpush {LR}\n" );
  253. output( "\tsub SP, #4\n");
  254. for (mask = 0xff; mask; mask <<= 8)
  255. if (val & mask) output( "\t%s r1,#%u\n", count++ ? "add" : "mov", val & mask );
  256. if (!count) output( "\tmov r1,#0\n" );
  257. output( "\tldr r0, 2f\n");
  258. output( "\tadd r0, PC\n");
  259. output( "\tldr IP, [r0, #4]\n");
  260. output( "1:\tblx IP\n");
  261. output( "\tldr IP, [SP, #4]\n" );
  262. output( "\tadd SP, #%u\n", 24 + (has_float ? 64 : 0) );
  263. output( "\tbx IP\n");
  264. output( "2:\t.long .L__wine_spec_relay_descr-1b\n" );
  265. output_cfi( ".cfi_endproc" );
  266. break;
  267. }
  268. case CPU_ARM64:
  269. output( "\t.align %d\n", get_alignment(4) );
  270. output( ".L__wine_spec_relay_entry_point_%d:\n", i );
  271. output_cfi( ".cfi_startproc" );
  272. switch (odp->u.func.nb_args)
  273. {
  274. default:
  275. case 8:
  276. case 7: output( "\tstp x6, x7, [SP,#-16]!\n" );
  277. /* fall through */
  278. case 6:
  279. case 5: output( "\tstp x4, x5, [SP,#-16]!\n" );
  280. /* fall through */
  281. case 4:
  282. case 3: output( "\tstp x2, x3, [SP,#-16]!\n" );
  283. /* fall through */
  284. case 2:
  285. case 1: output( "\tstp x0, x1, [SP,#-16]!\n" );
  286. /* fall through */
  287. case 0: break;
  288. }
  289. output( "\tmov x2, SP\n");
  290. output( "\tstp x29, x30, [SP,#-16]!\n" );
  291. output( "\tstp x8, x9, [SP,#-16]!\n" );
  292. output( "\tmov w1, #%u\n", odp->u.func.args_str_offset << 16 );
  293. if (i - spec->base) output( "\tadd w1, w1, #%u\n", i - spec->base );
  294. output( "\tadrp x0, .L__wine_spec_relay_descr\n");
  295. output( "\tadd x0, x0, #:lo12:.L__wine_spec_relay_descr\n");
  296. output( "\tldr x3, [x0, #8]\n");
  297. output( "\tblr x3\n");
  298. output( "\tadd SP, SP, #16\n" );
  299. output( "\tldp x29, x30, [SP], #16\n" );
  300. if (odp->u.func.nb_args)
  301. output( "\tadd SP, SP, #%u\n", 8 * ((min(odp->u.func.nb_args, 8) + 1) & ~1) );
  302. output( "\tret\n");
  303. output_cfi( ".cfi_endproc" );
  304. break;
  305. case CPU_x86_64:
  306. output( "\t.align %d\n", get_alignment(4) );
  307. output( "\t.long 0x90909090,0x90909090\n" );
  308. output( ".L__wine_spec_relay_entry_point_%d:\n", i );
  309. output_cfi( ".cfi_startproc" );
  310. switch (odp->u.func.nb_args)
  311. {
  312. default: output( "\tmovq %%%s,32(%%rsp)\n", is_float_arg( odp, 3 ) ? "xmm3" : "r9" );
  313. /* fall through */
  314. case 3: output( "\tmovq %%%s,24(%%rsp)\n", is_float_arg( odp, 2 ) ? "xmm2" : "r8" );
  315. /* fall through */
  316. case 2: output( "\tmovq %%%s,16(%%rsp)\n", is_float_arg( odp, 1 ) ? "xmm1" : "rdx" );
  317. /* fall through */
  318. case 1: output( "\tmovq %%%s,8(%%rsp)\n", is_float_arg( odp, 0 ) ? "xmm0" : "rcx" );
  319. /* fall through */
  320. case 0: break;
  321. }
  322. output( "\tmovl $%u,%%edx\n", (odp->u.func.args_str_offset << 16) | (i - spec->base) );
  323. output( "\tleaq .L__wine_spec_relay_descr(%%rip),%%rcx\n" );
  324. output( "\tcallq *8(%%rcx)\n" );
  325. output( "\tret\n" );
  326. output_cfi( ".cfi_endproc" );
  327. break;
  328. default:
  329. assert(0);
  330. }
  331. }
  332. }
  333. /*******************************************************************
  334. * output_exports
  335. *
  336. * Output the export table for a Win32 module.
  337. */
  338. void output_exports( DLLSPEC *spec )
  339. {
  340. int i, fwd_size = 0;
  341. int needs_imports = 0;
  342. int needs_relay = has_relays( spec );
  343. int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
  344. const char *func_ptr = (target_platform == PLATFORM_WINDOWS) ? ".rva" : get_asm_ptr_keyword();
  345. const char *name;
  346. if (!nr_exports) return;
  347. output( "\n/* export table */\n\n" );
  348. output( "\t%s\n", get_asm_export_section() );
  349. output( "\t.align %d\n", get_alignment(4) );
  350. output( ".L__wine_spec_exports:\n" );
  351. /* export directory header */
  352. output( "\t.long 0\n" ); /* Characteristics */
  353. output( "\t.long 0\n" ); /* TimeDateStamp */
  354. output( "\t.long 0\n" ); /* MajorVersion/MinorVersion */
  355. output_rva( ".L__wine_spec_exp_names" ); /* Name */
  356. output( "\t.long %u\n", spec->base ); /* Base */
  357. output( "\t.long %u\n", nr_exports ); /* NumberOfFunctions */
  358. output( "\t.long %u\n", spec->nb_names ); /* NumberOfNames */
  359. output_rva( ".L__wine_spec_exports_funcs " ); /* AddressOfFunctions */
  360. if (spec->nb_names)
  361. {
  362. output_rva( ".L__wine_spec_exp_name_ptrs" ); /* AddressOfNames */
  363. output_rva( ".L__wine_spec_exp_ordinals" ); /* AddressOfNameOrdinals */
  364. }
  365. else
  366. {
  367. output( "\t.long 0\n" ); /* AddressOfNames */
  368. output( "\t.long 0\n" ); /* AddressOfNameOrdinals */
  369. }
  370. /* output the function pointers */
  371. output( "\n.L__wine_spec_exports_funcs:\n" );
  372. for (i = spec->base; i <= spec->limit; i++)
  373. {
  374. ORDDEF *odp = spec->ordinals[i];
  375. if (!odp) output( "\t%s 0\n",
  376. (target_platform == PLATFORM_WINDOWS) ? ".long" : get_asm_ptr_keyword() );
  377. else switch(odp->type)
  378. {
  379. case TYPE_EXTERN:
  380. case TYPE_STDCALL:
  381. case TYPE_VARARGS:
  382. case TYPE_CDECL:
  383. if (odp->flags & FLAG_FORWARD)
  384. {
  385. output( "\t%s .L__wine_spec_forwards+%u\n", func_ptr, fwd_size );
  386. fwd_size += strlen(odp->link_name) + 1;
  387. }
  388. else if ((odp->flags & FLAG_IMPORT) && (target_cpu == CPU_x86 || target_cpu == CPU_x86_64))
  389. {
  390. name = odp->name ? odp->name : odp->export_name;
  391. if (name) output( "\t%s %s_%s\n", func_ptr, asm_name("__wine_spec_imp"), name );
  392. else output( "\t%s %s_%u\n", func_ptr, asm_name("__wine_spec_imp"), i );
  393. needs_imports = 1;
  394. }
  395. else if (odp->flags & FLAG_EXT_LINK)
  396. {
  397. output( "\t%s %s_%s\n", func_ptr, asm_name("__wine_spec_ext_link"), odp->link_name );
  398. }
  399. else
  400. {
  401. output( "\t%s %s\n", func_ptr, asm_name( get_link_name( odp )));
  402. }
  403. break;
  404. case TYPE_STUB:
  405. output( "\t%s %s\n", func_ptr, asm_name( get_stub_name( odp, spec )) );
  406. break;
  407. default:
  408. assert(0);
  409. }
  410. }
  411. if (spec->nb_names)
  412. {
  413. /* output the function name pointers */
  414. int namepos = strlen(spec->file_name) + 1;
  415. output( "\n.L__wine_spec_exp_name_ptrs:\n" );
  416. for (i = 0; i < spec->nb_names; i++)
  417. {
  418. output_rva( ".L__wine_spec_exp_names + %u", namepos );
  419. namepos += strlen(spec->names[i]->name) + 1;
  420. }
  421. /* output the function ordinals */
  422. output( "\n.L__wine_spec_exp_ordinals:\n" );
  423. for (i = 0; i < spec->nb_names; i++)
  424. {
  425. output( "\t.short %d\n", spec->names[i]->ordinal - spec->base );
  426. }
  427. if (spec->nb_names % 2)
  428. {
  429. output( "\t.short 0\n" );
  430. }
  431. }
  432. if (needs_relay)
  433. {
  434. output( "\t.long 0xdeb90002\n" ); /* magic */
  435. if (target_platform == PLATFORM_WINDOWS) output_rva( ".L__wine_spec_relay_descr" );
  436. else output( "\t.long 0\n" );
  437. }
  438. /* output the export name strings */
  439. output( "\n.L__wine_spec_exp_names:\n" );
  440. output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
  441. for (i = 0; i < spec->nb_names; i++)
  442. output( "\t%s \"%s\"\n",
  443. get_asm_string_keyword(), spec->names[i]->name );
  444. /* output forward strings */
  445. if (fwd_size)
  446. {
  447. output( "\n.L__wine_spec_forwards:\n" );
  448. for (i = spec->base; i <= spec->limit; i++)
  449. {
  450. ORDDEF *odp = spec->ordinals[i];
  451. if (odp && (odp->flags & FLAG_FORWARD))
  452. output( "\t%s \"%s\"\n", get_asm_string_keyword(), odp->link_name );
  453. }
  454. }
  455. /* output relays */
  456. if (needs_relay)
  457. {
  458. if (target_platform == PLATFORM_WINDOWS)
  459. {
  460. output( "\t.data\n" );
  461. output( "\t.align %d\n", get_alignment(get_ptr_size()) );
  462. }
  463. else
  464. {
  465. output( "\t.align %d\n", get_alignment(get_ptr_size()) );
  466. output( ".L__wine_spec_exports_end:\n" );
  467. }
  468. output( ".L__wine_spec_relay_descr:\n" );
  469. output( "\t%s 0xdeb90002\n", get_asm_ptr_keyword() ); /* magic */
  470. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* relay func */
  471. output( "\t%s 0\n", get_asm_ptr_keyword() ); /* private data */
  472. output( "\t%s __wine_spec_relay_entry_points\n", get_asm_ptr_keyword() );
  473. output( "\t%s .L__wine_spec_relay_entry_point_offsets\n", get_asm_ptr_keyword() );
  474. output( "\t%s .L__wine_spec_relay_args_string\n", get_asm_ptr_keyword() );
  475. output_relay_debug( spec );
  476. }
  477. else if (target_platform != PLATFORM_WINDOWS)
  478. {
  479. output( "\t.align %d\n", get_alignment(get_ptr_size()) );
  480. output( ".L__wine_spec_exports_end:\n" );
  481. output( "\t%s 0\n", get_asm_ptr_keyword() );
  482. }
  483. /* output import thunks */
  484. if (!needs_imports) return;
  485. output( "\t.text\n" );
  486. for (i = spec->base; i <= spec->limit; i++)
  487. {
  488. ORDDEF *odp = spec->ordinals[i];
  489. if (!odp) continue;
  490. if (!(odp->flags & FLAG_IMPORT)) continue;
  491. name = odp->name ? odp->name : odp->export_name;
  492. output( "\t.align %d\n", get_alignment(4) );
  493. output( "\t.long 0x90909090,0x90909090\n" );
  494. if (name) output( "%s_%s:\n", asm_name("__wine_spec_imp"), name );
  495. else output( "%s_%u:\n", asm_name("__wine_spec_imp"), i );
  496. output_cfi( ".cfi_startproc" );
  497. switch (target_cpu)
  498. {
  499. case CPU_x86:
  500. output( "\t.byte 0x8b,0xff,0x55,0x8b,0xec,0x5d\n" ); /* hotpatch prolog */
  501. if (UsePIC)
  502. {
  503. output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
  504. output( "1:\tjmp *__imp_%s-1b(%%eax)\n", asm_name( get_link_name( odp )));
  505. needs_get_pc_thunk = 1;
  506. }
  507. else output( "\tjmp *__imp_%s\n", asm_name( get_link_name( odp )));
  508. break;
  509. case CPU_x86_64:
  510. output( "\t.byte 0x48\n" ); /* hotpatch prolog */
  511. output( "\tjmp *__imp_%s(%%rip)\n", asm_name( get_link_name( odp )));
  512. break;
  513. default:
  514. assert(0);
  515. }
  516. output_cfi( ".cfi_endproc" );
  517. }
  518. }
  519. /*******************************************************************
  520. * output_module
  521. *
  522. * Output the module data.
  523. */
  524. void output_module( DLLSPEC *spec )
  525. {
  526. int machine = 0;
  527. unsigned int page_size = get_page_size();
  528. const char *data_dirs[16] = { NULL };
  529. /* Reserve some space for the PE header */
  530. switch (target_platform)
  531. {
  532. case PLATFORM_WINDOWS:
  533. return; /* nothing to do */
  534. case PLATFORM_APPLE:
  535. output( "\t.text\n" );
  536. output( "\t.align %d\n", get_alignment(page_size) );
  537. output( "__wine_spec_pe_header:\n" );
  538. output( "\t.space 65536\n" );
  539. break;
  540. case PLATFORM_SOLARIS:
  541. output( "\n\t.section \".text\",\"ax\"\n" );
  542. output( "__wine_spec_pe_header:\n" );
  543. output( "\t.skip %u\n", 65536 + page_size );
  544. break;
  545. default:
  546. switch(target_cpu)
  547. {
  548. case CPU_x86:
  549. case CPU_x86_64:
  550. output( "\n\t.section \".init\",\"ax\"\n" );
  551. output( "\tjmp 1f\n" );
  552. break;
  553. case CPU_ARM:
  554. output( "\n\t.section \".text\",\"ax\"\n" );
  555. output( "\tb 1f\n" );
  556. break;
  557. case CPU_ARM64:
  558. case CPU_POWERPC:
  559. output( "\n\t.section \".init\",\"ax\"\n" );
  560. output( "\tb 1f\n" );
  561. break;
  562. }
  563. output( "__wine_spec_pe_header:\n" );
  564. output( "\t.skip %u\n", 65536 + page_size );
  565. output( "1:\n" );
  566. break;
  567. }
  568. /* Output the NT header */
  569. output( "\n\t.data\n" );
  570. output( "\t.align %d\n", get_alignment(get_ptr_size()) );
  571. output( "\t.globl %s\n", asm_name("__wine_spec_nt_header") );
  572. output( "%s:\n", asm_name("__wine_spec_nt_header") );
  573. output( ".L__wine_spec_rva_base:\n" );
  574. output( "\t.long 0x4550\n" ); /* Signature */
  575. switch(target_cpu)
  576. {
  577. case CPU_x86: machine = IMAGE_FILE_MACHINE_I386; break;
  578. case CPU_x86_64: machine = IMAGE_FILE_MACHINE_AMD64; break;
  579. case CPU_POWERPC: machine = IMAGE_FILE_MACHINE_POWERPC; break;
  580. case CPU_ARM: machine = IMAGE_FILE_MACHINE_ARMNT; break;
  581. case CPU_ARM64: machine = IMAGE_FILE_MACHINE_ARM64; break;
  582. }
  583. output( "\t.short 0x%04x\n", /* Machine */
  584. machine );
  585. output( "\t.short 0\n" ); /* NumberOfSections */
  586. output( "\t.long 0\n" ); /* TimeDateStamp */
  587. output( "\t.long 0\n" ); /* PointerToSymbolTable */
  588. output( "\t.long 0\n" ); /* NumberOfSymbols */
  589. output( "\t.short %d\n", /* SizeOfOptionalHeader */
  590. get_ptr_size() == 8 ? IMAGE_SIZEOF_NT_OPTIONAL64_HEADER : IMAGE_SIZEOF_NT_OPTIONAL32_HEADER );
  591. output( "\t.short 0x%04x\n", /* Characteristics */
  592. spec->characteristics );
  593. output( "\t.short 0x%04x\n", /* Magic */
  594. get_ptr_size() == 8 ? IMAGE_NT_OPTIONAL_HDR64_MAGIC : IMAGE_NT_OPTIONAL_HDR32_MAGIC );
  595. output( "\t.byte 7\n" ); /* MajorLinkerVersion */
  596. output( "\t.byte 10\n" ); /* MinorLinkerVersion */
  597. output( "\t.long 0\n" ); /* SizeOfCode */
  598. output( "\t.long 0\n" ); /* SizeOfInitializedData */
  599. output( "\t.long 0\n" ); /* SizeOfUninitializedData */
  600. /* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */
  601. output( "\t%s %s\n", /* AddressOfEntryPoint */
  602. get_asm_ptr_keyword(), spec->init_func ? asm_name(spec->init_func) : "0" );
  603. if (get_ptr_size() == 4)
  604. {
  605. output( "\t.long 0\n" ); /* BaseOfCode */
  606. output( "\t.long 0\n" ); /* BaseOfData */
  607. }
  608. output( "\t%s __wine_spec_pe_header\n", /* ImageBase */
  609. get_asm_ptr_keyword() );
  610. output( "\t.long %u\n", page_size ); /* SectionAlignment */
  611. output( "\t.long %u\n", page_size ); /* FileAlignment */
  612. output( "\t.short 1,0\n" ); /* Major/MinorOperatingSystemVersion */
  613. output( "\t.short 0,0\n" ); /* Major/MinorImageVersion */
  614. output( "\t.short %u,%u\n", /* Major/MinorSubsystemVersion */
  615. spec->subsystem_major, spec->subsystem_minor );
  616. output( "\t.long 0\n" ); /* Win32VersionValue */
  617. output_rva( "%s", asm_name("_end") ); /* SizeOfImage */
  618. output( "\t.long %u\n", page_size ); /* SizeOfHeaders */
  619. output( "\t.long 0\n" ); /* CheckSum */
  620. output( "\t.short 0x%04x\n", /* Subsystem */
  621. spec->subsystem );
  622. output( "\t.short 0x%04x\n", /* DllCharacteristics */
  623. spec->dll_characteristics );
  624. output( "\t%s %u,%u\n", /* SizeOfStackReserve/Commit */
  625. get_asm_ptr_keyword(), (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
  626. output( "\t%s %u,%u\n", /* SizeOfHeapReserve/Commit */
  627. get_asm_ptr_keyword(), (spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
  628. output( "\t.long 0\n" ); /* LoaderFlags */
  629. output( "\t.long 16\n" ); /* NumberOfRvaAndSizes */
  630. if (spec->base <= spec->limit)
  631. data_dirs[0] = ".L__wine_spec_exports"; /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */
  632. if (has_imports())
  633. data_dirs[1] = ".L__wine_spec_imports"; /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */
  634. if (spec->nb_resources)
  635. data_dirs[2] = ".L__wine_spec_resources"; /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
  636. output_data_directories( data_dirs );
  637. if (target_platform == PLATFORM_APPLE)
  638. output( "\t.lcomm %s,4\n", asm_name("_end") );
  639. }
  640. /*******************************************************************
  641. * output_spec32_file
  642. *
  643. * Build a Win32 C file from a spec file.
  644. */
  645. void output_spec32_file( DLLSPEC *spec )
  646. {
  647. needs_get_pc_thunk = 0;
  648. open_output_file();
  649. output_standard_file_header();
  650. output_module( spec );
  651. output_stubs( spec );
  652. output_exports( spec );
  653. output_imports( spec );
  654. if (needs_get_pc_thunk) output_get_pc_thunk();
  655. output_resources( spec );
  656. output_gnu_stack_note();
  657. close_output_file();
  658. }
  659. /*******************************************************************
  660. * output_fake_module
  661. *
  662. * Build a fake binary module from a spec file.
  663. */
  664. void output_fake_module( DLLSPEC *spec )
  665. {
  666. static const unsigned char dll_code_section[] = { 0x31, 0xc0, /* xor %eax,%eax */
  667. 0xc2, 0x0c, 0x00 }; /* ret $12 */
  668. static const unsigned char exe_code_section[] = { 0xb8, 0x01, 0x00, 0x00, 0x00, /* movl $1,%eax */
  669. 0xc2, 0x04, 0x00 }; /* ret $4 */
  670. const unsigned int page_size = get_page_size();
  671. const unsigned int section_align = page_size;
  672. const unsigned int file_align = 0x200;
  673. const unsigned int reloc_size = 8;
  674. const unsigned int lfanew = 0x40 + sizeof(fakedll_signature);
  675. const unsigned int nb_sections = 2 + (spec->nb_resources != 0);
  676. const unsigned int text_size = (spec->characteristics & IMAGE_FILE_DLL) ?
  677. sizeof(dll_code_section) : sizeof(exe_code_section);
  678. unsigned char *resources;
  679. unsigned int resources_size;
  680. unsigned int image_size = 3 * section_align;
  681. resolve_imports( spec );
  682. output_bin_resources( spec, 3 * section_align );
  683. resources = output_buffer;
  684. resources_size = output_buffer_pos;
  685. if (resources_size) image_size += (resources_size + section_align - 1) & ~(section_align - 1);
  686. init_output_buffer();
  687. put_word( 0x5a4d ); /* e_magic */
  688. put_word( 0x40 ); /* e_cblp */
  689. put_word( 0x01 ); /* e_cp */
  690. put_word( 0 ); /* e_crlc */
  691. put_word( lfanew / 16 ); /* e_cparhdr */
  692. put_word( 0x0000 ); /* e_minalloc */
  693. put_word( 0xffff ); /* e_maxalloc */
  694. put_word( 0x0000 ); /* e_ss */
  695. put_word( 0x00b8 ); /* e_sp */
  696. put_word( 0 ); /* e_csum */
  697. put_word( 0 ); /* e_ip */
  698. put_word( 0 ); /* e_cs */
  699. put_word( lfanew ); /* e_lfarlc */
  700. put_word( 0 ); /* e_ovno */
  701. put_dword( 0 ); /* e_res */
  702. put_dword( 0 );
  703. put_word( 0 ); /* e_oemid */
  704. put_word( 0 ); /* e_oeminfo */
  705. put_dword( 0 ); /* e_res2 */
  706. put_dword( 0 );
  707. put_dword( 0 );
  708. put_dword( 0 );
  709. put_dword( 0 );
  710. put_dword( lfanew );
  711. put_data( fakedll_signature, sizeof(fakedll_signature) );
  712. put_dword( 0x4550 ); /* Signature */
  713. switch(target_cpu)
  714. {
  715. case CPU_x86: put_word( IMAGE_FILE_MACHINE_I386 ); break;
  716. case CPU_x86_64: put_word( IMAGE_FILE_MACHINE_AMD64 ); break;
  717. case CPU_POWERPC: put_word( IMAGE_FILE_MACHINE_POWERPC ); break;
  718. case CPU_ARM: put_word( IMAGE_FILE_MACHINE_ARMNT ); break;
  719. case CPU_ARM64: put_word( IMAGE_FILE_MACHINE_ARM64 ); break;
  720. }
  721. put_word( nb_sections ); /* NumberOfSections */
  722. put_dword( 0 ); /* TimeDateStamp */
  723. put_dword( 0 ); /* PointerToSymbolTable */
  724. put_dword( 0 ); /* NumberOfSymbols */
  725. put_word( get_ptr_size() == 8 ?
  726. IMAGE_SIZEOF_NT_OPTIONAL64_HEADER :
  727. IMAGE_SIZEOF_NT_OPTIONAL32_HEADER ); /* SizeOfOptionalHeader */
  728. put_word( spec->characteristics ); /* Characteristics */
  729. put_word( get_ptr_size() == 8 ?
  730. IMAGE_NT_OPTIONAL_HDR64_MAGIC :
  731. IMAGE_NT_OPTIONAL_HDR32_MAGIC ); /* Magic */
  732. put_byte( 7 ); /* MajorLinkerVersion */
  733. put_byte( 10 ); /* MinorLinkerVersion */
  734. put_dword( text_size ); /* SizeOfCode */
  735. put_dword( 0 ); /* SizeOfInitializedData */
  736. put_dword( 0 ); /* SizeOfUninitializedData */
  737. put_dword( section_align ); /* AddressOfEntryPoint */
  738. put_dword( section_align ); /* BaseOfCode */
  739. if (get_ptr_size() == 4) put_dword( 0 ); /* BaseOfData */
  740. put_pword( 0x10000000 ); /* ImageBase */
  741. put_dword( section_align ); /* SectionAlignment */
  742. put_dword( file_align ); /* FileAlignment */
  743. put_word( 1 ); /* MajorOperatingSystemVersion */
  744. put_word( 0 ); /* MinorOperatingSystemVersion */
  745. put_word( 0 ); /* MajorImageVersion */
  746. put_word( 0 ); /* MinorImageVersion */
  747. put_word( spec->subsystem_major ); /* MajorSubsystemVersion */
  748. put_word( spec->subsystem_minor ); /* MinorSubsystemVersion */
  749. put_dword( 0 ); /* Win32VersionValue */
  750. put_dword( image_size ); /* SizeOfImage */
  751. put_dword( file_align ); /* SizeOfHeaders */
  752. put_dword( 0 ); /* CheckSum */
  753. put_word( spec->subsystem ); /* Subsystem */
  754. put_word( spec->dll_characteristics ); /* DllCharacteristics */
  755. put_pword( (spec->stack_size ? spec->stack_size : 1024) * 1024 ); /* SizeOfStackReserve */
  756. put_pword( page_size ); /* SizeOfStackCommit */
  757. put_pword( (spec->heap_size ? spec->heap_size : 1024) * 1024 ); /* SizeOfHeapReserve */
  758. put_pword( page_size ); /* SizeOfHeapCommit */
  759. put_dword( 0 ); /* LoaderFlags */
  760. put_dword( 16 ); /* NumberOfRvaAndSizes */
  761. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */
  762. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */
  763. if (resources_size) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
  764. {
  765. put_dword( 3 * section_align );
  766. put_dword( resources_size );
  767. }
  768. else
  769. {
  770. put_dword( 0 );
  771. put_dword( 0 );
  772. }
  773. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION] */
  774. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] */
  775. put_dword( 2 * section_align ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC] */
  776. put_dword( reloc_size );
  777. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG] */
  778. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_COPYRIGHT] */
  779. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR] */
  780. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS] */
  781. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG] */
  782. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT] */
  783. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT] */
  784. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT] */
  785. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] */
  786. put_dword( 0 ); put_dword( 0 ); /* DataDirectory[15] */
  787. /* .text section */
  788. put_data( ".text\0\0", 8 ); /* Name */
  789. put_dword( section_align ); /* VirtualSize */
  790. put_dword( section_align ); /* VirtualAddress */
  791. put_dword( text_size ); /* SizeOfRawData */
  792. put_dword( file_align ); /* PointerToRawData */
  793. put_dword( 0 ); /* PointerToRelocations */
  794. put_dword( 0 ); /* PointerToLinenumbers */
  795. put_word( 0 ); /* NumberOfRelocations */
  796. put_word( 0 ); /* NumberOfLinenumbers */
  797. put_dword( 0x60000020 /* CNT_CODE|MEM_EXECUTE|MEM_READ */ ); /* Characteristics */
  798. /* .reloc section */
  799. put_data( ".reloc\0", 8 ); /* Name */
  800. put_dword( section_align ); /* VirtualSize */
  801. put_dword( 2 * section_align );/* VirtualAddress */
  802. put_dword( reloc_size ); /* SizeOfRawData */
  803. put_dword( 2 * file_align ); /* PointerToRawData */
  804. put_dword( 0 ); /* PointerToRelocations */
  805. put_dword( 0 ); /* PointerToLinenumbers */
  806. put_word( 0 ); /* NumberOfRelocations */
  807. put_word( 0 ); /* NumberOfLinenumbers */
  808. put_dword( 0x42000040 /* CNT_INITIALIZED_DATA|MEM_DISCARDABLE|MEM_READ */ ); /* Characteristics */
  809. /* .rsrc section */
  810. if (resources_size)
  811. {
  812. put_data( ".rsrc\0\0", 8 ); /* Name */
  813. put_dword( (resources_size + section_align - 1) & ~(section_align - 1) ); /* VirtualSize */
  814. put_dword( 3 * section_align );/* VirtualAddress */
  815. put_dword( resources_size ); /* SizeOfRawData */
  816. put_dword( 3 * file_align ); /* PointerToRawData */
  817. put_dword( 0 ); /* PointerToRelocations */
  818. put_dword( 0 ); /* PointerToLinenumbers */
  819. put_word( 0 ); /* NumberOfRelocations */
  820. put_word( 0 ); /* NumberOfLinenumbers */
  821. put_dword( 0x40000040 /* CNT_INITIALIZED_DATA|MEM_READ */ ); /* Characteristics */
  822. }
  823. /* .text contents */
  824. align_output( file_align );
  825. if (spec->characteristics & IMAGE_FILE_DLL)
  826. put_data( dll_code_section, sizeof(dll_code_section) );
  827. else
  828. put_data( exe_code_section, sizeof(exe_code_section) );
  829. /* .reloc contents */
  830. align_output( file_align );
  831. put_dword( 0 ); /* VirtualAddress */
  832. put_dword( 0 ); /* SizeOfBlock */
  833. /* .rsrc contents */
  834. if (resources_size)
  835. {
  836. align_output( file_align );
  837. put_data( resources, resources_size );
  838. }
  839. flush_output_buffer();
  840. }
  841. /*******************************************************************
  842. * output_def_file
  843. *
  844. * Build a Win32 def file from a spec file.
  845. */
  846. void output_def_file( DLLSPEC *spec, int import_only )
  847. {
  848. DLLSPEC *spec32 = NULL;
  849. const char *name;
  850. int i, total;
  851. if (spec->type == SPEC_WIN16)
  852. {
  853. spec32 = alloc_dll_spec();
  854. add_16bit_exports( spec32, spec );
  855. spec = spec32;
  856. }
  857. if (spec_file_name)
  858. output( "; File generated automatically from %s; do not edit!\n\n",
  859. spec_file_name );
  860. else
  861. output( "; File generated automatically; do not edit!\n\n" );
  862. output( "LIBRARY %s\n\n", spec->file_name);
  863. output( "EXPORTS\n");
  864. /* Output the exports and relay entry points */
  865. for (i = total = 0; i < spec->nb_entry_points; i++)
  866. {
  867. const ORDDEF *odp = &spec->entry_points[i];
  868. int is_data = 0, is_private = odp->flags & FLAG_PRIVATE;
  869. if (odp->name) name = odp->name;
  870. else if (odp->export_name) name = odp->export_name;
  871. else continue;
  872. if (!is_private) total++;
  873. if (import_only && odp->type == TYPE_STUB) continue;
  874. if ((odp->flags & FLAG_FASTCALL) && target_platform == PLATFORM_WINDOWS)
  875. name = strmake( "@%s", name );
  876. output( " %s", name );
  877. switch(odp->type)
  878. {
  879. case TYPE_EXTERN:
  880. is_data = 1;
  881. /* fall through */
  882. case TYPE_VARARGS:
  883. case TYPE_CDECL:
  884. /* try to reduce output */
  885. if(!import_only && (strcmp(name, odp->link_name) || (odp->flags & FLAG_FORWARD)))
  886. output( "=%s", odp->link_name );
  887. break;
  888. case TYPE_STDCALL:
  889. {
  890. int at_param = get_args_size( odp );
  891. if (!kill_at && target_cpu == CPU_x86) output( "@%d", at_param );
  892. if (import_only) break;
  893. if (odp->flags & FLAG_FORWARD)
  894. output( "=%s", odp->link_name );
  895. else if (strcmp(name, odp->link_name)) /* try to reduce output */
  896. output( "=%s", get_link_name( odp ));
  897. break;
  898. }
  899. case TYPE_STUB:
  900. if (!kill_at && target_cpu == CPU_x86) output( "@%d", get_args_size( odp ));
  901. is_private = 1;
  902. break;
  903. default:
  904. assert(0);
  905. }
  906. output( " @%d", odp->ordinal );
  907. if (!odp->name || (odp->flags & FLAG_ORDINAL)) output( " NONAME" );
  908. if (is_data) output( " DATA" );
  909. if (is_private) output( " PRIVATE" );
  910. output( "\n" );
  911. }
  912. if (!total) warning( "%s: Import library doesn't export anything\n", spec->file_name );
  913. if (spec32) free_dll_spec( spec32 );
  914. }
  915. /*******************************************************************
  916. * make_builtin_files
  917. */
  918. void make_builtin_files( char *argv[] )
  919. {
  920. int i, fd;
  921. struct
  922. {
  923. unsigned short e_magic;
  924. unsigned short unused[29];
  925. unsigned int e_lfanew;
  926. } header;
  927. for (i = 0; argv[i]; i++)
  928. {
  929. if ((fd = open( argv[i], O_RDWR | O_BINARY )) == -1) fatal_perror( "Cannot open %s", argv[i] );
  930. if (read( fd, &header, sizeof(header) ) == sizeof(header) && !memcmp( &header.e_magic, "MZ", 2 ))
  931. {
  932. if (header.e_lfanew < sizeof(header) + sizeof(builtin_signature))
  933. fatal_error( "%s: Not enough space (%x) for Wine signature\n", argv[i], header.e_lfanew );
  934. write( fd, builtin_signature, sizeof(builtin_signature) );
  935. }
  936. else fatal_error( "%s: Unrecognized file format\n", argv[i] );
  937. close( fd );
  938. }
  939. }
  940. static void fixup_elf32( const char *name, int fd, void *header, size_t header_size )
  941. {
  942. struct
  943. {
  944. unsigned char e_ident[16];
  945. unsigned short e_type;
  946. unsigned short e_machine;
  947. unsigned int e_version;
  948. unsigned int e_entry;
  949. unsigned int e_phoff;
  950. unsigned int e_shoff;
  951. unsigned int e_flags;
  952. unsigned short e_ehsize;
  953. unsigned short e_phentsize;
  954. unsigned short e_phnum;
  955. unsigned short e_shentsize;
  956. unsigned short e_shnum;
  957. unsigned short e_shstrndx;
  958. } *elf = header;
  959. struct
  960. {
  961. unsigned int p_type;
  962. unsigned int p_offset;
  963. unsigned int p_vaddr;
  964. unsigned int p_paddr;
  965. unsigned int p_filesz;
  966. unsigned int p_memsz;
  967. unsigned int p_flags;
  968. unsigned int p_align;
  969. } *phdr;
  970. struct
  971. {
  972. unsigned int d_tag;
  973. unsigned int d_val;
  974. } *dyn;
  975. unsigned int i, size;
  976. if (header_size < sizeof(*elf)) return;
  977. if (elf->e_ident[6] != 1 /* EV_CURRENT */) return;
  978. size = elf->e_phnum * elf->e_phentsize;
  979. phdr = xmalloc( size );
  980. lseek( fd, elf->e_phoff, SEEK_SET );
  981. if (read( fd, phdr, size ) != size) return;
  982. for (i = 0; i < elf->e_phnum; i++)
  983. {
  984. if (phdr->p_type == 2 /* PT_DYNAMIC */ ) break;
  985. phdr = (void *)((char *)phdr + elf->e_phentsize);
  986. }
  987. if (i == elf->e_phnum) return;
  988. dyn = xmalloc( phdr->p_filesz );
  989. lseek( fd, phdr->p_offset, SEEK_SET );
  990. if (read( fd, dyn, phdr->p_filesz ) != phdr->p_filesz) return;
  991. for (i = 0; i < phdr->p_filesz / sizeof(*dyn) && dyn[i].d_tag; i++)
  992. {
  993. switch (dyn[i].d_tag)
  994. {
  995. case 25: dyn[i].d_tag = 0x60009990; break; /* DT_INIT_ARRAY */
  996. case 27: dyn[i].d_tag = 0x60009991; break; /* DT_INIT_ARRAYSZ */
  997. case 12: dyn[i].d_tag = 0x60009992; break; /* DT_INIT */
  998. }
  999. }
  1000. lseek( fd, phdr->p_offset, SEEK_SET );
  1001. write( fd, dyn, phdr->p_filesz );
  1002. }
  1003. static void fixup_elf64( const char *name, int fd, void *header, size_t header_size )
  1004. {
  1005. struct
  1006. {
  1007. unsigned char e_ident[16];
  1008. unsigned short e_type;
  1009. unsigned short e_machine;
  1010. unsigned int e_version;
  1011. unsigned __int64 e_entry;
  1012. unsigned __int64 e_phoff;
  1013. unsigned __int64 e_shoff;
  1014. unsigned int e_flags;
  1015. unsigned short e_ehsize;
  1016. unsigned short e_phentsize;
  1017. unsigned short e_phnum;
  1018. unsigned short e_shentsize;
  1019. unsigned short e_shnum;
  1020. unsigned short e_shstrndx;
  1021. } *elf = header;
  1022. struct
  1023. {
  1024. unsigned int p_type;
  1025. unsigned int p_flags;
  1026. unsigned __int64 p_offset;
  1027. unsigned __int64 p_vaddr;
  1028. unsigned __int64 p_paddr;
  1029. unsigned __int64 p_filesz;
  1030. unsigned __int64 p_memsz;
  1031. unsigned __int64 p_align;
  1032. } *phdr;
  1033. struct
  1034. {
  1035. unsigned __int64 d_tag;
  1036. unsigned __int64 d_val;
  1037. } *dyn;
  1038. unsigned int i, size;
  1039. if (header_size < sizeof(*elf)) return;
  1040. if (elf->e_ident[6] != 1 /* EV_CURRENT */) return;
  1041. size = elf->e_phnum * elf->e_phentsize;
  1042. phdr = xmalloc( size );
  1043. lseek( fd, elf->e_phoff, SEEK_SET );
  1044. if (read( fd, phdr, size ) != size) return;
  1045. for (i = 0; i < elf->e_phnum; i++)
  1046. {
  1047. if (phdr->p_type == 2 /* PT_DYNAMIC */ ) break;
  1048. phdr = (void *)((char *)phdr + elf->e_phentsize);
  1049. }
  1050. if (i == elf->e_phnum) return;
  1051. dyn = xmalloc( phdr->p_filesz );
  1052. lseek( fd, phdr->p_offset, SEEK_SET );
  1053. if (read( fd, dyn, phdr->p_filesz ) != phdr->p_filesz) return;
  1054. for (i = 0; i < phdr->p_filesz / sizeof(*dyn) && dyn[i].d_tag; i++)
  1055. {
  1056. switch (dyn[i].d_tag)
  1057. {
  1058. case 25: dyn[i].d_tag = 0x60009990; break; /* DT_INIT_ARRAY */
  1059. case 27: dyn[i].d_tag = 0x60009991; break; /* DT_INIT_ARRAYSZ */
  1060. case 12: dyn[i].d_tag = 0x60009992; break; /* DT_INIT */
  1061. }
  1062. }
  1063. lseek( fd, phdr->p_offset, SEEK_SET );
  1064. write( fd, dyn, phdr->p_filesz );
  1065. }
  1066. /*******************************************************************
  1067. * fixup_constructors
  1068. */
  1069. void fixup_constructors( char *argv[] )
  1070. {
  1071. int i, fd, size;
  1072. unsigned int header[64];
  1073. for (i = 0; argv[i]; i++)
  1074. {
  1075. if ((fd = open( argv[i], O_RDWR | O_BINARY )) == -1) fatal_perror( "Cannot open %s", argv[i] );
  1076. size = read( fd, &header, sizeof(header) );
  1077. if (size > 5)
  1078. {
  1079. if (!memcmp( header, "\177ELF\001", 5 )) fixup_elf32( argv[i], fd, header, size );
  1080. else if (!memcmp( header, "\177ELF\002", 5 )) fixup_elf64( argv[i], fd, header, size );
  1081. }
  1082. close( fd );
  1083. }
  1084. }