Move semaphore objects into directory name space.
[wine] / tools / winebuild / spec32.c
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
24
25 #include "config.h"
26 #include "wine/port.h"
27
28 #include <assert.h>
29 #include <ctype.h>
30 #include <stdarg.h>
31 #include <string.h>
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "wine/exception.h"
36 #include "build.h"
37
38
39 /*******************************************************************
40  *         output_exports
41  *
42  * Output the export table for a Win32 module.
43  */
44 static void output_exports( FILE *outfile, DLLSPEC *spec )
45 {
46     int i, fwd_size = 0;
47     int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
48
49     if (!nr_exports) return;
50
51     fprintf( outfile, "\n/* export table */\n\n" );
52     fprintf( outfile, "\t.data\n" );
53     fprintf( outfile, "\t.align %d\n", get_alignment(4) );
54     fprintf( outfile, ".L__wine_spec_exports:\n" );
55
56     /* export directory header */
57
58     fprintf( outfile, "\t.long 0\n" );                       /* Characteristics */
59     fprintf( outfile, "\t.long 0\n" );                       /* TimeDateStamp */
60     fprintf( outfile, "\t.long 0\n" );                       /* MajorVersion/MinorVersion */
61     fprintf( outfile, "\t.long .L__wine_spec_exp_names-.L__wine_spec_rva_base\n" ); /* Name */
62     fprintf( outfile, "\t.long %u\n", spec->base );          /* Base */
63     fprintf( outfile, "\t.long %u\n", nr_exports );          /* NumberOfFunctions */
64     fprintf( outfile, "\t.long %u\n", spec->nb_names );      /* NumberOfNames */
65     fprintf( outfile, "\t.long .L__wine_spec_exports_funcs-.L__wine_spec_rva_base\n" ); /* AddressOfFunctions */
66     if (spec->nb_names)
67     {
68         fprintf( outfile, "\t.long .L__wine_spec_exp_name_ptrs-.L__wine_spec_rva_base\n" ); /* AddressOfNames */
69         fprintf( outfile, "\t.long .L__wine_spec_exp_ordinals-.L__wine_spec_rva_base\n" );  /* AddressOfNameOrdinals */
70     }
71     else
72     {
73         fprintf( outfile, "\t.long 0\n" );  /* AddressOfNames */
74         fprintf( outfile, "\t.long 0\n" );  /* AddressOfNameOrdinals */
75     }
76
77     /* output the function pointers */
78
79     fprintf( outfile, "\n.L__wine_spec_exports_funcs:\n" );
80     for (i = spec->base; i <= spec->limit; i++)
81     {
82         ORDDEF *odp = spec->ordinals[i];
83         if (!odp) fprintf( outfile, "\t.long 0\n" );
84         else switch(odp->type)
85         {
86         case TYPE_EXTERN:
87         case TYPE_STDCALL:
88         case TYPE_VARARGS:
89         case TYPE_CDECL:
90             if (odp->flags & FLAG_FORWARD)
91             {
92                 fprintf( outfile, "\t%s .L__wine_spec_forwards+%u\n", get_asm_ptr_keyword(), fwd_size );
93                 fwd_size += strlen(odp->link_name) + 1;
94             }
95             else if (odp->flags & FLAG_EXT_LINK)
96             {
97                 fprintf( outfile, "\t%s %s_%s\n",
98                          get_asm_ptr_keyword(), asm_name("__wine_spec_ext_link"), odp->link_name );
99             }
100             else
101             {
102                 fprintf( outfile, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->link_name) );
103             }
104             break;
105         case TYPE_STUB:
106             fprintf( outfile, "\t%s %s\n", get_asm_ptr_keyword(),
107                      asm_name( get_stub_name( odp, spec )) );
108             break;
109         default:
110             assert(0);
111         }
112     }
113
114     if (spec->nb_names)
115     {
116         /* output the function name pointers */
117
118         int namepos = strlen(spec->file_name) + 1;
119
120         fprintf( outfile, "\n.L__wine_spec_exp_name_ptrs:\n" );
121         for (i = 0; i < spec->nb_names; i++)
122         {
123             fprintf( outfile, "\t.long .L__wine_spec_exp_names+%u-.L__wine_spec_rva_base\n", namepos );
124             namepos += strlen(spec->names[i]->name) + 1;
125         }
126
127         /* output the function ordinals */
128
129         fprintf( outfile, "\n.L__wine_spec_exp_ordinals:\n" );
130         for (i = 0; i < spec->nb_names; i++)
131         {
132             fprintf( outfile, "\t%s %d\n",
133                      get_asm_short_keyword(), spec->names[i]->ordinal - spec->base );
134         }
135         if (spec->nb_names % 2)
136         {
137             fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() );
138         }
139     }
140
141     /* output the export name strings */
142
143     fprintf( outfile, "\n.L__wine_spec_exp_names:\n" );
144     fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
145     for (i = 0; i < spec->nb_names; i++)
146         fprintf( outfile, "\t%s \"%s\"\n",
147                  get_asm_string_keyword(), spec->names[i]->name );
148
149     /* output forward strings */
150
151     if (fwd_size)
152     {
153         fprintf( outfile, "\n.L__wine_spec_forwards:\n" );
154         for (i = spec->base; i <= spec->limit; i++)
155         {
156             ORDDEF *odp = spec->ordinals[i];
157             if (odp && (odp->flags & FLAG_FORWARD))
158                 fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), odp->link_name );
159         }
160     }
161     fprintf( outfile, "\t.align %d\n", get_alignment(4) );
162     fprintf( outfile, ".L__wine_spec_exports_end:\n" );
163
164     /* output relays */
165
166     /* we only support relay debugging on i386 */
167     if (target_cpu == CPU_x86)
168     {
169         for (i = spec->base; i <= spec->limit; i++)
170         {
171             ORDDEF *odp = spec->ordinals[i];
172             unsigned int j, args, mask = 0;
173
174             /* skip nonexistent entry points */
175             if (!odp) goto ignore;
176             /* skip non-functions */
177             if ((odp->type != TYPE_STDCALL) && (odp->type != TYPE_CDECL)) goto ignore;
178             /* skip norelay and forward entry points */
179             if (odp->flags & (FLAG_NORELAY|FLAG_FORWARD)) goto ignore;
180
181             for (j = 0; odp->u.func.arg_types[j]; j++)
182             {
183                 if (odp->u.func.arg_types[j] == 't') mask |= 1<< (j*2);
184                 if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
185             }
186             if ((odp->flags & FLAG_RET64) && (j < 16)) mask |= 0x80000000;
187
188             args = strlen(odp->u.func.arg_types) * get_ptr_size();
189
190             switch(odp->type)
191             {
192             case TYPE_STDCALL:
193                 fprintf( outfile, "\tjmp %s\n", asm_name(odp->link_name) );
194                 fprintf( outfile, "\tret $%d\n", args );
195                 fprintf( outfile, "\t.long %s,0x%08x\n", asm_name(odp->link_name), mask );
196                 break;
197             case TYPE_CDECL:
198                 fprintf( outfile, "\tjmp %s\n", asm_name(odp->link_name) );
199                 fprintf( outfile, "\tret\n" );
200                 fprintf( outfile, "\t%s %d\n", get_asm_short_keyword(), args );
201                 fprintf( outfile, "\t.long %s,0x%08x\n", asm_name(odp->link_name), mask );
202                 break;
203             default:
204                 assert(0);
205             }
206             continue;
207
208         ignore:
209             fprintf( outfile, "\t.long 0,0,0,0\n" );
210         }
211     }
212     else fprintf( outfile, "\t.long 0\n" );
213 }
214
215
216 /*******************************************************************
217  *         output_asm_constructor
218  *
219  * Output code for calling a dll constructor.
220  */
221 static void output_asm_constructor( FILE *outfile, const char *constructor )
222 {
223     if (target_platform == PLATFORM_APPLE)
224     {
225         /* Mach-O doesn't have an init section */
226         fprintf( outfile, "\n\t.mod_init_func\n" );
227         fprintf( outfile, "\t.align %d\n", get_alignment(4) );
228         fprintf( outfile, "\t.long %s\n", asm_name(constructor) );
229     }
230     else
231     {
232         fprintf( outfile, "\n\t.section \".init\",\"ax\"\n" );
233         switch(target_cpu)
234         {
235         case CPU_x86:
236         case CPU_x86_64:
237             fprintf( outfile, "\tcall %s\n", asm_name(constructor) );
238             break;
239         case CPU_SPARC:
240             fprintf( outfile, "\tcall %s\n", asm_name(constructor) );
241             fprintf( outfile, "\tnop\n" );
242             break;
243         case CPU_ALPHA:
244             fprintf( outfile, "\tjsr $26,%s\n", asm_name(constructor) );
245             break;
246         case CPU_POWERPC:
247             fprintf( outfile, "\tbl %s\n", asm_name(constructor) );
248             break;
249         }
250     }
251 }
252
253
254 /*******************************************************************
255  *         BuildSpec32File
256  *
257  * Build a Win32 C file from a spec file.
258  */
259 void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
260 {
261     int machine = 0;
262     unsigned int page_size = get_page_size();
263
264     resolve_imports( spec );
265     output_standard_file_header( outfile );
266
267     /* Reserve some space for the PE header */
268
269     fprintf( outfile, "\t.text\n" );
270     fprintf( outfile, "\t.align %d\n", get_alignment(page_size) );
271     fprintf( outfile, "__wine_spec_pe_header:\n" );
272     if (target_platform == PLATFORM_APPLE)
273         fprintf( outfile, "\t.space 65536\n" );
274     else
275         fprintf( outfile, "\t.skip 65536\n" );
276
277     /* Output the NT header */
278
279     fprintf( outfile, "\n\t.data\n" );
280     fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
281     fprintf( outfile, "%s\n", asm_globl("__wine_spec_nt_header") );
282     fprintf( outfile, ".L__wine_spec_rva_base:\n" );
283
284     fprintf( outfile, "\t.long 0x%04x\n", IMAGE_NT_SIGNATURE );    /* Signature */
285     switch(target_cpu)
286     {
287     case CPU_x86:     machine = IMAGE_FILE_MACHINE_I386; break;
288     case CPU_x86_64:  machine = IMAGE_FILE_MACHINE_AMD64; break;
289     case CPU_POWERPC: machine = IMAGE_FILE_MACHINE_POWERPC; break;
290     case CPU_ALPHA:   machine = IMAGE_FILE_MACHINE_ALPHA; break;
291     case CPU_SPARC:   machine = IMAGE_FILE_MACHINE_UNKNOWN; break;
292     }
293     fprintf( outfile, "\t%s 0x%04x\n",              /* Machine */
294              get_asm_short_keyword(), machine );
295     fprintf( outfile, "\t%s 0\n",                   /* NumberOfSections */
296              get_asm_short_keyword() );
297     fprintf( outfile, "\t.long 0\n" );              /* TimeDateStamp */
298     fprintf( outfile, "\t.long 0\n" );              /* PointerToSymbolTable */
299     fprintf( outfile, "\t.long 0\n" );              /* NumberOfSymbols */
300     fprintf( outfile, "\t%s %d\n",                  /* SizeOfOptionalHeader */
301              get_asm_short_keyword(),
302              get_ptr_size() == 8 ? IMAGE_SIZEOF_NT_OPTIONAL64_HEADER : IMAGE_SIZEOF_NT_OPTIONAL32_HEADER );
303     fprintf( outfile, "\t%s 0x%04x\n",              /* Characteristics */
304              get_asm_short_keyword(), spec->characteristics );
305     fprintf( outfile, "\t%s 0x%04x\n",              /* Magic */
306              get_asm_short_keyword(),
307              get_ptr_size() == 8 ? IMAGE_NT_OPTIONAL_HDR64_MAGIC : IMAGE_NT_OPTIONAL_HDR32_MAGIC );
308     fprintf( outfile, "\t.byte 0\n" );              /* MajorLinkerVersion */
309     fprintf( outfile, "\t.byte 0\n" );              /* MinorLinkerVersion */
310     fprintf( outfile, "\t.long 0\n" );              /* SizeOfCode */
311     fprintf( outfile, "\t.long 0\n" );              /* SizeOfInitializedData */
312     fprintf( outfile, "\t.long 0\n" );              /* SizeOfUninitializedData */
313     /* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */
314     fprintf( outfile, "\t%s %s\n",                  /* AddressOfEntryPoint */
315              get_asm_ptr_keyword(), asm_name(spec->init_func) );
316     if (get_ptr_size() == 4)
317     {
318         fprintf( outfile, "\t.long 0\n" );          /* BaseOfCode */
319         fprintf( outfile, "\t.long 0\n" );          /* BaseOfData */
320     }
321     fprintf( outfile, "\t%s __wine_spec_pe_header\n",         /* ImageBase */
322              get_asm_ptr_keyword() );
323     fprintf( outfile, "\t.long %u\n", page_size );  /* SectionAlignment */
324     fprintf( outfile, "\t.long %u\n", page_size );  /* FileAlignment */
325     fprintf( outfile, "\t%s 1,0\n",                 /* Major/MinorOperatingSystemVersion */
326              get_asm_short_keyword() );
327     fprintf( outfile, "\t%s 0,0\n",                 /* Major/MinorImageVersion */
328              get_asm_short_keyword() );
329     fprintf( outfile, "\t%s %u,%u\n",               /* Major/MinorSubsystemVersion */
330              get_asm_short_keyword(), spec->subsystem_major, spec->subsystem_minor );
331     fprintf( outfile, "\t.long 0\n" );                          /* Win32VersionValue */
332     fprintf( outfile, "\t.long %s-.L__wine_spec_rva_base\n",    /* SizeOfImage */
333              asm_name("_end") );
334     fprintf( outfile, "\t.long %u\n", page_size );  /* SizeOfHeaders */
335     fprintf( outfile, "\t.long 0\n" );              /* CheckSum */
336     fprintf( outfile, "\t%s 0x%04x\n",              /* Subsystem */
337              get_asm_short_keyword(), spec->subsystem );
338     fprintf( outfile, "\t%s 0\n",                   /* DllCharacteristics */
339              get_asm_short_keyword() );
340     fprintf( outfile, "\t%s %u,%u\n",               /* SizeOfStackReserve/Commit */
341              get_asm_ptr_keyword(), (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
342     fprintf( outfile, "\t%s %u,%u\n",               /* SizeOfHeapReserve/Commit */
343              get_asm_ptr_keyword(), (spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
344     fprintf( outfile, "\t.long 0\n" );              /* LoaderFlags */
345     fprintf( outfile, "\t.long 16\n" );             /* NumberOfRvaAndSizes */
346
347     if (spec->base <= spec->limit)   /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */
348         fprintf( outfile, "\t.long .L__wine_spec_exports-.L__wine_spec_rva_base,"
349                  ".L__wine_spec_exports_end-.L__wine_spec_exports\n" );
350     else
351         fprintf( outfile, "\t.long 0,0\n" );
352
353     if (has_imports())   /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */
354         fprintf( outfile, "\t.long .L__wine_spec_imports-.L__wine_spec_rva_base,"
355                  ".L__wine_spec_imports_end-.L__wine_spec_imports\n" );
356     else
357         fprintf( outfile, "\t.long 0,0\n" );
358
359     if (spec->nb_resources)   /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
360         fprintf( outfile, "\t.long .L__wine_spec_resources-.L__wine_spec_rva_base,"
361                  ".L__wine_spec_resources_end-.L__wine_spec_resources\n" );
362     else
363         fprintf( outfile, "\t.long 0,0\n" );
364
365     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[3] */
366     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[4] */
367     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[5] */
368     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[6] */
369     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[7] */
370     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[8] */
371     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[9] */
372     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[10] */
373     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[11] */
374     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[12] */
375     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[13] */
376     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[14] */
377     fprintf( outfile, "\t.long 0,0\n" );  /* DataDirectory[15] */
378
379     fprintf( outfile, "\n\t%s\n", get_asm_string_section() );
380     fprintf( outfile, "%s\n", asm_globl("__wine_spec_file_name") );
381     fprintf( outfile, ".L__wine_spec_file_name:\n" );
382     fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
383     if (target_platform == PLATFORM_APPLE)
384         fprintf( outfile, "\t.lcomm %s,4\n", asm_name("_end") );
385
386     output_stubs( outfile, spec );
387     output_exports( outfile, spec );
388     output_imports( outfile, spec );
389     output_resources( outfile, spec );
390     output_asm_constructor( outfile, "__wine_spec_init_ctor" );
391 }
392
393
394 /*******************************************************************
395  *         BuildDef32File
396  *
397  * Build a Win32 def file from a spec file.
398  */
399 void BuildDef32File( FILE *outfile, DLLSPEC *spec )
400 {
401     const char *name;
402     int i, total;
403
404     if (spec_file_name)
405         fprintf( outfile, "; File generated automatically from %s; do not edit!\n\n",
406                  spec_file_name );
407     else
408         fprintf( outfile, "; File generated automatically; do not edit!\n\n" );
409
410     fprintf(outfile, "LIBRARY %s\n\n", spec->file_name);
411
412     fprintf(outfile, "EXPORTS\n");
413
414     /* Output the exports and relay entry points */
415
416     for (i = total = 0; i < spec->nb_entry_points; i++)
417     {
418         const ORDDEF *odp = &spec->entry_points[i];
419         int is_data = 0;
420
421         if (!odp) continue;
422
423         if (odp->name) name = odp->name;
424         else if (odp->export_name) name = odp->export_name;
425         else continue;
426
427         if (!(odp->flags & FLAG_PRIVATE)) total++;
428
429         if (odp->type == TYPE_STUB) continue;
430
431         fprintf(outfile, "  %s", name);
432
433         switch(odp->type)
434         {
435         case TYPE_EXTERN:
436             is_data = 1;
437             /* fall through */
438         case TYPE_VARARGS:
439         case TYPE_CDECL:
440             /* try to reduce output */
441             if(strcmp(name, odp->link_name) || (odp->flags & FLAG_FORWARD))
442                 fprintf(outfile, "=%s", odp->link_name);
443             break;
444         case TYPE_STDCALL:
445         {
446             int at_param = strlen(odp->u.func.arg_types) * get_ptr_size();
447             if (!kill_at) fprintf(outfile, "@%d", at_param);
448             if  (odp->flags & FLAG_FORWARD)
449             {
450                 fprintf(outfile, "=%s", odp->link_name);
451             }
452             else if (strcmp(name, odp->link_name)) /* try to reduce output */
453             {
454                 fprintf(outfile, "=%s", odp->link_name);
455                 if (!kill_at) fprintf(outfile, "@%d", at_param);
456             }
457             break;
458         }
459         default:
460             assert(0);
461         }
462         fprintf( outfile, " @%d", odp->ordinal );
463         if (!odp->name) fprintf( outfile, " NONAME" );
464         if (is_data) fprintf( outfile, " DATA" );
465         if (odp->flags & FLAG_PRIVATE) fprintf( outfile, " PRIVATE" );
466         fprintf( outfile, "\n" );
467     }
468     if (!total) warning( "%s: Import library doesn't export anything\n", spec->file_name );
469 }