spec32.c 45 KB

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