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