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