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