Added UYT to TZ_INFO.
[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, "GetProcAddress", spec );
536         kernel_imports += add_extra_symbol( extras, &count, "RaiseException", spec );
537     }
538     if (nb_stubs)
539         ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException", spec );
540
541     /* make sure we import the dlls that contain these functions */
542     if (kernel_imports) add_import_dll( "kernel32", NULL );
543     if (ntdll_imports) add_import_dll( "ntdll", NULL );
544
545     if (count)
546     {
547         for (i = 0; i < count; i++) add_undef_symbol( extras[i] );
548         sort_symbols( undef_symbols, nb_undef_symbols );
549     }
550 }
551
552 /* check if a given imported dll is not needed, taking forwards into account */
553 static int check_unused( const struct import* imp, const DLLSPEC *spec )
554 {
555     int i;
556     const char *file_name = imp->spec->file_name;
557     size_t len = strlen( file_name );
558     const char *p = strchr( file_name, '.' );
559     if (p && !strcasecmp( p, ".dll" )) len = p - file_name;
560
561     for (i = spec->base; i <= spec->limit; i++)
562     {
563         ORDDEF *odp = spec->ordinals[i];
564         if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
565         if (!strncasecmp( odp->link_name, file_name, len ) &&
566             odp->link_name[len] == '.')
567             return 0;  /* found a forward, it is used */
568     }
569     return 1;
570 }
571
572 /* combine a list of object files with ld into a single object file */
573 /* returns the name of the combined file */
574 static const char *ldcombine_files( char **argv )
575 {
576     int i, len = 0;
577     char *cmd;
578     int fd, err;
579
580     if (output_file_name && output_file_name[0])
581     {
582         ld_tmp_file = xmalloc( strlen(output_file_name) + 10 );
583         strcpy( ld_tmp_file, output_file_name );
584         strcat( ld_tmp_file, ".XXXXXX.o" );
585     }
586     else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" );
587
588     if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" );
589     close( fd );
590     atexit( remove_ld_tmp_file );
591
592     for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
593     cmd = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ld_command)  );
594     sprintf( cmd, "%s -r -o %s", ld_command, ld_tmp_file );
595     for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] );
596     err = system( cmd );
597     if (err) fatal_error( "%s -r failed with status %d\n", ld_command, err );
598     free( cmd );
599     return ld_tmp_file;
600 }
601
602 /* read in the list of undefined symbols */
603 void read_undef_symbols( char **argv )
604 {
605     static const char name_prefix[] = __ASM_NAME("");
606     static const int prefix_len = sizeof(name_prefix) - 1;
607     FILE *f;
608     char *cmd, buffer[1024];
609     int err;
610     const char *name;
611
612     if (!argv[0]) return;
613
614     undef_size = nb_undef_symbols = 0;
615
616     /* if we have multiple object files, link them together */
617     if (argv[1]) name = ldcombine_files( argv );
618     else name = argv[0];
619
620     cmd = xmalloc( strlen(nm_command) + strlen(name) + 5 );
621     sprintf( cmd, "%s -u %s", nm_command, name );
622     if (!(f = popen( cmd, "r" )))
623         fatal_error( "Cannot execute '%s'\n", cmd );
624
625     while (fgets( buffer, sizeof(buffer), f ))
626     {
627         char *p = buffer + strlen(buffer) - 1;
628         if (p < buffer) continue;
629         if (*p == '\n') *p-- = 0;
630         p = buffer;
631         while (*p == ' ') p++;
632         if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
633         if (prefix_len && !strncmp( p, name_prefix, prefix_len )) p += prefix_len;
634         add_undef_symbol( p );
635     }
636     if ((err = pclose( f ))) warning( "%s failed with status %d\n", cmd, err );
637     free( cmd );
638 }
639
640 static void remove_ignored_symbols(void)
641 {
642     int i;
643
644     if (!ignore_symbols) init_ignored_symbols();
645     sort_symbols( ignore_symbols, nb_ignore_symbols );
646     for (i = 0; i < nb_undef_symbols; i++)
647     {
648         if (find_symbol( undef_symbols[i], ignore_symbols, nb_ignore_symbols ))
649         {
650             free( undef_symbols[i] );
651             undef_symbols[i] = NULL;
652         }
653     }
654     remove_symbol_holes();
655 }
656
657 /* resolve the imports for a Win32 module */
658 int resolve_imports( DLLSPEC *spec )
659 {
660     int i, j;
661
662     if (nb_undef_symbols == -1) return 0; /* no symbol file specified */
663
664     add_extra_undef_symbols( spec );
665     remove_ignored_symbols();
666
667     for (i = 0; i < nb_imports; i++)
668     {
669         struct import *imp = dll_imports[i];
670
671         for (j = 0; j < nb_undef_symbols; j++)
672         {
673             ORDDEF *odp = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
674             if (odp)
675             {
676                 add_import_func( imp, odp );
677                 free( undef_symbols[j] );
678                 undef_symbols[j] = NULL;
679             }
680         }
681         /* remove all the holes in the undef symbols list */
682         if (!remove_symbol_holes() && check_unused( imp, spec ))
683         {
684             /* the dll is not used, get rid of it */
685             warning( "%s imported but no symbols used\n", imp->spec->file_name );
686             remove_import_dll( i );
687             i--;
688         }
689     }
690     return 1;
691 }
692
693 /* output the import table of a Win32 module */
694 static int output_immediate_imports( FILE *outfile )
695 {
696     int i, j, pos;
697     int nb_imm = nb_imports - nb_delayed;
698     static const char import_thunks[] = "__wine_spec_import_thunks";
699
700     if (!nb_imm) goto done;
701
702     /* main import header */
703
704     fprintf( outfile, "\nstatic struct {\n" );
705     fprintf( outfile, "  struct {\n" );
706     fprintf( outfile, "    void        *OriginalFirstThunk;\n" );
707     fprintf( outfile, "    unsigned int TimeDateStamp;\n" );
708     fprintf( outfile, "    unsigned int ForwarderChain;\n" );
709     fprintf( outfile, "    const char  *Name;\n" );
710     fprintf( outfile, "    void        *FirstThunk;\n" );
711     fprintf( outfile, "  } imp[%d];\n", nb_imm+1 );
712     fprintf( outfile, "  const char *data[%d];\n",
713              total_imports - total_delayed + nb_imm );
714     fprintf( outfile, "} imports = {\n  {\n" );
715
716     /* list of dlls */
717
718     for (i = j = 0; i < nb_imports; i++)
719     {
720         if (dll_imports[i]->delay) continue;
721         fprintf( outfile, "    { 0, 0, 0, \"%s\", &imports.data[%d] },\n",
722                  dll_imports[i]->spec->file_name, j );
723         j += dll_imports[i]->nb_imports + 1;
724     }
725
726     fprintf( outfile, "    { 0, 0, 0, 0, 0 },\n" );
727     fprintf( outfile, "  },\n  {\n" );
728
729     /* list of imported functions */
730
731     for (i = 0; i < nb_imports; i++)
732     {
733         if (dll_imports[i]->delay) continue;
734         fprintf( outfile, "    /* %s */\n", dll_imports[i]->spec->file_name );
735         for (j = 0; j < dll_imports[i]->nb_imports; j++)
736         {
737             ORDDEF *odp = dll_imports[i]->imports[j];
738             if (!(odp->flags & FLAG_NONAME))
739             {
740                 unsigned short ord = odp->ordinal;
741                 fprintf( outfile, "    \"\\%03o\\%03o%s\",\n",
742                          *(unsigned char *)&ord, *((unsigned char *)&ord + 1), odp->name );
743             }
744             else
745                 fprintf( outfile, "    (char *)%d,\n", odp->ordinal );
746         }
747         fprintf( outfile, "    0,\n" );
748     }
749     fprintf( outfile, "  }\n};\n\n" );
750
751     /* thunks for imported functions */
752
753     fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
754     pos = (sizeof(void *) + 2*sizeof(unsigned int) + sizeof(const char *) + sizeof(void *)) *
755             (nb_imm + 1);  /* offset of imports.data from start of imports */
756     fprintf( outfile, "asm(\".text\\n\\t.align %d\\n\"\n", get_alignment(8) );
757     fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\"\n", import_thunks);
758
759     for (i = 0; i < nb_imports; i++)
760     {
761         if (dll_imports[i]->delay) continue;
762         for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += sizeof(const char *))
763         {
764             ORDDEF *odp = dll_imports[i]->imports[j];
765             const char *name = odp->name ? odp->name : odp->export_name;
766             fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
767             fprintf( outfile, "    \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
768             fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\\t", name);
769
770 #if defined(__i386__)
771             if (strstr( name, "__wine_call_from_16" ))
772                 fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos );
773             else
774                 fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos );
775 #elif defined(__sparc__)
776             if ( !UsePIC )
777             {
778                 fprintf( outfile, "sethi %%hi(imports+%d), %%g1\\n\\t", pos );
779                 fprintf( outfile, "ld [%%g1+%%lo(imports+%d)], %%g1\\n\\t", pos );
780                 fprintf( outfile, "jmp %%g1\\n\\tnop\\n" );
781             }
782             else
783             {
784                 /* Hmpf.  Stupid sparc assembler always interprets global variable
785                    names as GOT offsets, so we have to do it the long way ... */
786                 fprintf( outfile, "save %%sp, -96, %%sp\\n" );
787                 fprintf( outfile, "0:\\tcall 1f\\n\\tnop\\n" );
788                 fprintf( outfile, "1:\\tsethi %%hi(imports+%d-0b), %%g1\\n\\t", pos );
789                 fprintf( outfile, "or %%g1, %%lo(imports+%d-0b), %%g1\\n\\t", pos );
790                 fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
791                 fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
792             }
793
794 #elif defined(__powerpc__)
795             fprintf(outfile, "\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
796             fprintf(outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[9], ppc_reg[1]);
797             fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
798             fprintf(outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[8], ppc_reg[1]);
799             fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
800             fprintf(outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[7], ppc_reg[1]);
801
802             fprintf(outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("imports") "+ %d")  "\\n\"\n", ppc_reg[9], pos);
803             fprintf(outfile, "\t\"\\tla  %s, " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
804             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
805             fprintf(outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
806
807             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[7], ppc_reg[1]);
808             fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
809             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[8], ppc_reg[1]);
810             fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
811             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[9], ppc_reg[1]);
812             fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
813             fprintf(outfile, "\t\"\\tbctr\\n");
814 #elif defined(__ALPHA__)
815             fprintf( outfile, "\tlda $0,imports\\n\"\n" );
816             fprintf( outfile, "\t\"\\tlda $0,%d($0)\\n\"\n", pos);
817             fprintf( outfile, "\t\"\\tjmp $31,($0)\\n" );
818 #else
819 #error You need to define import thunks for your architecture!
820 #endif
821             fprintf( outfile, "\"\n" );
822             output_function_size( outfile, name );
823         }
824         pos += 4;
825     }
826     output_function_size( outfile, import_thunks );
827     fprintf( outfile, "    \".text\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
828
829  done:
830     return nb_imm;
831 }
832
833 /* output the delayed import table of a Win32 module */
834 static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
835 {
836     int i, idx, j, pos;
837     static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders";
838     static const char delayed_import_thunks[] = "__wine_spec_delayed_import_thunks";
839
840     if (!nb_delayed) goto done;
841
842     for (i = 0; i < nb_imports; i++)
843     {
844         if (!dll_imports[i]->delay) continue;
845         fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i);
846         for (j = 0; j < dll_imports[i]->nb_imports; j++)
847         {
848             ORDDEF *odp = dll_imports[i]->imports[j];
849             const char *name = odp->name ? odp->name : odp->export_name;
850             fprintf( outfile, "void __wine_delay_imp_%d_%s();\n", i, name );
851         }
852     }
853     fprintf( outfile, "\n" );
854     fprintf( outfile, "static struct {\n" );
855     fprintf( outfile, "  struct ImgDelayDescr {\n" );
856     fprintf( outfile, "    unsigned int  grAttrs;\n" );
857     fprintf( outfile, "    const char   *szName;\n" );
858     fprintf( outfile, "    void        **phmod;\n" );
859     fprintf( outfile, "    void        **pIAT;\n" );
860     fprintf( outfile, "    const char  **pINT;\n" );
861     fprintf( outfile, "    void*         pBoundIAT;\n" );
862     fprintf( outfile, "    void*         pUnloadIAT;\n" );
863     fprintf( outfile, "    unsigned long dwTimeStamp;\n" );
864     fprintf( outfile, "  } imp[%d];\n", nb_delayed );
865     fprintf( outfile, "  void         *IAT[%d];\n", total_delayed );
866     fprintf( outfile, "  const char   *INT[%d];\n", total_delayed );
867     fprintf( outfile, "} delay_imports = {\n" );
868     fprintf( outfile, "  {\n" );
869     for (i = j = 0; i < nb_imports; i++)
870     {
871         if (!dll_imports[i]->delay) continue;
872         fprintf( outfile, "    { 0, \"%s\", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n",
873                  dll_imports[i]->spec->file_name, i, j, j );
874         j += dll_imports[i]->nb_imports;
875     }
876     fprintf( outfile, "  },\n  {\n" );
877     for (i = 0; i < nb_imports; i++)
878     {
879         if (!dll_imports[i]->delay) continue;
880         fprintf( outfile, "    /* %s */\n", dll_imports[i]->spec->file_name );
881         for (j = 0; j < dll_imports[i]->nb_imports; j++)
882         {
883             ORDDEF *odp = dll_imports[i]->imports[j];
884             const char *name = odp->name ? odp->name : odp->export_name;
885             fprintf( outfile, "    &__wine_delay_imp_%d_%s,\n", i, name );
886         }
887     }
888     fprintf( outfile, "  },\n  {\n" );
889     for (i = 0; i < nb_imports; i++)
890     {
891         if (!dll_imports[i]->delay) continue;
892         fprintf( outfile, "    /* %s */\n", dll_imports[i]->spec->file_name );
893         for (j = 0; j < dll_imports[i]->nb_imports; j++)
894         {
895             ORDDEF *odp = dll_imports[i]->imports[j];
896             if (!odp->name)
897                 fprintf( outfile, "    (char *)%d,\n", odp->ordinal );
898             else
899                 fprintf( outfile, "    \"%s\",\n", odp->name );
900         }
901     }
902     fprintf( outfile, "  }\n};\n\n" );
903
904     fprintf( outfile, "extern void __stdcall RaiseException(unsigned int, unsigned int, unsigned int, const void *args[]);\n" );
905     fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n");
906     fprintf( outfile, "extern void * __stdcall GetProcAddress(void *, const char*);\n");
907     fprintf( outfile, "\n" );
908
909     fprintf( outfile, "void *__stdcall __wine_delay_load( int idx_nr )\n" );
910     fprintf( outfile, "{\n" );
911     fprintf( outfile, "  int idx = idx_nr >> 16, nr = idx_nr & 0xffff;\n" );
912     fprintf( outfile, "  struct ImgDelayDescr *imd = delay_imports.imp + idx;\n" );
913     fprintf( outfile, "  void **pIAT = imd->pIAT + nr;\n" );
914     fprintf( outfile, "  const char** pINT = imd->pINT + nr;\n" );
915     fprintf( outfile, "  void *fn;\n\n" );
916
917     fprintf( outfile, "  if (!*imd->phmod) *imd->phmod = LoadLibraryA(imd->szName);\n" );
918     fprintf( outfile, "  if (*imd->phmod && (fn = GetProcAddress(*imd->phmod, *pINT)))\n");
919     fprintf( outfile, "    /* patch IAT with final value */\n" );
920     fprintf( outfile, "    return *pIAT = fn;\n" );
921     fprintf( outfile, "  else {\n");
922     fprintf( outfile, "    const void *args[2];\n" );
923     fprintf( outfile, "    args[0] = imd->szName;\n" );
924     fprintf( outfile, "    args[1] = *pINT;\n" );
925     fprintf( outfile, "    RaiseException( 0x%08x, %d, 2, args );\n",
926              EXCEPTION_WINE_STUB, EH_NONCONTINUABLE );
927     fprintf( outfile, "    return 0;\n" );
928     fprintf( outfile, "  }\n}\n\n" );
929
930     fprintf( outfile, "#ifndef __GNUC__\n" );
931     fprintf( outfile, "static void __asm__dummy_delay_import(void) {\n" );
932     fprintf( outfile, "#endif\n" );
933
934     fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) );
935     fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_loaders);
936     fprintf( outfile, "    \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
937     fprintf( outfile, "    \"" __ASM_NAME("__wine_delay_load_asm") ":\\n\"\n" );
938 #if defined(__i386__)
939     fprintf( outfile, "    \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
940     fprintf( outfile, "    \"\\tcall __wine_delay_load\\n\"\n" );
941     fprintf( outfile, "    \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
942 #elif defined(__sparc__)
943     fprintf( outfile, "    \"\\tsave %%sp, -96, %%sp\\n\"\n" );
944     fprintf( outfile, "    \"\\tcall __wine_delay_load\\n\"\n" );
945     fprintf( outfile, "    \"\\tmov %%g1, %%o0\\n\"\n" );
946     fprintf( outfile, "    \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
947 #elif defined(__powerpc__)
948 # if defined(__APPLE__)
949 /* On darwin an extra 56 bytes must be allowed for the linkage area+param area */
950 #  define extra_stack_storage    56
951 # else
952 #  define extra_stack_storage    0
953 # endif
954     /* Save all callee saved registers into a stackframe. */
955     fprintf( outfile, "    \"\\tstwu %s, -%d(%s)\\n\"\n",ppc_reg[1], 48+extra_stack_storage, ppc_reg[1]);
956     fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[3],  4+extra_stack_storage, ppc_reg[1]);
957     fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[4],  8+extra_stack_storage, ppc_reg[1]);
958     fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]);
959     fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]);
960     fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]);
961     fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]);
962     fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]);
963     fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]);
964     fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]);
965     fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]);
966
967     /* r0 -> r3 (arg1) */
968     fprintf( outfile, "    \"\\tmr %s, %s\\n\"\n", ppc_reg[3], ppc_reg[0]);
969
970     /* save return address */
971     fprintf( outfile, "    \"\\tmflr %s\\n\"\n", ppc_reg[0]);
972     fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[0], 44+extra_stack_storage, ppc_reg[1]);
973
974     /* Call the __wine_delay_load function, arg1 is arg1. */
975     fprintf( outfile, "    \"\\tbl " __ASM_NAME("__wine_delay_load") "\\n\"\n");
976
977     /* Load return value from call into ctr register */
978     fprintf( outfile, "    \"\\tmtctr %s\\n\"\n", ppc_reg[3]);
979
980     /* restore all saved registers and drop stackframe. */
981     fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[3],  4+extra_stack_storage, ppc_reg[1]);
982     fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[4],  8+extra_stack_storage, ppc_reg[1]);
983     fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]);
984     fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]);
985     fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]);
986     fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]);
987     fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]);
988     fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]);
989     fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]);
990     fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]);
991
992     /* Load return value from call into return register */
993     fprintf( outfile, "    \"\\tlwz  %s,  %d(%s)\\n\"\n", ppc_reg[0], 44+extra_stack_storage, ppc_reg[1]);
994     fprintf( outfile, "    \"\\tmtlr %s\\n\"\n", ppc_reg[0]);
995     fprintf( outfile, "    \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[1], ppc_reg[1],  48+extra_stack_storage);
996
997     /* branch to ctr register. */
998     fprintf( outfile, "    \"bctr\\n\"\n");
999 #elif defined(__ALPHA__)
1000     fprintf( outfile, "    \"\\tjsr $26,__wine_delay_load\\n\"\n" );
1001     fprintf( outfile, "    \"\\tjmp $31,($0)\\n\"\n" );
1002 #else
1003 #error You need to defined delayed import thunks for your architecture!
1004 #endif
1005     output_function_size( outfile, "__wine_delay_load_asm" );
1006
1007     for (i = idx = 0; i < nb_imports; i++)
1008     {
1009         if (!dll_imports[i]->delay) continue;
1010         for (j = 0; j < dll_imports[i]->nb_imports; j++)
1011         {
1012             char buffer[128];
1013             ORDDEF *odp = dll_imports[i]->imports[j];
1014             const char *name = odp->name ? odp->name : odp->export_name;
1015
1016             sprintf( buffer, "__wine_delay_imp_%d_%s", i, name );
1017             fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer );
1018             fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\"\n", buffer );
1019 #if defined(__i386__)
1020             fprintf( outfile, "    \"\\tmovl $%d, %%eax\\n\"\n", (idx << 16) | j );
1021             fprintf( outfile, "    \"\\tjmp __wine_delay_load_asm\\n\"\n" );
1022 #elif defined(__sparc__)
1023             fprintf( outfile, "    \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
1024             fprintf( outfile, "    \"\\tb,a __wine_delay_load_asm\\n\"\n" );
1025 #elif defined(__powerpc__)
1026 #ifdef __APPLE__
1027             /* On Darwin we can use r0 and r2 */
1028             /* Upper part in r2 */
1029             fprintf( outfile, "    \"\\tlis %s, %d\\n\"\n", ppc_reg[2], idx);
1030             /* Lower part + r2 -> r0, Note we can't use r0 directly */
1031             fprintf( outfile, "    \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[2], j);
1032             fprintf( outfile, "    \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
1033 #else /* __APPLE__ */
1034             /* On linux we can't use r2 since r2 is not a scratch register (hold the TOC) */
1035             /* Save r13 on the stack */
1036             fprintf( outfile, "    \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1037             fprintf( outfile, "    \"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[13], ppc_reg[1]);
1038             /* Upper part in r13 */
1039             fprintf( outfile, "    \"\\tlis %s, %d\\n\"\n", ppc_reg[13], idx);
1040             /* Lower part + r13 -> r0, Note we can't use r0 directly */
1041             fprintf( outfile, "    \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[13], j);
1042             /* Restore r13 */
1043             fprintf( outfile, "    \"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[13], ppc_reg[1]);
1044             fprintf( outfile, "    \"\\taddic %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1045             fprintf( outfile, "    \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
1046 #endif /* __APPLE__ */
1047 #elif defined(__ALPHA__)
1048             fprintf( outfile, "    \"\\tlda $0,%d($31)\\n\"\n", j);
1049             fprintf( outfile, "    \"\\tldah $0,%d($0)\\n\"\n", idx);
1050             fprintf( outfile, "    \"\\tjmp $31,__wine_delay_load_asm\\n\"\n" );
1051 #else
1052 #error You need to defined delayed import thunks for your architecture!
1053 #endif
1054             output_function_size( outfile, name );
1055         }
1056         idx++;
1057     }
1058     output_function_size( outfile, delayed_import_loaders );
1059
1060     fprintf( outfile, "\n    \".align %d\\n\"\n", get_alignment(8) );
1061     fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_thunks);
1062     pos = nb_delayed * 32;
1063     for (i = 0; i < nb_imports; i++)
1064     {
1065         if (!dll_imports[i]->delay) continue;
1066         for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
1067         {
1068             ORDDEF *odp = dll_imports[i]->imports[j];
1069             const char *name = odp->name ? odp->name : odp->export_name;
1070
1071             fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
1072             fprintf( outfile, "    \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
1073             fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\\t\"", name );
1074 #if defined(__i386__)
1075             if (strstr( name, "__wine_call_from_16" ))
1076                 fprintf( outfile, "\".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n\"", pos );
1077             else
1078                 fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos );
1079 #elif defined(__sparc__)
1080             if ( !UsePIC )
1081             {
1082                 fprintf( outfile, "\"sethi %%hi(delay_imports+%d), %%g1\\n\\t\"", pos );
1083                 fprintf( outfile, "\"ld [%%g1+%%lo(delay_imports+%d)], %%g1\\n\\t\"", pos );
1084                 fprintf( outfile, "\"jmp %%g1\\n\\tnop\\n\"" );
1085             }
1086             else
1087             {
1088                 /* Hmpf.  Stupid sparc assembler always interprets global variable
1089                    names as GOT offsets, so we have to do it the long way ... */
1090                 fprintf( outfile, "\"save %%sp, -96, %%sp\\n\"" );
1091                 fprintf( outfile, "\"0:\\tcall 1f\\n\\tnop\\n\"" );
1092                 fprintf( outfile, "\"1:\\tsethi %%hi(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1093                 fprintf( outfile, "\"or %%g1, %%lo(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1094                 fprintf( outfile, "\"ld [%%g1+%%o7], %%g1\\n\\t\"" );
1095                 fprintf( outfile, "\"jmp %%g1\\n\\trestore\\n\"" );
1096             }
1097
1098 #elif defined(__powerpc__)
1099             fprintf( outfile, "\t\"addi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1100             fprintf( outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[9], ppc_reg[1]);
1101             fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1102             fprintf( outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[8], ppc_reg[1]);
1103             fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1104             fprintf( outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[7], ppc_reg[1]);
1105
1106             fprintf( outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("delay_imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
1107             fprintf( outfile, "\t\"\\tla  %s, " ppc_low (__ASM_NAME("delay_imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
1108             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
1109             fprintf( outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
1110
1111             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[7], ppc_reg[1]);
1112             fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1113             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[8], ppc_reg[1]);
1114             fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1115             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[9], ppc_reg[1]);
1116             fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1117             fprintf( outfile, "\t\"\\tbctr\\n\"");
1118 #elif defined(__ALPHA__)
1119             fprintf( outfile, "\t\"lda $0,delay_imports\\n\"\n" );
1120             fprintf( outfile, "\t\"\\tlda $0,%d($0)\\n\"\n", pos);
1121             fprintf( outfile, "\t\"\\tjmp $31,($0)\\n\"" );
1122 #else
1123 #error You need to define delayed import thunks for your architecture!
1124 #endif
1125             fprintf( outfile, "\n" );
1126             output_function_size( outfile, name );
1127         }
1128     }
1129     output_function_size( outfile, delayed_import_thunks );
1130     fprintf( outfile, ");\n" );
1131     fprintf( outfile, "#ifndef __GNUC__\n" );
1132     fprintf( outfile, "}\n" );
1133     fprintf( outfile, "#endif\n" );
1134     fprintf( outfile, "\n" );
1135
1136  done:
1137     return nb_delayed;
1138 }
1139
1140 /* output the import and delayed import tables of a Win32 module
1141  * returns number of DLLs exported in 'immediate' mode
1142  */
1143 int output_imports( FILE *outfile, DLLSPEC *spec )
1144 {
1145    output_delayed_imports( outfile, spec );
1146    return output_immediate_imports( outfile );
1147 }