Remove . from default library search path.
[wine] / tools / winebuild / import.c
1 /*
2  * DLL imports support
3  *
4  * Copyright 2000, 2004 Alexandre Julliard
5  * Copyright 2000 Eric Pouech
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <ctype.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <string.h>
29 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 #endif
32
33 #include "build.h"
34
35 struct import
36 {
37     DLLSPEC     *spec;         /* description of the imported dll */
38     int          delay;       /* delay or not dll loading ? */
39     ORDDEF     **exports;     /* functions exported from this dll */
40     int          nb_exports;  /* number of exported functions */
41     ORDDEF     **imports;     /* functions we want to import from this dll */
42     int          nb_imports;  /* number of imported functions */
43 };
44
45 static char **undef_symbols;  /* list of undefined symbols */
46 static int nb_undef_symbols = -1;
47 static int undef_size;
48
49 static char **ignore_symbols; /* list of symbols to ignore */
50 static int nb_ignore_symbols;
51 static int ignore_size;
52
53 static char *ld_tmp_file;  /* ld temp file name */
54
55 static struct import **dll_imports = NULL;
56 static int nb_imports = 0;      /* number of imported dlls (delayed or not) */
57 static int nb_delayed = 0;      /* number of delayed dlls */
58 static int total_imports = 0;   /* total number of imported functions */
59 static int total_delayed = 0;   /* total number of imported functions in delayed DLLs */
60
61 /* list of symbols that are ignored by default */
62 static const char * const default_ignored_symbols[] =
63 {
64     "abs",
65     "acos",
66     "asin",
67     "atan",
68     "atan2",
69     "atof",
70     "atoi",
71     "atol",
72     "bsearch",
73     "ceil",
74     "cos",
75     "cosh",
76     "exp",
77     "fabs",
78     "floor",
79     "fmod",
80     "frexp",
81     "labs",
82     "log",
83     "log10",
84     "memchr",
85     "memcmp",
86     "memcpy",
87     "memmove",
88     "memset",
89     "modf",
90     "pow",
91     "qsort",
92     "sin",
93     "sinh",
94     "sqrt",
95     "strcat",
96     "strchr",
97     "strcmp",
98     "strcpy",
99     "strcspn",
100     "strlen",
101     "strncat",
102     "strncmp",
103     "strncpy",
104     "strpbrk",
105     "strrchr",
106     "strspn",
107     "strstr",
108     "tan",
109     "tanh"
110 };
111
112 #ifdef __powerpc__
113 # ifdef __APPLE__
114 # define ppc_high(mem) "ha16(" mem ")"
115 # define ppc_low(mem)  "lo16(" mem ")"
116 static const char * const ppc_reg[32] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
117                                           "r8", "r9", "r10","r11","r12","r13","r14","r15",
118                                           "r16","r17","r18","r19","r20","r21","r22","r23",
119                                           "r24","r25","r26","r27","r28","r29","r30","r31" };
120 # else  /* __APPLE__ */
121 # define ppc_high(mem) "(" mem ")@hi"
122 # define ppc_low(mem)  "(" mem ")@l"
123 static const char * const ppc_reg[32] = { "0", "1", "2", "3", "4", "5", "6", "7",
124                                           "8", "9", "10","11","12","13","14","15",
125                                           "16","17","18","19","20","21","22","23",
126                                           "24","25","26","27","28","29","30","31" };
127 # endif  /* __APPLE__ */
128 #endif  /* __powerpc__ */
129
130 /* compare function names; helper for resolve_imports */
131 static int name_cmp( const void *name, const void *entry )
132 {
133     return strcmp( *(char **)name, *(char **)entry );
134 }
135
136 /* compare function names; helper for resolve_imports */
137 static int func_cmp( const void *func1, const void *func2 )
138 {
139     const ORDDEF *odp1 = *(const ORDDEF **)func1;
140     const ORDDEF *odp2 = *(const ORDDEF **)func2;
141     return strcmp( odp1->name ? odp1->name : odp1->export_name,
142                    odp2->name ? odp2->name : odp2->export_name );
143 }
144
145 /* locate a symbol in a (sorted) list */
146 inline static const char *find_symbol( const char *name, char **table, int size )
147 {
148     char **res = NULL;
149
150     if (table) {
151         res = bsearch( &name, table, size, sizeof(*table), name_cmp );
152     }
153
154     return res ? *res : NULL;
155 }
156
157 /* locate an export in a (sorted) export list */
158 inline static ORDDEF *find_export( const char *name, ORDDEF **table, int size )
159 {
160     ORDDEF func, *odp, **res = NULL;
161
162     func.name = (char *)name;
163     func.ordinal = -1;
164     odp = &func;
165     if (table) res = bsearch( &odp, table, size, sizeof(*table), func_cmp );
166     return res ? *res : NULL;
167 }
168
169 /* sort a symbol table */
170 inline static void sort_symbols( char **table, int size )
171 {
172     if (table )
173         qsort( table, size, sizeof(*table), name_cmp );
174 }
175
176 /* free an import structure */
177 static void free_imports( struct import *imp )
178 {
179     free( imp->exports );
180     free( imp->imports );
181     free_dll_spec( imp->spec );
182     free( imp );
183 }
184
185 /* remove the temp file at exit */
186 static void remove_ld_tmp_file(void)
187 {
188     if (ld_tmp_file) unlink( ld_tmp_file );
189 }
190
191 /* check whether a given dll has already been imported */
192 static int is_already_imported( const char *name )
193 {
194     int i;
195
196     for (i = 0; i < nb_imports; i++)
197     {
198         if (!strcmp( dll_imports[i]->spec->file_name, name )) return 1;
199     }
200     return 0;
201 }
202
203 /* open the .so library for a given dll in a specified path */
204 static char *try_library_path( const char *path, const char *name )
205 {
206     char *buffer;
207     int fd;
208
209     buffer = xmalloc( strlen(path) + strlen(name) + 9 );
210     sprintf( buffer, "%s/lib%s.def", path, name );
211
212     /* check if the file exists */
213     if ((fd = open( buffer, O_RDONLY )) != -1)
214     {
215         close( fd );
216         return buffer;
217     }
218     free( buffer );
219     return NULL;
220 }
221
222 /* open the .so library for a given dll */
223 static char *open_library( const char *name )
224 {
225     char *fullname;
226     int i;
227
228     for (i = 0; i < nb_lib_paths; i++)
229     {
230         if ((fullname = try_library_path( lib_path[i], name ))) return fullname;
231     }
232     fatal_error( "could not open .def file for %s\n", name );
233     return NULL;
234 }
235
236 /* read in the list of exported symbols of an import library */
237 static int read_import_lib( const char *name, struct import *imp )
238 {
239     FILE *f;
240     char *fullname;
241     int i, ret;
242     DLLSPEC *spec = imp->spec;
243
244     imp->exports    = NULL;
245     imp->nb_exports = 0;
246
247     fullname = open_library( name );
248     f = open_input_file( NULL, fullname );
249     free( fullname );
250
251     ret = parse_def_file( f, spec );
252     close_input_file( f );
253     if (!ret) return 0;
254     if (is_already_imported( spec->file_name )) return 0;
255
256     imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) );
257
258     for (i = 0; i < spec->nb_entry_points; i++)
259     {
260         ORDDEF *odp = &spec->entry_points[i];
261
262         if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
263         if (odp->flags & FLAG_PRIVATE) continue;
264         imp->exports[imp->nb_exports++] = odp;
265     }
266     imp->exports = xrealloc( imp->exports, imp->nb_exports * sizeof(*imp->exports) );
267     if (imp->nb_exports)
268         qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp );
269     return 1;
270 }
271
272 /* add a dll to the list of imports */
273 void add_import_dll( const char *name, int delay )
274 {
275     struct import *imp;
276     char *fullname;
277
278     fullname = xmalloc( strlen(name) + 5 );
279     strcpy( fullname, name );
280     if (!strchr( fullname, '.' )) strcat( fullname, ".dll" );
281
282     /* check if we already imported it */
283     if (is_already_imported( fullname ))
284     {
285         free( fullname );
286         return;
287     }
288
289     imp = xmalloc( sizeof(*imp) );
290     imp->spec            = alloc_dll_spec();
291     imp->spec->file_name = fullname;
292     imp->delay           = delay;
293     imp->imports         = NULL;
294     imp->nb_imports      = 0;
295     if (delay) nb_delayed++;
296
297     if (read_import_lib( name, imp ))
298     {
299         dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) );
300         dll_imports[nb_imports++] = imp;
301     }
302     else
303     {
304         free_imports( imp );
305         if (nb_errors) exit(1);
306     }
307 }
308
309 /* remove an imported dll, based on its index in the dll_imports array */
310 static void remove_import_dll( int index )
311 {
312     struct import *imp = dll_imports[index];
313
314     memmove( &dll_imports[index], &dll_imports[index+1], sizeof(imp) * (nb_imports - index - 1) );
315     nb_imports--;
316     if (imp->delay) nb_delayed--;
317     free_imports( imp );
318 }
319
320 /* initialize the list of ignored symbols */
321 static void init_ignored_symbols(void)
322 {
323     int i;
324
325     nb_ignore_symbols = sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]);
326     ignore_size = nb_ignore_symbols + 32;
327     ignore_symbols = xmalloc( ignore_size * sizeof(*ignore_symbols) );
328     for (i = 0; i < nb_ignore_symbols; i++)
329         ignore_symbols[i] = xstrdup( default_ignored_symbols[i] );
330 }
331
332 /* add a symbol to the ignored symbol list */
333 /* if the name starts with '-' the symbol is removed instead */
334 void add_ignore_symbol( const char *name )
335 {
336     int i;
337
338     if (!ignore_symbols) init_ignored_symbols();  /* first time around, fill list with defaults */
339
340     if (name[0] == '-')  /* remove it */
341     {
342         if (!name[1])  /* remove everything */
343         {
344             for (i = 0; i < nb_ignore_symbols; i++) free( ignore_symbols[i] );
345             nb_ignore_symbols = 0;
346         }
347         else
348         {
349             for (i = 0; i < nb_ignore_symbols; i++)
350             {
351                 if (!strcmp( ignore_symbols[i], name+1 ))
352                 {
353                     free( ignore_symbols[i] );
354                     memmove( &ignore_symbols[i], &ignore_symbols[i+1], nb_ignore_symbols - i - 1 );
355                     nb_ignore_symbols--;
356                 }
357             }
358         }
359     }
360     else
361     {
362         if (nb_ignore_symbols == ignore_size)
363         {
364             ignore_size += 32;
365             ignore_symbols = xrealloc( ignore_symbols, ignore_size * sizeof(*ignore_symbols) );
366         }
367         ignore_symbols[nb_ignore_symbols++] = xstrdup( name );
368     }
369 }
370
371 /* add a function to the list of imports from a given dll */
372 static void add_import_func( struct import *imp, ORDDEF *func )
373 {
374     imp->imports = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) );
375     imp->imports[imp->nb_imports++] = func;
376     total_imports++;
377     if (imp->delay) total_delayed++;
378 }
379
380 /* add a symbol to the undef list */
381 inline static void add_undef_symbol( const char *name )
382 {
383     if (nb_undef_symbols == undef_size)
384     {
385         undef_size += 128;
386         undef_symbols = xrealloc( undef_symbols, undef_size * sizeof(*undef_symbols) );
387     }
388     undef_symbols[nb_undef_symbols++] = xstrdup( name );
389 }
390
391 /* remove all the holes in the undefined symbol list; return the number of removed symbols */
392 static int remove_symbol_holes(void)
393 {
394     int i, off;
395     for (i = off = 0; i < nb_undef_symbols; i++)
396     {
397         if (!undef_symbols[i]) off++;
398         else undef_symbols[i - off] = undef_symbols[i];
399     }
400     nb_undef_symbols -= off;
401     return off;
402 }
403
404 /* add a symbol to the extra list, but only if needed */
405 static int add_extra_symbol( const char **extras, int *count, const char *name, const DLLSPEC *spec )
406 {
407     int i;
408
409     if (!find_symbol( name, undef_symbols, nb_undef_symbols ))
410     {
411         /* check if the symbol is being exported by this dll */
412         for (i = 0; i < spec->nb_entry_points; i++)
413         {
414             ORDDEF *odp = &spec->entry_points[i];
415             if (odp->type == TYPE_STDCALL ||
416                 odp->type == TYPE_CDECL ||
417                 odp->type == TYPE_VARARGS ||
418                 odp->type == TYPE_EXTERN)
419             {
420                 if (odp->name && !strcmp( odp->name, name )) return 0;
421             }
422         }
423         extras[*count] = name;
424         (*count)++;
425     }
426     return 1;
427 }
428
429 /* add the extra undefined symbols that will be contained in the generated spec file itself */
430 static void add_extra_undef_symbols( const DLLSPEC *spec )
431 {
432     const char *extras[10];
433     int i, count = 0, nb_stubs = 0, nb_regs = 0;
434     int kernel_imports = 0, ntdll_imports = 0;
435
436     sort_symbols( undef_symbols, nb_undef_symbols );
437
438     for (i = 0; i < spec->nb_entry_points; i++)
439     {
440         ORDDEF *odp = &spec->entry_points[i];
441         if (odp->type == TYPE_STUB) nb_stubs++;
442         if (odp->flags & FLAG_REGISTER) nb_regs++;
443     }
444
445     /* add symbols that will be contained in the spec file itself */
446     switch (spec->mode)
447     {
448     case SPEC_MODE_DLL:
449     case SPEC_MODE_NATIVE:
450         break;
451     case SPEC_MODE_GUIEXE:
452         kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec );
453         kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA", spec );
454         kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA", spec );
455         /* fall through */
456     case SPEC_MODE_CUIEXE:
457         kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
458         break;
459     case SPEC_MODE_GUIEXE_UNICODE:
460         kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec );
461         kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA", spec );
462         kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA", spec );
463         /* fall through */
464     case SPEC_MODE_CUIEXE_UNICODE:
465         kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
466         break;
467     }
468     if (nb_delayed)
469     {
470         kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA", spec );
471         kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress", spec );
472     }
473     if (nb_regs)
474         ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs", spec );
475     if (nb_delayed || nb_stubs)
476         ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException", spec );
477
478     /* make sure we import the dlls that contain these functions */
479     if (kernel_imports) add_import_dll( "kernel32", 0 );
480     if (ntdll_imports) add_import_dll( "ntdll", 0 );
481
482     if (count)
483     {
484         for (i = 0; i < count; i++) add_undef_symbol( extras[i] );
485         sort_symbols( undef_symbols, nb_undef_symbols );
486     }
487 }
488
489 /* check if a given imported dll is not needed, taking forwards into account */
490 static int check_unused( const struct import* imp, const DLLSPEC *spec )
491 {
492     int i;
493     const char *file_name = imp->spec->file_name;
494     size_t len = strlen( file_name );
495     const char *p = strchr( file_name, '.' );
496     if (p && !strcasecmp( p, ".dll" )) len = p - file_name;
497
498     for (i = spec->base; i <= spec->limit; i++)
499     {
500         ORDDEF *odp = spec->ordinals[i];
501         if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
502         if (!strncasecmp( odp->link_name, file_name, len ) &&
503             odp->link_name[len] == '.')
504             return 0;  /* found a forward, it is used */
505     }
506     return 1;
507 }
508
509 /* combine a list of object files with ld into a single object file */
510 /* returns the name of the combined file */
511 static const char *ldcombine_files( char **argv )
512 {
513     int i, len = 0;
514     char *cmd;
515     int fd, err;
516
517     if (output_file_name && output_file_name[0])
518     {
519         ld_tmp_file = xmalloc( strlen(output_file_name) + 10 );
520         strcpy( ld_tmp_file, output_file_name );
521         strcat( ld_tmp_file, ".XXXXXX.o" );
522     }
523     else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" );
524
525     if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" );
526     close( fd );
527     atexit( remove_ld_tmp_file );
528
529     for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
530     cmd = xmalloc( len + strlen(ld_tmp_file) + 10 );
531     sprintf( cmd, "ld -r -o %s", ld_tmp_file );
532     for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] );
533     err = system( cmd );
534     if (err) fatal_error( "ld -r failed with status %d\n", err );
535     free( cmd );
536     return ld_tmp_file;
537 }
538
539 /* read in the list of undefined symbols */
540 void read_undef_symbols( char **argv )
541 {
542     FILE *f;
543     char buffer[1024];
544     int err;
545     const char *name;
546
547     if (!argv[0]) return;
548
549     undef_size = nb_undef_symbols = 0;
550
551     /* if we have multiple object files, link them together */
552     if (argv[1]) name = ldcombine_files( argv );
553     else name = argv[0];
554
555     sprintf( buffer, "nm -u %s", name );
556     if (!(f = popen( buffer, "r" )))
557         fatal_error( "Cannot execute '%s'\n", buffer );
558
559     while (fgets( buffer, sizeof(buffer), f ))
560     {
561         char *p = buffer + strlen(buffer) - 1;
562         if (p < buffer) continue;
563         if (*p == '\n') *p-- = 0;
564         p = buffer;
565         while (*p == ' ') p++;
566         if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
567         add_undef_symbol( p );
568     }
569     if ((err = pclose( f ))) warning( "nm -u %s error %d\n", name, err );
570 }
571
572 static void remove_ignored_symbols(void)
573 {
574     int i;
575
576     if (!ignore_symbols) init_ignored_symbols();
577     sort_symbols( ignore_symbols, nb_ignore_symbols );
578     for (i = 0; i < nb_undef_symbols; i++)
579     {
580         if (find_symbol( undef_symbols[i], ignore_symbols, nb_ignore_symbols ))
581         {
582             free( undef_symbols[i] );
583             undef_symbols[i] = NULL;
584         }
585     }
586     remove_symbol_holes();
587 }
588
589 /* resolve the imports for a Win32 module */
590 int resolve_imports( DLLSPEC *spec )
591 {
592     int i, j;
593
594     if (nb_undef_symbols == -1) return 0; /* no symbol file specified */
595
596     add_extra_undef_symbols( spec );
597     remove_ignored_symbols();
598
599     for (i = 0; i < nb_imports; i++)
600     {
601         struct import *imp = dll_imports[i];
602
603         for (j = 0; j < nb_undef_symbols; j++)
604         {
605             ORDDEF *odp = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
606             if (odp)
607             {
608                 add_import_func( imp, odp );
609                 free( undef_symbols[j] );
610                 undef_symbols[j] = NULL;
611             }
612         }
613         /* remove all the holes in the undef symbols list */
614         if (!remove_symbol_holes() && check_unused( imp, spec ))
615         {
616             /* the dll is not used, get rid of it */
617             warning( "%s imported but no symbols used\n", imp->spec->file_name );
618             remove_import_dll( i );
619             i--;
620         }
621     }
622     return 1;
623 }
624
625 /* output the import table of a Win32 module */
626 static int output_immediate_imports( FILE *outfile )
627 {
628     int i, j, pos;
629     int nb_imm = nb_imports - nb_delayed;
630
631     if (!nb_imm) goto done;
632
633     /* main import header */
634
635     fprintf( outfile, "\nstatic struct {\n" );
636     fprintf( outfile, "  struct {\n" );
637     fprintf( outfile, "    void        *OriginalFirstThunk;\n" );
638     fprintf( outfile, "    unsigned int TimeDateStamp;\n" );
639     fprintf( outfile, "    unsigned int ForwarderChain;\n" );
640     fprintf( outfile, "    const char  *Name;\n" );
641     fprintf( outfile, "    void        *FirstThunk;\n" );
642     fprintf( outfile, "  } imp[%d];\n", nb_imm+1 );
643     fprintf( outfile, "  const char *data[%d];\n",
644              total_imports - total_delayed + nb_imm );
645     fprintf( outfile, "} imports = {\n  {\n" );
646
647     /* list of dlls */
648
649     for (i = j = 0; i < nb_imports; i++)
650     {
651         if (dll_imports[i]->delay) continue;
652         fprintf( outfile, "    { 0, 0, 0, \"%s\", &imports.data[%d] },\n",
653                  dll_imports[i]->spec->file_name, j );
654         j += dll_imports[i]->nb_imports + 1;
655     }
656
657     fprintf( outfile, "    { 0, 0, 0, 0, 0 },\n" );
658     fprintf( outfile, "  },\n  {\n" );
659
660     /* list of imported functions */
661
662     for (i = 0; i < nb_imports; i++)
663     {
664         if (dll_imports[i]->delay) continue;
665         fprintf( outfile, "    /* %s */\n", dll_imports[i]->spec->file_name );
666         for (j = 0; j < dll_imports[i]->nb_imports; j++)
667         {
668             ORDDEF *odp = dll_imports[i]->imports[j];
669             if (!(odp->flags & FLAG_NONAME))
670             {
671                 unsigned short ord = odp->ordinal;
672                 fprintf( outfile, "    \"\\%03o\\%03o%s\",\n",
673                          *(unsigned char *)&ord, *((unsigned char *)&ord + 1), odp->name );
674             }
675             else
676                 fprintf( outfile, "    (char *)%d,\n", odp->ordinal );
677         }
678         fprintf( outfile, "    0,\n" );
679     }
680     fprintf( outfile, "  }\n};\n\n" );
681
682     /* thunks for imported functions */
683
684     fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
685     pos = 20 * (nb_imm + 1);  /* offset of imports.data from start of imports */
686     fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
687     for (i = 0; i < nb_imports; i++)
688     {
689         if (dll_imports[i]->delay) continue;
690         for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
691         {
692             ORDDEF *odp = dll_imports[i]->imports[j];
693             const char *name = odp->name ? odp->name : odp->export_name;
694             fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
695             fprintf( outfile, "    \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
696             fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\\t", name);
697
698 #if defined(__i386__)
699             if (strstr( name, "__wine_call_from_16" ))
700                 fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos );
701             else
702                 fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos );
703 #elif defined(__sparc__)
704             if ( !UsePIC )
705             {
706                 fprintf( outfile, "sethi %%hi(imports+%d), %%g1\\n\\t", pos );
707                 fprintf( outfile, "ld [%%g1+%%lo(imports+%d)], %%g1\\n\\t", pos );
708                 fprintf( outfile, "jmp %%g1\\n\\tnop\\n" );
709             }
710             else
711             {
712                 /* Hmpf.  Stupid sparc assembler always interprets global variable
713                    names as GOT offsets, so we have to do it the long way ... */
714                 fprintf( outfile, "save %%sp, -96, %%sp\\n" );
715                 fprintf( outfile, "0:\\tcall 1f\\n\\tnop\\n" );
716                 fprintf( outfile, "1:\\tsethi %%hi(imports+%d-0b), %%g1\\n\\t", pos );
717                 fprintf( outfile, "or %%g1, %%lo(imports+%d-0b), %%g1\\n\\t", pos );
718                 fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
719                 fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
720             }
721
722 #elif defined(__powerpc__)
723             fprintf(outfile, "\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
724             fprintf(outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[9], ppc_reg[1]);
725             fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
726             fprintf(outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[8], ppc_reg[1]);
727             fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
728             fprintf(outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[7], ppc_reg[1]);
729
730             fprintf(outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("imports") "+ %d")  "\\n\"\n", ppc_reg[9], pos);
731             fprintf(outfile, "\t\"\\tla  %s, " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
732             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
733             fprintf(outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
734
735             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[7], ppc_reg[1]);
736             fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
737             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[8], ppc_reg[1]);
738             fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
739             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[9], ppc_reg[1]);
740             fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
741             fprintf(outfile, "\t\"\\tbctr\\n");
742 #else
743 #error You need to define import thunks for your architecture!
744 #endif
745             fprintf( outfile, "\"\n" );
746         }
747         pos += 4;
748     }
749     fprintf( outfile, "\".text\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
750
751  done:
752     return nb_imm;
753 }
754
755 /* output the delayed import table of a Win32 module */
756 static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
757 {
758     int i, idx, j, pos;
759
760     if (!nb_delayed) goto done;
761
762     for (i = 0; i < nb_imports; i++)
763     {
764         if (!dll_imports[i]->delay) continue;
765         fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i);
766         for (j = 0; j < dll_imports[i]->nb_imports; j++)
767         {
768             ORDDEF *odp = dll_imports[i]->imports[j];
769             const char *name = odp->name ? odp->name : odp->export_name;
770             fprintf( outfile, "void __wine_delay_imp_%d_%s();\n", i, name );
771         }
772     }
773     fprintf( outfile, "\n" );
774     fprintf( outfile, "static struct {\n" );
775     fprintf( outfile, "  struct ImgDelayDescr {\n" );
776     fprintf( outfile, "    unsigned int  grAttrs;\n" );
777     fprintf( outfile, "    const char   *szName;\n" );
778     fprintf( outfile, "    void        **phmod;\n" );
779     fprintf( outfile, "    void        **pIAT;\n" );
780     fprintf( outfile, "    const char  **pINT;\n" );
781     fprintf( outfile, "    void*         pBoundIAT;\n" );
782     fprintf( outfile, "    void*         pUnloadIAT;\n" );
783     fprintf( outfile, "    unsigned long dwTimeStamp;\n" );
784     fprintf( outfile, "  } imp[%d];\n", nb_delayed );
785     fprintf( outfile, "  void         *IAT[%d];\n", total_delayed );
786     fprintf( outfile, "  const char   *INT[%d];\n", total_delayed );
787     fprintf( outfile, "} delay_imports = {\n" );
788     fprintf( outfile, "  {\n" );
789     for (i = j = 0; i < nb_imports; i++)
790     {
791         if (!dll_imports[i]->delay) continue;
792         fprintf( outfile, "    { 0, \"%s\", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n",
793                  dll_imports[i]->spec->file_name, i, j, j );
794         j += dll_imports[i]->nb_imports;
795     }
796     fprintf( outfile, "  },\n  {\n" );
797     for (i = 0; i < nb_imports; i++)
798     {
799         if (!dll_imports[i]->delay) continue;
800         fprintf( outfile, "    /* %s */\n", dll_imports[i]->spec->file_name );
801         for (j = 0; j < dll_imports[i]->nb_imports; j++)
802         {
803             ORDDEF *odp = dll_imports[i]->imports[j];
804             const char *name = odp->name ? odp->name : odp->export_name;
805             fprintf( outfile, "    &__wine_delay_imp_%d_%s,\n", i, name );
806         }
807     }
808     fprintf( outfile, "  },\n  {\n" );
809     for (i = 0; i < nb_imports; i++)
810     {
811         if (!dll_imports[i]->delay) continue;
812         fprintf( outfile, "    /* %s */\n", dll_imports[i]->spec->file_name );
813         for (j = 0; j < dll_imports[i]->nb_imports; j++)
814         {
815             ORDDEF *odp = dll_imports[i]->imports[j];
816             if (!odp->name)
817                 fprintf( outfile, "    (char *)%d,\n", odp->ordinal );
818             else
819                 fprintf( outfile, "    \"%s\",\n", odp->name );
820         }
821     }
822     fprintf( outfile, "  }\n};\n\n" );
823
824     /* check if there's some stub defined. if so, exception struct
825      *  is already defined, so don't emit it twice
826      */
827     for (i = 0; i < spec->nb_entry_points; i++) if (spec->entry_points[i].type == TYPE_STUB) break;
828
829     if (i == spec->nb_entry_points) {
830        fprintf( outfile, "struct exc_record {\n" );
831        fprintf( outfile, "  unsigned int code, flags;\n" );
832        fprintf( outfile, "  void *rec, *addr;\n" );
833        fprintf( outfile, "  unsigned int params;\n" );
834        fprintf( outfile, "  const void *info[15];\n" );
835        fprintf( outfile, "};\n\n" );
836        fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n" );
837     }
838
839     fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n");
840     fprintf( outfile, "extern void * __stdcall GetProcAddress(void *, const char*);\n");
841     fprintf( outfile, "\n" );
842
843     fprintf( outfile, "void *__stdcall __wine_delay_load( int idx_nr )\n" );
844     fprintf( outfile, "{\n" );
845     fprintf( outfile, "  int idx = idx_nr >> 16, nr = idx_nr & 0xffff;\n" );
846     fprintf( outfile, "  struct ImgDelayDescr *imd = delay_imports.imp + idx;\n" );
847     fprintf( outfile, "  void **pIAT = imd->pIAT + nr;\n" );
848     fprintf( outfile, "  const char** pINT = imd->pINT + nr;\n" );
849     fprintf( outfile, "  void *fn;\n\n" );
850
851     fprintf( outfile, "  if (!*imd->phmod) *imd->phmod = LoadLibraryA(imd->szName);\n" );
852     fprintf( outfile, "  if (*imd->phmod && (fn = GetProcAddress(*imd->phmod, *pINT)))\n");
853     fprintf( outfile, "    /* patch IAT with final value */\n" );
854     fprintf( outfile, "    return *pIAT = fn;\n" );
855     fprintf( outfile, "  else {\n");
856     fprintf( outfile, "    struct exc_record rec;\n" );
857     fprintf( outfile, "    rec.code    = 0x80000100;\n" );
858     fprintf( outfile, "    rec.flags   = 1;\n" );
859     fprintf( outfile, "    rec.rec     = 0;\n" );
860     fprintf( outfile, "    rec.params  = 2;\n" );
861     fprintf( outfile, "    rec.info[0] = imd->szName;\n" );
862     fprintf( outfile, "    rec.info[1] = *pINT;\n" );
863     fprintf( outfile, "#ifdef __GNUC__\n" );
864     fprintf( outfile, "    rec.addr = __builtin_return_address(1);\n" );
865     fprintf( outfile, "#else\n" );
866     fprintf( outfile, "    rec.addr = 0;\n" );
867     fprintf( outfile, "#endif\n" );
868     fprintf( outfile, "    for (;;) RtlRaiseException( &rec );\n" );
869     fprintf( outfile, "    return 0; /* shouldn't go here */\n" );
870     fprintf( outfile, "  }\n}\n\n" );
871
872     fprintf( outfile, "#ifndef __GNUC__\n" );
873     fprintf( outfile, "static void __asm__dummy_delay_import(void) {\n" );
874     fprintf( outfile, "#endif\n" );
875
876     fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) );
877     fprintf( outfile, "    \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
878     fprintf( outfile, "    \"" __ASM_NAME("__wine_delay_load_asm") ":\\n\"\n" );
879 #if defined(__i386__)
880     fprintf( outfile, "    \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
881     fprintf( outfile, "    \"\\tcall __wine_delay_load\\n\"\n" );
882     fprintf( outfile, "    \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
883 #elif defined(__sparc__)
884     fprintf( outfile, "    \"\\tsave %%sp, -96, %%sp\\n\"\n" );
885     fprintf( outfile, "    \"\\tcall __wine_delay_load\\n\"\n" );
886     fprintf( outfile, "    \"\\tmov %%g1, %%o0\\n\"\n" );
887     fprintf( outfile, "    \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
888 #elif defined(__powerpc__)
889     /* Save all callee saved registers into a stackframe. */
890     fprintf( outfile, "    \"\\tstwu %s, -48(%s)\\n\"\n", ppc_reg[1], ppc_reg[1]);
891     fprintf( outfile, "    \"\\tstw  %s,   4(%s)\\n\"\n", ppc_reg[3], ppc_reg[1]);
892     fprintf( outfile, "    \"\\tstw  %s,   8(%s)\\n\"\n", ppc_reg[4], ppc_reg[1]);
893     fprintf( outfile, "    \"\\tstw  %s,  12(%s)\\n\"\n", ppc_reg[5], ppc_reg[1]);
894     fprintf( outfile, "    \"\\tstw  %s,  16(%s)\\n\"\n", ppc_reg[6], ppc_reg[1]);
895     fprintf( outfile, "    \"\\tstw  %s,  20(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
896     fprintf( outfile, "    \"\\tstw  %s,  24(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
897     fprintf( outfile, "    \"\\tstw  %s,  28(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
898     fprintf( outfile, "    \"\\tstw  %s,  32(%s)\\n\"\n", ppc_reg[10], ppc_reg[1]);
899     fprintf( outfile, "    \"\\tstw  %s,  36(%s)\\n\"\n", ppc_reg[11], ppc_reg[1]);
900     fprintf( outfile, "    \"\\tstw  %s,  40(%s)\\n\"\n", ppc_reg[12], ppc_reg[1]);
901
902     /* r0 -> r3 (arg1) */
903     fprintf( outfile, "    \"\\tmr %s, %s\\n\"\n", ppc_reg[3], ppc_reg[0]);
904
905     /* save return address */
906     fprintf( outfile, "    \"\\tmflr %s\\n\"\n", ppc_reg[0]);
907     fprintf( outfile, "    \"\\tstw  %s, 44(%s)\\n\"\n", ppc_reg[0], ppc_reg[1]);
908
909     /* Call the __wine_delay_load function, arg1 is arg1. */
910     fprintf( outfile, "    \"\\tbl " __ASM_NAME("__wine_delay_load") "\\n\"\n");
911
912     /* Load return value from call into ctr register */
913     fprintf( outfile, "    \"\\tmtctr %s\\n\"\n", ppc_reg[3]);
914
915     /* restore all saved registers and drop stackframe. */
916     fprintf( outfile, "    \"\\tlwz  %s,   4(%s)\\n\"\n", ppc_reg[3], ppc_reg[1]);
917     fprintf( outfile, "    \"\\tlwz  %s,   8(%s)\\n\"\n", ppc_reg[4], ppc_reg[1]);
918     fprintf( outfile, "    \"\\tlwz  %s,  12(%s)\\n\"\n", ppc_reg[5], ppc_reg[1]);
919     fprintf( outfile, "    \"\\tlwz  %s,  16(%s)\\n\"\n", ppc_reg[6], ppc_reg[1]);
920     fprintf( outfile, "    \"\\tlwz  %s,  20(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
921     fprintf( outfile, "    \"\\tlwz  %s,  24(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
922     fprintf( outfile, "    \"\\tlwz  %s,  28(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
923     fprintf( outfile, "    \"\\tlwz  %s,  32(%s)\\n\"\n", ppc_reg[10], ppc_reg[1]);
924     fprintf( outfile, "    \"\\tlwz  %s,  36(%s)\\n\"\n", ppc_reg[11], ppc_reg[1]);
925     fprintf( outfile, "    \"\\tlwz  %s,  40(%s)\\n\"\n", ppc_reg[12], ppc_reg[1]);
926
927     /* Load return value from call into return register */
928     fprintf( outfile, "    \"\\tlwz  %s,  44(%s)\\n\"\n", ppc_reg[0], ppc_reg[1]);
929     fprintf( outfile, "    \"\\tmtlr %s\\n\"\n", ppc_reg[0]);
930     fprintf( outfile, "    \"\\taddi %s, %s, 48\\n\"\n", ppc_reg[1], ppc_reg[1]);
931
932     /* branch to ctr register. */
933     fprintf( outfile, "\"bctr\\n\"\n");
934 #else
935 #error You need to defined delayed import thunks for your architecture!
936 #endif
937
938     for (i = idx = 0; i < nb_imports; i++)
939     {
940         if (!dll_imports[i]->delay) continue;
941         for (j = 0; j < dll_imports[i]->nb_imports; j++)
942         {
943             char buffer[128];
944             ORDDEF *odp = dll_imports[i]->imports[j];
945             const char *name = odp->name ? odp->name : odp->export_name;
946
947             sprintf( buffer, "__wine_delay_imp_%d_%s", i, name );
948             fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer );
949             fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\"\n", buffer );
950 #if defined(__i386__)
951             fprintf( outfile, "    \"\\tmovl $%d, %%eax\\n\"\n", (idx << 16) | j );
952             fprintf( outfile, "    \"\\tjmp __wine_delay_load_asm\\n\"\n" );
953 #elif defined(__sparc__)
954             fprintf( outfile, "    \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
955             fprintf( outfile, "    \"\\tb,a __wine_delay_load_asm\\n\"\n" );
956 #elif defined(__powerpc__)
957             /* g0 is a function scratch register or so I understand. */
958             /* First load the upper half-word, and then the lower part */
959             fprintf( outfile, "    \"\\tlis %s, %d\\n\"\n", ppc_reg[0], idx);
960             fprintf( outfile, "    \"\\tli %s, %d\\n\"\n", ppc_reg[0], j);
961             fprintf( outfile, "    \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
962 #else
963 #error You need to defined delayed import thunks for your architecture!
964 #endif
965         }
966         idx++;
967     }
968
969     fprintf( outfile, "\n    \".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
970     pos = nb_delayed * 32;
971     for (i = 0; i < nb_imports; i++)
972     {
973         if (!dll_imports[i]->delay) continue;
974         for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
975         {
976             ORDDEF *odp = dll_imports[i]->imports[j];
977             const char *name = odp->name ? odp->name : odp->export_name;
978
979             fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
980             fprintf( outfile, "    \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
981             fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\\t\"", name );
982 #if defined(__i386__)
983             if (strstr( name, "__wine_call_from_16" ))
984                 fprintf( outfile, "\".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n\"", pos );
985             else
986                 fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos );
987 #elif defined(__sparc__)
988             if ( !UsePIC )
989             {
990                 fprintf( outfile, "\"sethi %%hi(delay_imports+%d), %%g1\\n\\t\"", pos );
991                 fprintf( outfile, "\"ld [%%g1+%%lo(delay_imports+%d)], %%g1\\n\\t\"", pos );
992                 fprintf( outfile, "\"jmp %%g1\\n\\tnop\\n\"" );
993             }
994             else
995             {
996                 /* Hmpf.  Stupid sparc assembler always interprets global variable
997                    names as GOT offsets, so we have to do it the long way ... */
998                 fprintf( outfile, "\"save %%sp, -96, %%sp\\n\"" );
999                 fprintf( outfile, "\"0:\\tcall 1f\\n\\tnop\\n\"" );
1000                 fprintf( outfile, "\"1:\\tsethi %%hi(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1001                 fprintf( outfile, "\"or %%g1, %%lo(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1002                 fprintf( outfile, "\"ld [%%g1+%%o7], %%g1\\n\\t\"" );
1003                 fprintf( outfile, "\"jmp %%g1\\n\\trestore\\n\"" );
1004             }
1005
1006 #elif defined(__powerpc__)
1007             fprintf( outfile, "\t\"addi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1008             fprintf( outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[9], ppc_reg[1]);
1009             fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1010             fprintf( outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[8], ppc_reg[1]);
1011             fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1012             fprintf( outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[7], ppc_reg[1]);
1013             fprintf( outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
1014             fprintf( outfile, "\t\"\\tla  %s, " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
1015             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
1016             fprintf( outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
1017
1018             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[7], ppc_reg[1]);
1019             fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1020             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[8], ppc_reg[1]);
1021             fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1022             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[9], ppc_reg[1]);
1023             fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1024             fprintf( outfile, "\t\"\\tbctr\\n\"");
1025 #else
1026 #error You need to define delayed import thunks for your architecture!
1027 #endif
1028             fprintf( outfile, "\n" );
1029         }
1030     }
1031     fprintf( outfile, "\".text\");\n" );
1032     fprintf( outfile, "#ifndef __GNUC__\n" );
1033     fprintf( outfile, "}\n" );
1034     fprintf( outfile, "#endif\n" );
1035     fprintf( outfile, "\n" );
1036
1037  done:
1038     return nb_delayed;
1039 }
1040
1041 /* output the import and delayed import tables of a Win32 module
1042  * returns number of DLLs exported in 'immediate' mode
1043  */
1044 int output_imports( FILE *outfile, DLLSPEC *spec )
1045 {
1046    output_delayed_imports( outfile, spec );
1047    return output_immediate_imports( outfile );
1048 }