Move semaphore objects into directory name space.
[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 <assert.h>
26 #include <ctype.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #ifdef HAVE_SYS_STAT_H
32 # include <sys/stat.h>
33 #endif
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37
38 #include "windef.h"
39 #include "winbase.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 struct name_table
56 {
57     char **names;
58     unsigned int count, size;
59 };
60
61 static struct name_table undef_symbols;    /* list of undefined symbols */
62 static struct name_table ignore_symbols;   /* list of symbols to ignore */
63 static struct name_table extra_ld_symbols; /* list of extra symbols that ld should resolve */
64 static struct name_table delayed_imports;  /* list of delayed import dlls */
65 static struct name_table ext_link_imports; /* list of external symbols to link to */
66
67 static struct import **dll_imports = NULL;
68 static int nb_imports = 0;      /* number of imported dlls (delayed or not) */
69 static int nb_delayed = 0;      /* number of delayed dlls */
70 static int total_imports = 0;   /* total number of imported functions */
71 static int total_delayed = 0;   /* total number of imported functions in delayed DLLs */
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
125 static inline const char *ppc_reg( int reg )
126 {
127     static const char * const ppc_regs[32] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
128                                                "r8", "r9", "r10","r11","r12","r13","r14","r15",
129                                                "r16","r17","r18","r19","r20","r21","r22","r23",
130                                                "r24","r25","r26","r27","r28","r29","r30","r31" };
131     if (target_platform == PLATFORM_APPLE) return ppc_regs[reg];
132     return ppc_regs[reg] + 1;  /* skip the 'r' */
133 }
134
135 /* compare function names; helper for resolve_imports */
136 static int name_cmp( const void *name, const void *entry )
137 {
138     return strcmp( *(const char* const *)name, *(const char* const *)entry );
139 }
140
141 /* compare function names; helper for resolve_imports */
142 static int func_cmp( const void *func1, const void *func2 )
143 {
144     const ORDDEF *odp1 = *(const ORDDEF * const *)func1;
145     const ORDDEF *odp2 = *(const ORDDEF * const *)func2;
146     return strcmp( odp1->name ? odp1->name : odp1->export_name,
147                    odp2->name ? odp2->name : odp2->export_name );
148 }
149
150 /* add a name to a name table */
151 inline static void add_name( struct name_table *table, const char *name )
152 {
153     if (table->count == table->size)
154     {
155         table->size += (table->size / 2);
156         if (table->size < 32) table->size = 32;
157         table->names = xrealloc( table->names, table->size * sizeof(*table->names) );
158     }
159     table->names[table->count++] = xstrdup( name );
160 }
161
162 /* remove a name from a name table */
163 inline static void remove_name( struct name_table *table, unsigned int idx )
164 {
165     assert( idx < table->count );
166     free( table->names[idx] );
167     memmove( table->names + idx, table->names + idx + 1,
168              (table->count - idx - 1) * sizeof(*table->names) );
169     table->count--;
170 }
171
172 /* make a name table empty */
173 inline static void empty_name_table( struct name_table *table )
174 {
175     unsigned int i;
176
177     for (i = 0; i < table->count; i++) free( table->names[i] );
178     table->count = 0;
179 }
180
181 /* locate a name in a (sorted) list */
182 inline static const char *find_name( const char *name, const struct name_table *table )
183 {
184     char **res = NULL;
185
186     if (table->count) res = bsearch( &name, table->names, table->count, sizeof(*table->names), name_cmp );
187     return res ? *res : NULL;
188 }
189
190 /* sort a name table */
191 inline static void sort_names( struct name_table *table )
192 {
193     if (table->count) qsort( table->names, table->count, sizeof(*table->names), name_cmp );
194 }
195
196 /* locate an export in a (sorted) export list */
197 inline static ORDDEF *find_export( const char *name, ORDDEF **table, int size )
198 {
199     ORDDEF func, *odp, **res = NULL;
200
201     func.name = (char *)name;
202     func.ordinal = -1;
203     odp = &func;
204     if (table) res = bsearch( &odp, table, size, sizeof(*table), func_cmp );
205     return res ? *res : NULL;
206 }
207
208 /* free an import structure */
209 static void free_imports( struct import *imp )
210 {
211     free( imp->exports );
212     free( imp->imports );
213     free_dll_spec( imp->spec );
214     free( imp->full_name );
215     free( imp );
216 }
217
218 /* check whether a given dll is imported in delayed mode */
219 static int is_delayed_import( const char *name )
220 {
221     int i;
222
223     for (i = 0; i < delayed_imports.count; i++)
224     {
225         if (!strcmp( delayed_imports.names[i], name )) return 1;
226     }
227     return 0;
228 }
229
230 /* check whether a given dll has already been imported */
231 static struct import *is_already_imported( const char *name )
232 {
233     int i;
234
235     for (i = 0; i < nb_imports; i++)
236     {
237         if (!strcmp( dll_imports[i]->spec->file_name, name )) return dll_imports[i];
238     }
239     return NULL;
240 }
241
242 /* open the .so library for a given dll in a specified path */
243 static char *try_library_path( const char *path, const char *name )
244 {
245     char *buffer;
246     int fd;
247
248     buffer = xmalloc( strlen(path) + strlen(name) + 9 );
249     sprintf( buffer, "%s/lib%s.def", path, name );
250
251     /* check if the file exists */
252     if ((fd = open( buffer, O_RDONLY )) != -1)
253     {
254         close( fd );
255         return buffer;
256     }
257     free( buffer );
258     return NULL;
259 }
260
261 /* find the .def import library for a given dll */
262 static char *find_library( const char *name )
263 {
264     char *fullname;
265     int i;
266
267     for (i = 0; i < nb_lib_paths; i++)
268     {
269         if ((fullname = try_library_path( lib_path[i], name ))) return fullname;
270     }
271     fatal_error( "could not open .def file for %s\n", name );
272     return NULL;
273 }
274
275 /* read in the list of exported symbols of an import library */
276 static int read_import_lib( struct import *imp )
277 {
278     FILE *f;
279     int i, ret;
280     struct stat stat;
281     struct import *prev_imp;
282     DLLSPEC *spec = imp->spec;
283
284     f = open_input_file( NULL, imp->full_name );
285     fstat( fileno(f), &stat );
286     imp->dev = stat.st_dev;
287     imp->ino = stat.st_ino;
288     ret = parse_def_file( f, spec );
289     close_input_file( f );
290     if (!ret) return 0;
291
292     /* check if we already imported that library from a different file */
293     if ((prev_imp = is_already_imported( spec->file_name )))
294     {
295         if (prev_imp->dev != imp->dev || prev_imp->ino != imp->ino)
296             fatal_error( "%s and %s have the same export name '%s'\n",
297                          prev_imp->full_name, imp->full_name, spec->file_name );
298         return 0;  /* the same file was already loaded, ignore this one */
299     }
300
301     if (is_delayed_import( spec->file_name ))
302     {
303         imp->delay = 1;
304         nb_delayed++;
305     }
306
307     imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) );
308
309     for (i = 0; i < spec->nb_entry_points; i++)
310     {
311         ORDDEF *odp = &spec->entry_points[i];
312
313         if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
314         if (odp->flags & FLAG_PRIVATE) continue;
315         imp->exports[imp->nb_exports++] = odp;
316     }
317     imp->exports = xrealloc( imp->exports, imp->nb_exports * sizeof(*imp->exports) );
318     if (imp->nb_exports)
319         qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp );
320     return 1;
321 }
322
323 /* build the dll exported name from the import lib name or path */
324 static char *get_dll_name( const char *name, const char *filename )
325 {
326     char *ret;
327
328     if (filename)
329     {
330         const char *basename = strrchr( filename, '/' );
331         if (!basename) basename = filename;
332         else basename++;
333         if (!strncmp( basename, "lib", 3 )) basename += 3;
334         ret = xmalloc( strlen(basename) + 5 );
335         strcpy( ret, basename );
336         if (strendswith( ret, ".def" )) ret[strlen(ret)-4] = 0;
337     }
338     else
339     {
340         ret = xmalloc( strlen(name) + 5 );
341         strcpy( ret, name );
342     }
343     if (!strchr( ret, '.' )) strcat( ret, ".dll" );
344     return ret;
345 }
346
347 /* add a dll to the list of imports */
348 void add_import_dll( const char *name, const char *filename )
349 {
350     struct import *imp = xmalloc( sizeof(*imp) );
351
352     imp->spec            = alloc_dll_spec();
353     imp->spec->file_name = get_dll_name( name, filename );
354     imp->delay           = 0;
355     imp->imports         = NULL;
356     imp->nb_imports      = 0;
357     imp->exports         = NULL;
358     imp->nb_exports      = 0;
359
360     if (filename) imp->full_name = xstrdup( filename );
361     else imp->full_name = find_library( name );
362
363     if (read_import_lib( imp ))
364     {
365         dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) );
366         dll_imports[nb_imports++] = imp;
367     }
368     else
369     {
370         free_imports( imp );
371         if (nb_errors) exit(1);
372     }
373 }
374
375 /* add a library to the list of delayed imports */
376 void add_delayed_import( const char *name )
377 {
378     struct import *imp;
379     char *fullname = get_dll_name( name, NULL );
380
381     add_name( &delayed_imports, fullname );
382     if ((imp = is_already_imported( fullname )) && !imp->delay)
383     {
384         imp->delay = 1;
385         nb_delayed++;
386     }
387     free( fullname );
388 }
389
390 /* remove an imported dll, based on its index in the dll_imports array */
391 static void remove_import_dll( int index )
392 {
393     struct import *imp = dll_imports[index];
394
395     memmove( &dll_imports[index], &dll_imports[index+1], sizeof(imp) * (nb_imports - index - 1) );
396     nb_imports--;
397     if (imp->delay) nb_delayed--;
398     free_imports( imp );
399 }
400
401 /* initialize the list of ignored symbols */
402 static void init_ignored_symbols(void)
403 {
404     unsigned int i;
405
406     for (i = 0; i < sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]); i++)
407         add_name( &ignore_symbols, default_ignored_symbols[i] );
408 }
409
410 /* add a symbol to the ignored symbol list */
411 /* if the name starts with '-' the symbol is removed instead */
412 void add_ignore_symbol( const char *name )
413 {
414     unsigned int i;
415
416     if (!ignore_symbols.size) init_ignored_symbols();  /* first time around, fill list with defaults */
417
418     if (name[0] == '-')  /* remove it */
419     {
420         if (!name[1]) empty_name_table( &ignore_symbols );  /* remove everything */
421         else for (i = 0; i < ignore_symbols.count; i++)
422         {
423             if (!strcmp( ignore_symbols.names[i], name+1 )) remove_name( &ignore_symbols, i-- );
424         }
425     }
426     else add_name( &ignore_symbols, name );
427 }
428
429 /* add a symbol to the list of extra symbols that ld must resolve */
430 void add_extra_ld_symbol( const char *name )
431 {
432     add_name( &extra_ld_symbols, name );
433 }
434
435 /* add a function to the list of imports from a given dll */
436 static void add_import_func( struct import *imp, ORDDEF *func )
437 {
438     imp->imports = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) );
439     imp->imports[imp->nb_imports++] = func;
440     total_imports++;
441     if (imp->delay) total_delayed++;
442 }
443
444 /* get the default entry point for a given spec file */
445 static const char *get_default_entry_point( const DLLSPEC *spec )
446 {
447     if (spec->characteristics & IMAGE_FILE_DLL) return "__wine_spec_dll_entry";
448     if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "__wine_spec_drv_entry";
449     return "__wine_spec_exe_entry";
450 }
451
452 /* check if the spec file exports any stubs */
453 static int has_stubs( const DLLSPEC *spec )
454 {
455     int i;
456     for (i = 0; i < spec->nb_entry_points; i++)
457     {
458         ORDDEF *odp = &spec->entry_points[i];
459         if (odp->type == TYPE_STUB) return 1;
460     }
461     return 0;
462 }
463
464 /* add the extra undefined symbols that will be contained in the generated spec file itself */
465 static void add_extra_undef_symbols( DLLSPEC *spec )
466 {
467     if (!spec->init_func) spec->init_func = xstrdup( get_default_entry_point(spec) );
468     add_extra_ld_symbol( spec->init_func );
469     if (has_stubs( spec )) add_extra_ld_symbol( "__wine_spec_unimplemented_stub" );
470     if (nb_delayed) add_extra_ld_symbol( "__wine_spec_delay_load" );
471 }
472
473 /* check if a given imported dll is not needed, taking forwards into account */
474 static int check_unused( const struct import* imp, const DLLSPEC *spec )
475 {
476     int i;
477     const char *file_name = imp->spec->file_name;
478     size_t len = strlen( file_name );
479     const char *p = strchr( file_name, '.' );
480     if (p && !strcasecmp( p, ".dll" )) len = p - file_name;
481
482     for (i = spec->base; i <= spec->limit; i++)
483     {
484         ORDDEF *odp = spec->ordinals[i];
485         if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
486         if (!strncasecmp( odp->link_name, file_name, len ) &&
487             odp->link_name[len] == '.')
488             return 0;  /* found a forward, it is used */
489     }
490     return 1;
491 }
492
493 /* flag the dll exports that link to an undefined symbol */
494 static void check_undefined_exports( DLLSPEC *spec )
495 {
496     int i;
497
498     for (i = 0; i < spec->nb_entry_points; i++)
499     {
500         ORDDEF *odp = &spec->entry_points[i];
501         if (odp->type == TYPE_STUB) continue;
502         if (odp->flags & FLAG_FORWARD) continue;
503         if (find_name( odp->link_name, &undef_symbols ))
504         {
505             odp->flags |= FLAG_EXT_LINK;
506             add_name( &ext_link_imports, odp->link_name );
507         }
508     }
509 }
510
511 /* create a .o file that references all the undefined symbols we want to resolve */
512 static char *create_undef_symbols_file( DLLSPEC *spec )
513 {
514     char *as_file, *obj_file;
515     unsigned int i;
516     FILE *f;
517
518     as_file = get_temp_file_name( output_file_name, ".s" );
519     if (!(f = fopen( as_file, "w" ))) fatal_error( "Cannot create %s\n", as_file );
520     fprintf( f, "\t.data\n" );
521
522     for (i = 0; i < spec->nb_entry_points; i++)
523     {
524         ORDDEF *odp = &spec->entry_points[i];
525         if (odp->type == TYPE_STUB) continue;
526         if (odp->flags & FLAG_FORWARD) continue;
527         fprintf( f, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->link_name) );
528     }
529     for (i = 0; i < extra_ld_symbols.count; i++)
530         fprintf( f, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(extra_ld_symbols.names[i]) );
531     fclose( f );
532
533     obj_file = get_temp_file_name( output_file_name, ".o" );
534     assemble_file( as_file, obj_file );
535     return obj_file;
536 }
537
538 /* combine a list of object files with ld into a single object file */
539 /* returns the name of the combined file */
540 static const char *ldcombine_files( DLLSPEC *spec, char **argv )
541 {
542     unsigned int i, len = 0;
543     char *cmd, *p, *ld_tmp_file, *undef_file;
544     int err;
545
546     undef_file = create_undef_symbols_file( spec );
547     len += strlen(undef_file) + 1;
548     ld_tmp_file = get_temp_file_name( output_file_name, ".o" );
549     if (!ld_command) ld_command = xstrdup("ld");
550     for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
551     cmd = p = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ld_command)  );
552     p += sprintf( cmd, "%s -r -o %s %s", ld_command, ld_tmp_file, undef_file );
553     for (i = 0; argv[i]; i++)
554         p += sprintf( p, " %s", argv[i] );
555     if (verbose) fprintf( stderr, "%s\n", cmd );
556     err = system( cmd );
557     if (err) fatal_error( "%s -r failed with status %d\n", ld_command, err );
558     free( cmd );
559     return ld_tmp_file;
560 }
561
562 /* read in the list of undefined symbols */
563 void read_undef_symbols( DLLSPEC *spec, char **argv )
564 {
565     size_t prefix_len;
566     FILE *f;
567     char *cmd, buffer[1024], name_prefix[16];
568     int err;
569     const char *name;
570
571     if (!argv[0]) return;
572
573     add_extra_undef_symbols( spec );
574
575     strcpy( name_prefix, asm_name("") );
576     prefix_len = strlen( name_prefix );
577
578     name = ldcombine_files( spec, argv );
579
580     if (!nm_command) nm_command = xstrdup("nm");
581     cmd = xmalloc( strlen(nm_command) + strlen(name) + 5 );
582     sprintf( cmd, "%s -u %s", nm_command, name );
583     if (!(f = popen( cmd, "r" )))
584         fatal_error( "Cannot execute '%s'\n", cmd );
585
586     while (fgets( buffer, sizeof(buffer), f ))
587     {
588         char *p = buffer + strlen(buffer) - 1;
589         if (p < buffer) continue;
590         if (*p == '\n') *p-- = 0;
591         p = buffer;
592         while (*p == ' ') p++;
593         if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
594         if (prefix_len && !strncmp( p, name_prefix, prefix_len )) p += prefix_len;
595         add_name( &undef_symbols, p );
596     }
597     if ((err = pclose( f ))) warning( "%s failed with status %d\n", cmd, err );
598     free( cmd );
599 }
600
601 /* resolve the imports for a Win32 module */
602 int resolve_imports( DLLSPEC *spec )
603 {
604     unsigned int i, j, removed;
605     ORDDEF *odp;
606
607     if (!ignore_symbols.size) init_ignored_symbols();
608     sort_names( &ignore_symbols );
609
610     for (i = 0; i < nb_imports; i++)
611     {
612         struct import *imp = dll_imports[i];
613
614         for (j = removed = 0; j < undef_symbols.count; j++)
615         {
616             if (find_name( undef_symbols.names[j], &ignore_symbols )) continue;
617             odp = find_export( undef_symbols.names[j], imp->exports, imp->nb_exports );
618             if (odp)
619             {
620                 add_import_func( imp, odp );
621                 remove_name( &undef_symbols, j-- );
622                 removed++;
623             }
624         }
625         if (!removed && check_unused( imp, spec ))
626         {
627             /* the dll is not used, get rid of it */
628             warning( "%s imported but no symbols used\n", imp->spec->file_name );
629             remove_import_dll( i );
630             i--;
631         }
632     }
633
634     sort_names( &undef_symbols );
635     check_undefined_exports( spec );
636
637     return 1;
638 }
639
640 /* output the get_pc thunk if needed */
641 void output_get_pc_thunk( FILE *outfile )
642 {
643     if (target_cpu != CPU_x86) return;
644     if (!UsePIC) return;
645     fprintf( outfile, "\n\t.text\n" );
646     fprintf( outfile, "\t.align %d\n", get_alignment(4) );
647     fprintf( outfile, "\t%s\n", func_declaration("__wine_spec_get_pc_thunk_eax") );
648     fprintf( outfile, "%s:\n", asm_name("__wine_spec_get_pc_thunk_eax") );
649     fprintf( outfile, "\tpopl %%eax\n" );
650     fprintf( outfile, "\tpushl %%eax\n" );
651     fprintf( outfile, "\tret\n" );
652     output_function_size( outfile, "__wine_spec_get_pc_thunk_eax" );
653 }
654
655 /* output a single import thunk */
656 static void output_import_thunk( FILE *outfile, const char *name, const char *table, int pos )
657 {
658     fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
659     fprintf( outfile, "\t%s\n", func_declaration(name) );
660     fprintf( outfile, "%s\n", asm_globl(name) );
661
662     switch(target_cpu)
663     {
664     case CPU_x86:
665         if (!UsePIC)
666         {
667             fprintf( outfile, "\tjmp *(%s+%d)\n", table, pos );
668         }
669         else
670         {
671             fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
672             fprintf( outfile, "1:\tjmp *%s+%d-1b(%%eax)\n", table, pos );
673         }
674         break;
675     case CPU_x86_64:
676         fprintf( outfile, "\tjmpq *%s+%d(%%rip)\n", table, pos );
677         break;
678     case CPU_SPARC:
679         if ( !UsePIC )
680         {
681             fprintf( outfile, "\tsethi %%hi(%s+%d), %%g1\n", table, pos );
682             fprintf( outfile, "\tld [%%g1+%%lo(%s+%d)], %%g1\n", table, pos );
683             fprintf( outfile, "\tjmp %%g1\n" );
684             fprintf( outfile, "\tnop\n" );
685         }
686         else
687         {
688             /* Hmpf.  Stupid sparc assembler always interprets global variable
689                names as GOT offsets, so we have to do it the long way ... */
690             fprintf( outfile, "\tsave %%sp, -96, %%sp\n" );
691             fprintf( outfile, "0:\tcall 1f\n" );
692             fprintf( outfile, "\tnop\n" );
693             fprintf( outfile, "1:\tsethi %%hi(%s+%d-0b), %%g1\n", table, pos );
694             fprintf( outfile, "\tor %%g1, %%lo(%s+%d-0b), %%g1\n", table, pos );
695             fprintf( outfile, "\tld [%%g1+%%o7], %%g1\n" );
696             fprintf( outfile, "\tjmp %%g1\n" );
697             fprintf( outfile, "\trestore\n" );
698         }
699         break;
700     case CPU_ALPHA:
701         fprintf( outfile, "\tlda $0,%s\n", table );
702         fprintf( outfile, "\tlda $0,%d($0)\n", pos );
703         fprintf( outfile, "\tjmp $31,($0)\n" );
704         break;
705     case CPU_POWERPC:
706         fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
707         fprintf( outfile, "\tstw  %s, 0(%s)\n",    ppc_reg(9), ppc_reg(1) );
708         fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
709         fprintf( outfile, "\tstw  %s, 0(%s)\n",    ppc_reg(8), ppc_reg(1) );
710         fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
711         fprintf( outfile, "\tstw  %s, 0(%s)\n",    ppc_reg(7), ppc_reg(1) );
712         if (target_platform == PLATFORM_APPLE)
713         {
714             fprintf( outfile, "\tlis %s, ha16(%s+%d)\n", ppc_reg(9), table, pos );
715             fprintf( outfile, "\tla  %s, lo16(%s+%d)(%s)\n", ppc_reg(8), table, pos, ppc_reg(9) );
716         }
717         else
718         {
719             fprintf( outfile, "\tlis %s, (%s+%d)@h\n", ppc_reg(9), table, pos );
720             fprintf( outfile, "\tla  %s, (%s+%d)@l(%s)\n", ppc_reg(8), table, pos, ppc_reg(9) );
721         }
722         fprintf( outfile, "\tlwz  %s, 0(%s)\n", ppc_reg(7), ppc_reg(8) );
723         fprintf( outfile, "\tmtctr %s\n", ppc_reg(7) );
724         fprintf( outfile, "\tlwz  %s, 0(%s)\n",   ppc_reg(7), ppc_reg(1) );
725         fprintf( outfile, "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
726         fprintf( outfile, "\tlwz  %s, 0(%s)\n",   ppc_reg(8), ppc_reg(1) );
727         fprintf( outfile, "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
728         fprintf( outfile, "\tlwz  %s, 0(%s)\n",   ppc_reg(9), ppc_reg(1) );
729         fprintf( outfile, "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
730         fprintf( outfile, "\tbctr\n" );
731         break;
732     }
733     output_function_size( outfile, name );
734 }
735
736 /* check if we need an import directory */
737 int has_imports(void)
738 {
739     return (nb_imports - nb_delayed) > 0;
740 }
741
742 /* output the import table of a Win32 module */
743 static void output_immediate_imports( FILE *outfile )
744 {
745     int i, j;
746     const char *dll_name;
747
748     if (nb_imports == nb_delayed) return;  /* no immediate imports */
749
750     /* main import header */
751
752     fprintf( outfile, "\n/* import table */\n" );
753     fprintf( outfile, "\n\t.data\n" );
754     fprintf( outfile, "\t.align %d\n", get_alignment(4) );
755     fprintf( outfile, ".L__wine_spec_imports:\n" );
756
757     /* list of dlls */
758
759     for (i = j = 0; i < nb_imports; i++)
760     {
761         if (dll_imports[i]->delay) continue;
762         dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
763         fprintf( outfile, "\t.long 0\n" );     /* OriginalFirstThunk */
764         fprintf( outfile, "\t.long 0\n" );     /* TimeDateStamp */
765         fprintf( outfile, "\t.long 0\n" );     /* ForwarderChain */
766         fprintf( outfile, "\t.long .L__wine_spec_import_name_%s-.L__wine_spec_rva_base\n", /* Name */
767                  dll_name );
768         fprintf( outfile, "\t.long .L__wine_spec_import_data_ptrs+%d-.L__wine_spec_rva_base\n",  /* FirstThunk */
769                  j * get_ptr_size() );
770         j += dll_imports[i]->nb_imports + 1;
771     }
772     fprintf( outfile, "\t.long 0\n" );     /* OriginalFirstThunk */
773     fprintf( outfile, "\t.long 0\n" );     /* TimeDateStamp */
774     fprintf( outfile, "\t.long 0\n" );     /* ForwarderChain */
775     fprintf( outfile, "\t.long 0\n" );     /* Name */
776     fprintf( outfile, "\t.long 0\n" );     /* FirstThunk */
777
778     fprintf( outfile, "\n\t.align %d\n", get_alignment(get_ptr_size()) );
779     fprintf( outfile, ".L__wine_spec_import_data_ptrs:\n" );
780     for (i = 0; i < nb_imports; i++)
781     {
782         if (dll_imports[i]->delay) continue;
783         dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
784         for (j = 0; j < dll_imports[i]->nb_imports; j++)
785         {
786             ORDDEF *odp = dll_imports[i]->imports[j];
787             if (!(odp->flags & FLAG_NONAME))
788                 fprintf( outfile, "\t%s .L__wine_spec_import_data_%s_%s-.L__wine_spec_rva_base\n",
789                          get_asm_ptr_keyword(), dll_name, odp->name );
790             else
791             {
792                 if (get_ptr_size() == 8)
793                     fprintf( outfile, "\t.quad 0x800000000000%04x\n", odp->ordinal );
794                 else
795                     fprintf( outfile, "\t.long 0x8000%04x\n", odp->ordinal );
796             }
797         }
798         fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
799     }
800     fprintf( outfile, ".L__wine_spec_imports_end:\n" );
801
802     for (i = 0; i < nb_imports; i++)
803     {
804         if (dll_imports[i]->delay) continue;
805         dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
806         for (j = 0; j < dll_imports[i]->nb_imports; j++)
807         {
808             ORDDEF *odp = dll_imports[i]->imports[j];
809             if (!(odp->flags & FLAG_NONAME))
810             {
811                 fprintf( outfile, "\t.align %d\n", get_alignment(2) );
812                 fprintf( outfile, ".L__wine_spec_import_data_%s_%s:\n", dll_name, odp->name );
813                 fprintf( outfile, "\t%s %d\n", get_asm_short_keyword(), odp->ordinal );
814                 fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), odp->name );
815             }
816         }
817     }
818
819     for (i = 0; i < nb_imports; i++)
820     {
821         if (dll_imports[i]->delay) continue;
822         dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
823         fprintf( outfile, ".L__wine_spec_import_name_%s:\n\t%s \"%s\"\n",
824                  dll_name, get_asm_string_keyword(), dll_imports[i]->spec->file_name );
825     }
826 }
827
828 /* output the import thunks of a Win32 module */
829 static void output_immediate_import_thunks( FILE *outfile )
830 {
831     int i, j, pos;
832     int nb_imm = nb_imports - nb_delayed;
833     static const char import_thunks[] = "__wine_spec_import_thunks";
834
835     if (!nb_imm) return;
836
837     fprintf( outfile, "\n/* immediate import thunks */\n\n" );
838     fprintf( outfile, "\t.text\n" );
839     fprintf( outfile, "\t.align %d\n", get_alignment(8) );
840     fprintf( outfile, "%s:\n", asm_name(import_thunks));
841
842     for (i = pos = 0; i < nb_imports; i++)
843     {
844         if (dll_imports[i]->delay) continue;
845         for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += get_ptr_size())
846         {
847             ORDDEF *odp = dll_imports[i]->imports[j];
848             output_import_thunk( outfile, odp->name ? odp->name : odp->export_name,
849                                  ".L__wine_spec_import_data_ptrs", pos );
850         }
851         pos += get_ptr_size();
852     }
853     output_function_size( outfile, import_thunks );
854 }
855
856 /* output the delayed import table of a Win32 module */
857 static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
858 {
859     int i, j;
860
861     if (!nb_delayed) return;
862
863     fprintf( outfile, "\n/* delayed imports */\n\n" );
864     fprintf( outfile, "\t.data\n" );
865     fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
866     fprintf( outfile, "%s\n", asm_globl("__wine_spec_delay_imports") );
867
868     /* list of dlls */
869
870     for (i = j = 0; i < nb_imports; i++)
871     {
872         if (!dll_imports[i]->delay) continue;
873         fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* grAttrs */
874         fprintf( outfile, "\t%s .L__wine_delay_name_%d\n",       /* szName */
875                  get_asm_ptr_keyword(), i );
876         fprintf( outfile, "\t%s .L__wine_delay_modules+%d\n",    /* phmod */
877                  get_asm_ptr_keyword(), i * get_ptr_size() );
878         fprintf( outfile, "\t%s .L__wine_delay_IAT+%d\n",        /* pIAT */
879                  get_asm_ptr_keyword(), j * get_ptr_size() );
880         fprintf( outfile, "\t%s .L__wine_delay_INT+%d\n",        /* pINT */
881                  get_asm_ptr_keyword(), j * get_ptr_size() );
882         fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pBoundIAT */
883         fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pUnloadIAT */
884         fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* dwTimeStamp */
885         j += dll_imports[i]->nb_imports;
886     }
887     fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* grAttrs */
888     fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* szName */
889     fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* phmod */
890     fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pIAT */
891     fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pINT */
892     fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pBoundIAT */
893     fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pUnloadIAT */
894     fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* dwTimeStamp */
895
896     fprintf( outfile, "\n.L__wine_delay_IAT:\n" );
897     for (i = 0; i < nb_imports; i++)
898     {
899         if (!dll_imports[i]->delay) continue;
900         for (j = 0; j < dll_imports[i]->nb_imports; j++)
901         {
902             ORDDEF *odp = dll_imports[i]->imports[j];
903             const char *name = odp->name ? odp->name : odp->export_name;
904             fprintf( outfile, "\t%s .L__wine_delay_imp_%d_%s\n",
905                      get_asm_ptr_keyword(), i, name );
906         }
907     }
908
909     fprintf( outfile, "\n.L__wine_delay_INT:\n" );
910     for (i = 0; i < nb_imports; i++)
911     {
912         if (!dll_imports[i]->delay) continue;
913         for (j = 0; j < dll_imports[i]->nb_imports; j++)
914         {
915             ORDDEF *odp = dll_imports[i]->imports[j];
916             if (!odp->name)
917                 fprintf( outfile, "\t%s %d\n", get_asm_ptr_keyword(), odp->ordinal );
918             else
919                 fprintf( outfile, "\t%s .L__wine_delay_data_%d_%s\n",
920                          get_asm_ptr_keyword(), i, odp->name );
921         }
922     }
923
924     fprintf( outfile, "\n.L__wine_delay_modules:\n" );
925     for (i = 0; i < nb_imports; i++)
926     {
927         if (dll_imports[i]->delay) fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
928     }
929
930     for (i = 0; i < nb_imports; i++)
931     {
932         if (!dll_imports[i]->delay) continue;
933         fprintf( outfile, ".L__wine_delay_name_%d:\n", i );
934         fprintf( outfile, "\t%s \"%s\"\n",
935                  get_asm_string_keyword(), dll_imports[i]->spec->file_name );
936     }
937
938     for (i = 0; i < nb_imports; i++)
939     {
940         if (!dll_imports[i]->delay) continue;
941         for (j = 0; j < dll_imports[i]->nb_imports; j++)
942         {
943             ORDDEF *odp = dll_imports[i]->imports[j];
944             if (!odp->name) continue;
945             fprintf( outfile, ".L__wine_delay_data_%d_%s:\n", i, odp->name );
946             fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), odp->name );
947         }
948     }
949     output_function_size( outfile, "__wine_spec_delay_imports" );
950 }
951
952 /* output the delayed import thunks of a Win32 module */
953 static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
954 {
955     int i, idx, j, pos, extra_stack_storage = 0;
956     static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders";
957     static const char delayed_import_thunks[] = "__wine_spec_delayed_import_thunks";
958
959     if (!nb_delayed) return;
960
961     fprintf( outfile, "\n/* delayed import thunks */\n\n" );
962     fprintf( outfile, "\t.text\n" );
963     fprintf( outfile, "\t.align %d\n", get_alignment(8) );
964     fprintf( outfile, "%s:\n", asm_name(delayed_import_loaders));
965     fprintf( outfile, "\t%s\n", func_declaration("__wine_delay_load_asm") );
966     fprintf( outfile, "%s:\n", asm_name("__wine_delay_load_asm") );
967     switch(target_cpu)
968     {
969     case CPU_x86:
970         fprintf( outfile, "\tpushl %%ecx\n" );
971         fprintf( outfile, "\tpushl %%edx\n" );
972         fprintf( outfile, "\tpushl %%eax\n" );
973         fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_delay_load") );
974         fprintf( outfile, "\tpopl %%edx\n" );
975         fprintf( outfile, "\tpopl %%ecx\n" );
976         fprintf( outfile, "\tjmp *%%eax\n" );
977         break;
978     case CPU_x86_64:
979         fprintf( outfile, "\tpushq %%rdi\n" );
980         fprintf( outfile, "\tsubq $8,%%rsp\n" );
981         fprintf( outfile, "\tmovq %%r11,%%rdi\n" );
982         fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_delay_load") );
983         fprintf( outfile, "\taddq $8,%%rsp\n" );
984         fprintf( outfile, "\tpopq %%rdi\n" );
985         fprintf( outfile, "\tjmp *%%rax\n" );
986         break;
987     case CPU_SPARC:
988         fprintf( outfile, "\tsave %%sp, -96, %%sp\n" );
989         fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_delay_load") );
990         fprintf( outfile, "\tmov %%g1, %%o0\n" );
991         fprintf( outfile, "\tjmp %%o0\n" );
992         fprintf( outfile, "\trestore\n" );
993         break;
994     case CPU_ALPHA:
995         fprintf( outfile, "\tjsr $26,%s\n", asm_name("__wine_spec_delay_load") );
996         fprintf( outfile, "\tjmp $31,($0)\n" );
997         break;
998     case CPU_POWERPC:
999         if (target_platform == PLATFORM_APPLE) extra_stack_storage = 56;
1000
1001         /* Save all callee saved registers into a stackframe. */
1002         fprintf( outfile, "\tstwu %s, -%d(%s)\n",ppc_reg(1), 48+extra_stack_storage, ppc_reg(1));
1003         fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(3),  4+extra_stack_storage, ppc_reg(1));
1004         fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(4),  8+extra_stack_storage, ppc_reg(1));
1005         fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
1006         fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
1007         fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
1008         fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
1009         fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
1010         fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
1011         fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
1012         fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
1013
1014         /* r0 -> r3 (arg1) */
1015         fprintf( outfile, "\tmr %s, %s\n", ppc_reg(3), ppc_reg(0));
1016
1017         /* save return address */
1018         fprintf( outfile, "\tmflr %s\n", ppc_reg(0));
1019         fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
1020
1021         /* Call the __wine_delay_load function, arg1 is arg1. */
1022         fprintf( outfile, "\tbl %s\n", asm_name("__wine_spec_delay_load") );
1023
1024         /* Load return value from call into ctr register */
1025         fprintf( outfile, "\tmtctr %s\n", ppc_reg(3));
1026
1027         /* restore all saved registers and drop stackframe. */
1028         fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(3),  4+extra_stack_storage, ppc_reg(1));
1029         fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(4),  8+extra_stack_storage, ppc_reg(1));
1030         fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
1031         fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
1032         fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
1033         fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
1034         fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
1035         fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
1036         fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
1037         fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
1038
1039         /* Load return value from call into return register */
1040         fprintf( outfile, "\tlwz  %s,  %d(%s)\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
1041         fprintf( outfile, "\tmtlr %s\n", ppc_reg(0));
1042         fprintf( outfile, "\taddi %s, %s, %d\n", ppc_reg(1), ppc_reg(1),  48+extra_stack_storage);
1043
1044         /* branch to ctr register. */
1045         fprintf( outfile, "\tbctr\n");
1046         break;
1047     }
1048     output_function_size( outfile, "__wine_delay_load_asm" );
1049     fprintf( outfile, "\n" );
1050
1051     for (i = idx = 0; i < nb_imports; i++)
1052     {
1053         if (!dll_imports[i]->delay) continue;
1054         for (j = 0; j < dll_imports[i]->nb_imports; j++)
1055         {
1056             ORDDEF *odp = dll_imports[i]->imports[j];
1057             const char *name = odp->name ? odp->name : odp->export_name;
1058
1059             fprintf( outfile, ".L__wine_delay_imp_%d_%s:\n", i, name );
1060             switch(target_cpu)
1061             {
1062             case CPU_x86:
1063                 fprintf( outfile, "\tmovl $%d, %%eax\n", (idx << 16) | j );
1064                 fprintf( outfile, "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
1065                 break;
1066             case CPU_x86_64:
1067                 fprintf( outfile, "\tmovq $%d,%%r11\n", (idx << 16) | j );
1068                 fprintf( outfile, "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
1069                 break;
1070             case CPU_SPARC:
1071                 fprintf( outfile, "\tset %d, %%g1\n", (idx << 16) | j );
1072                 fprintf( outfile, "\tb,a %s\n", asm_name("__wine_delay_load_asm") );
1073                 break;
1074             case CPU_ALPHA:
1075                 fprintf( outfile, "\tlda $0,%d($31)\n", j);
1076                 fprintf( outfile, "\tldah $0,%d($0)\n", idx);
1077                 fprintf( outfile, "\tjmp $31,%s\n", asm_name("__wine_delay_load_asm") );
1078                 break;
1079             case CPU_POWERPC:
1080                 switch(target_platform)
1081                 {
1082                 case PLATFORM_APPLE:
1083                     /* On Darwin we can use r0 and r2 */
1084                     /* Upper part in r2 */
1085                     fprintf( outfile, "\tlis %s, %d\n", ppc_reg(2), idx);
1086                     /* Lower part + r2 -> r0, Note we can't use r0 directly */
1087                     fprintf( outfile, "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(2), j);
1088                     fprintf( outfile, "\tb %s\n", asm_name("__wine_delay_load_asm") );
1089                     break;
1090                 default:
1091                     /* On linux we can't use r2 since r2 is not a scratch register (hold the TOC) */
1092                     /* Save r13 on the stack */
1093                     fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1));
1094                     fprintf( outfile, "\tstw  %s, 0(%s)\n",    ppc_reg(13), ppc_reg(1));
1095                     /* Upper part in r13 */
1096                     fprintf( outfile, "\tlis %s, %d\n", ppc_reg(13), idx);
1097                     /* Lower part + r13 -> r0, Note we can't use r0 directly */
1098                     fprintf( outfile, "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(13), j);
1099                     /* Restore r13 */
1100                     fprintf( outfile, "\tstw  %s, 0(%s)\n",    ppc_reg(13), ppc_reg(1));
1101                     fprintf( outfile, "\taddic %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1));
1102                     fprintf( outfile, "\tb %s\n", asm_name("__wine_delay_load_asm") );
1103                     break;
1104                 }
1105                 break;
1106             }
1107         }
1108         idx++;
1109     }
1110     output_function_size( outfile, delayed_import_loaders );
1111
1112     fprintf( outfile, "\n\t.align %d\n", get_alignment(get_ptr_size()) );
1113     fprintf( outfile, "%s:\n", asm_name(delayed_import_thunks));
1114     for (i = pos = 0; i < nb_imports; i++)
1115     {
1116         if (!dll_imports[i]->delay) continue;
1117         for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += get_ptr_size())
1118         {
1119             ORDDEF *odp = dll_imports[i]->imports[j];
1120             output_import_thunk( outfile, odp->name ? odp->name : odp->export_name,
1121                                  ".L__wine_delay_IAT", pos );
1122         }
1123     }
1124     output_function_size( outfile, delayed_import_thunks );
1125 }
1126
1127 /* output import stubs for exported entry points that link to external symbols */
1128 static void output_external_link_imports( FILE *outfile, DLLSPEC *spec )
1129 {
1130     unsigned int i, pos;
1131
1132     if (!ext_link_imports.count) return;  /* nothing to do */
1133
1134     sort_names( &ext_link_imports );
1135
1136     /* get rid of duplicate names */
1137     for (i = 1; i < ext_link_imports.count; i++)
1138     {
1139         if (!strcmp( ext_link_imports.names[i-1], ext_link_imports.names[i] ))
1140             remove_name( &ext_link_imports, i-- );
1141     }
1142
1143     fprintf( outfile, "\n/* external link thunks */\n\n" );
1144     fprintf( outfile, "\t.data\n" );
1145     fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
1146     fprintf( outfile, ".L__wine_spec_external_links:\n" );
1147     for (i = 0; i < ext_link_imports.count; i++)
1148         fprintf( outfile, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(ext_link_imports.names[i]) );
1149
1150     fprintf( outfile, "\n\t.text\n" );
1151     fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
1152     fprintf( outfile, "%s:\n", asm_name("__wine_spec_external_link_thunks") );
1153
1154     for (i = pos = 0; i < ext_link_imports.count; i++)
1155     {
1156         char buffer[256];
1157         sprintf( buffer, "__wine_spec_ext_link_%s", ext_link_imports.names[i] );
1158         output_import_thunk( outfile, buffer, ".L__wine_spec_external_links", pos );
1159         pos += get_ptr_size();
1160     }
1161     output_function_size( outfile, "__wine_spec_external_link_thunks" );
1162 }
1163
1164 /*******************************************************************
1165  *         output_stubs
1166  *
1167  * Output the functions for stub entry points
1168  */
1169 void output_stubs( FILE *outfile, DLLSPEC *spec )
1170 {
1171     const char *name, *exp_name;
1172     int i, pos;
1173
1174     if (!has_stubs( spec )) return;
1175
1176     fprintf( outfile, "\n/* stub functions */\n\n" );
1177     fprintf( outfile, "\t.text\n" );
1178
1179     for (i = pos = 0; i < spec->nb_entry_points; i++)
1180     {
1181         ORDDEF *odp = &spec->entry_points[i];
1182         if (odp->type != TYPE_STUB) continue;
1183
1184         name = get_stub_name( odp, spec );
1185         exp_name = odp->name ? odp->name : odp->export_name;
1186         fprintf( outfile, "\t.align %d\n", get_alignment(4) );
1187         fprintf( outfile, "\t%s\n", func_declaration(name) );
1188         fprintf( outfile, "%s:\n", asm_name(name) );
1189         fprintf( outfile, "\tsubl $4,%%esp\n" );
1190
1191         if (UsePIC)
1192         {
1193             fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
1194             fprintf( outfile, "1:" );
1195             if (exp_name)
1196             {
1197                 fprintf( outfile, "\tleal .L__wine_stub_strings+%d-1b(%%eax),%%ecx\n", pos );
1198                 fprintf( outfile, "\tpushl %%ecx\n" );
1199                 pos += strlen(exp_name) + 1;
1200             }
1201             else
1202                 fprintf( outfile, "\tpushl $%d\n", odp->ordinal );
1203             fprintf( outfile, "\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
1204             fprintf( outfile, "\tpushl %%ecx\n" );
1205         }
1206         else
1207         {
1208             if (exp_name)
1209             {
1210                 fprintf( outfile, "\tpushl $.L__wine_stub_strings+%d\n", pos );
1211                 pos += strlen(exp_name) + 1;
1212             }
1213             else
1214                 fprintf( outfile, "\tpushl $%d\n", odp->ordinal );
1215             fprintf( outfile, "\tpushl $.L__wine_spec_file_name\n" );
1216         }
1217         fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
1218         output_function_size( outfile, name );
1219     }
1220
1221     if (pos)
1222     {
1223         fprintf( outfile, "\t%s\n", get_asm_string_section() );
1224         fprintf( outfile, ".L__wine_stub_strings:\n" );
1225         for (i = 0; i < spec->nb_entry_points; i++)
1226         {
1227             ORDDEF *odp = &spec->entry_points[i];
1228             if (odp->type != TYPE_STUB) continue;
1229             exp_name = odp->name ? odp->name : odp->export_name;
1230             if (exp_name)
1231                 fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), exp_name );
1232         }
1233     }
1234 }
1235
1236 /* output the import and delayed import tables of a Win32 module */
1237 void output_imports( FILE *outfile, DLLSPEC *spec )
1238 {
1239     output_immediate_imports( outfile );
1240     output_delayed_imports( outfile, spec );
1241     output_immediate_import_thunks( outfile );
1242     output_delayed_import_thunks( outfile, spec );
1243     output_external_link_imports( outfile, spec );
1244     if (nb_imports || ext_link_imports.count || has_stubs(spec)) output_get_pc_thunk( outfile );
1245 }