Implement the use of NETCON_send for HTTP connections when in
[wine/multimedia.git] / tools / winebuild / import.c
blob6a2f8f512e56e7e3f401de86cceddd6fbdbbe257
1 /*
2 * DLL imports support
4 * Copyright 2000, 2004 Alexandre Julliard
5 * Copyright 2000 Eric Pouech
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.
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.
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
22 #include "config.h"
23 #include "wine/port.h"
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
38 #include "windef.h"
39 #include "winbase.h"
40 #include "build.h"
42 struct import
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 */
55 struct name_table
57 char **names;
58 unsigned int count, size;
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 */
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 */
73 /* list of symbols that are ignored by default */
74 static const char * const default_ignored_symbols[] =
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"
125 static inline const char *ppc_reg( int reg )
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' */
135 /* compare function names; helper for resolve_imports */
136 static int name_cmp( const void *name, const void *entry )
138 return strcmp( *(const char* const *)name, *(const char* const *)entry );
141 /* compare function names; helper for resolve_imports */
142 static int func_cmp( const void *func1, const void *func2 )
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 );
150 /* add a name to a name table */
151 inline static void add_name( struct name_table *table, const char *name )
153 if (table->count == table->size)
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) );
159 table->names[table->count++] = xstrdup( name );
162 /* remove a name from a name table */
163 inline static void remove_name( struct name_table *table, unsigned int idx )
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--;
172 /* make a name table empty */
173 inline static void empty_name_table( struct name_table *table )
175 unsigned int i;
177 for (i = 0; i < table->count; i++) free( table->names[i] );
178 table->count = 0;
181 /* locate a name in a (sorted) list */
182 inline static const char *find_name( const char *name, const struct name_table *table )
184 char **res = NULL;
186 if (table->count) res = bsearch( &name, table->names, table->count, sizeof(*table->names), name_cmp );
187 return res ? *res : NULL;
190 /* sort a name table */
191 inline static void sort_names( struct name_table *table )
193 if (table->count) qsort( table->names, table->count, sizeof(*table->names), name_cmp );
196 /* locate an export in a (sorted) export list */
197 inline static ORDDEF *find_export( const char *name, ORDDEF **table, int size )
199 ORDDEF func, *odp, **res = NULL;
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;
208 /* free an import structure */
209 static void free_imports( struct import *imp )
211 free( imp->exports );
212 free( imp->imports );
213 free_dll_spec( imp->spec );
214 free( imp->full_name );
215 free( imp );
218 /* check whether a given dll is imported in delayed mode */
219 static int is_delayed_import( const char *name )
221 int i;
223 for (i = 0; i < delayed_imports.count; i++)
225 if (!strcmp( delayed_imports.names[i], name )) return 1;
227 return 0;
230 /* check whether a given dll has already been imported */
231 static struct import *is_already_imported( const char *name )
233 int i;
235 for (i = 0; i < nb_imports; i++)
237 if (!strcmp( dll_imports[i]->spec->file_name, name )) return dll_imports[i];
239 return NULL;
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 )
245 char *buffer;
246 int fd;
248 buffer = xmalloc( strlen(path) + strlen(name) + 9 );
249 sprintf( buffer, "%s/lib%s.def", path, name );
251 /* check if the file exists */
252 if ((fd = open( buffer, O_RDONLY )) != -1)
254 close( fd );
255 return buffer;
257 free( buffer );
258 return NULL;
261 /* find the .def import library for a given dll */
262 static char *find_library( const char *name )
264 char *fullname;
265 int i;
267 for (i = 0; i < nb_lib_paths; i++)
269 if ((fullname = try_library_path( lib_path[i], name ))) return fullname;
271 fatal_error( "could not open .def file for %s\n", name );
272 return NULL;
275 /* read in the list of exported symbols of an import library */
276 static int read_import_lib( struct import *imp )
278 FILE *f;
279 int i, ret;
280 struct stat stat;
281 struct import *prev_imp;
282 DLLSPEC *spec = imp->spec;
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;
292 /* check if we already imported that library from a different file */
293 if ((prev_imp = is_already_imported( spec->file_name )))
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 */
301 if (is_delayed_import( spec->file_name ))
303 imp->delay = 1;
304 nb_delayed++;
307 imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) );
309 for (i = 0; i < spec->nb_entry_points; i++)
311 ORDDEF *odp = &spec->entry_points[i];
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;
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;
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 )
326 char *ret;
328 if (filename)
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;
338 else
340 ret = xmalloc( strlen(name) + 5 );
341 strcpy( ret, name );
343 if (!strchr( ret, '.' )) strcat( ret, ".dll" );
344 return ret;
347 /* add a dll to the list of imports */
348 void add_import_dll( const char *name, const char *filename )
350 struct import *imp = xmalloc( sizeof(*imp) );
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;
360 if (filename) imp->full_name = xstrdup( filename );
361 else imp->full_name = find_library( name );
363 if (read_import_lib( imp ))
365 dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) );
366 dll_imports[nb_imports++] = imp;
368 else
370 free_imports( imp );
371 if (nb_errors) exit(1);
375 /* add a library to the list of delayed imports */
376 void add_delayed_import( const char *name )
378 struct import *imp;
379 char *fullname = get_dll_name( name, NULL );
381 add_name( &delayed_imports, fullname );
382 if ((imp = is_already_imported( fullname )) && !imp->delay)
384 imp->delay = 1;
385 nb_delayed++;
387 free( fullname );
390 /* remove an imported dll, based on its index in the dll_imports array */
391 static void remove_import_dll( int index )
393 struct import *imp = dll_imports[index];
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 );
401 /* initialize the list of ignored symbols */
402 static void init_ignored_symbols(void)
404 unsigned int i;
406 for (i = 0; i < sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]); i++)
407 add_name( &ignore_symbols, default_ignored_symbols[i] );
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 )
414 unsigned int i;
416 if (!ignore_symbols.size) init_ignored_symbols(); /* first time around, fill list with defaults */
418 if (name[0] == '-') /* remove it */
420 if (!name[1]) empty_name_table( &ignore_symbols ); /* remove everything */
421 else for (i = 0; i < ignore_symbols.count; i++)
423 if (!strcmp( ignore_symbols.names[i], name+1 )) remove_name( &ignore_symbols, i-- );
426 else add_name( &ignore_symbols, name );
429 /* add a symbol to the list of extra symbols that ld must resolve */
430 void add_extra_ld_symbol( const char *name )
432 add_name( &extra_ld_symbols, name );
435 /* add a function to the list of imports from a given dll */
436 static void add_import_func( struct import *imp, ORDDEF *func )
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++;
444 /* get the default entry point for a given spec file */
445 static const char *get_default_entry_point( const DLLSPEC *spec )
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";
452 /* check if the spec file exports any stubs */
453 static int has_stubs( const DLLSPEC *spec )
455 int i;
456 for (i = 0; i < spec->nb_entry_points; i++)
458 ORDDEF *odp = &spec->entry_points[i];
459 if (odp->type == TYPE_STUB) return 1;
461 return 0;
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 )
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" );
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 )
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;
482 for (i = spec->base; i <= spec->limit; i++)
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 */
490 return 1;
493 /* flag the dll exports that link to an undefined symbol */
494 static void check_undefined_exports( DLLSPEC *spec )
496 int i;
498 for (i = 0; i < spec->nb_entry_points; i++)
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 ))
505 odp->flags |= FLAG_EXT_LINK;
506 add_name( &ext_link_imports, odp->link_name );
511 /* create a .o file that references all the undefined symbols we want to resolve */
512 static char *create_undef_symbols_file( DLLSPEC *spec )
514 char *as_file, *obj_file;
515 unsigned int i;
516 FILE *f;
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" );
522 for (i = 0; i < spec->nb_entry_points; i++)
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) );
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 );
533 obj_file = get_temp_file_name( output_file_name, ".o" );
534 assemble_file( as_file, obj_file );
535 return obj_file;
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 )
542 unsigned int i, len = 0;
543 char *cmd, *p, *ld_tmp_file, *undef_file;
544 int err;
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;
562 /* read in the list of undefined symbols */
563 void read_undef_symbols( DLLSPEC *spec, char **argv )
565 size_t prefix_len;
566 FILE *f;
567 char *cmd, buffer[1024], name_prefix[16];
568 int err;
569 const char *name;
571 if (!argv[0]) return;
573 add_extra_undef_symbols( spec );
575 strcpy( name_prefix, asm_name("") );
576 prefix_len = strlen( name_prefix );
578 name = ldcombine_files( spec, argv );
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 );
586 while (fgets( buffer, sizeof(buffer), f ))
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 );
597 if ((err = pclose( f ))) warning( "%s failed with status %d\n", cmd, err );
598 free( cmd );
601 /* resolve the imports for a Win32 module */
602 int resolve_imports( DLLSPEC *spec )
604 unsigned int i, j, removed;
605 ORDDEF *odp;
607 if (!ignore_symbols.size) init_ignored_symbols();
608 sort_names( &ignore_symbols );
610 for (i = 0; i < nb_imports; i++)
612 struct import *imp = dll_imports[i];
614 for (j = removed = 0; j < undef_symbols.count; j++)
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)
620 add_import_func( imp, odp );
621 remove_name( &undef_symbols, j-- );
622 removed++;
625 if (!removed && check_unused( imp, spec ))
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--;
634 sort_names( &undef_symbols );
635 check_undefined_exports( spec );
637 return 1;
640 /* output the get_pc thunk if needed */
641 void output_get_pc_thunk( FILE *outfile )
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" );
655 /* output a single import thunk */
656 static void output_import_thunk( FILE *outfile, const char *name, const char *table, int pos )
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) );
662 switch(target_cpu)
664 case CPU_x86:
665 if (!UsePIC)
667 fprintf( outfile, "\tjmp *(%s+%d)\n", table, pos );
669 else
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 );
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 )
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" );
686 else
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" );
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)
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) );
717 else
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) );
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;
733 output_function_size( outfile, name );
736 /* check if we need an import directory */
737 int has_imports(void)
739 return (nb_imports - nb_delayed) > 0;
742 /* output the import table of a Win32 module */
743 static void output_immediate_imports( FILE *outfile )
745 int i, j;
746 const char *dll_name;
748 if (nb_imports == nb_delayed) return; /* no immediate imports */
750 /* main import header */
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" );
757 /* list of dlls */
759 for (i = j = 0; i < nb_imports; i++)
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;
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 */
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++)
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++)
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
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 );
798 fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
800 fprintf( outfile, ".L__wine_spec_imports_end:\n" );
802 for (i = 0; i < nb_imports; i++)
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++)
808 ORDDEF *odp = dll_imports[i]->imports[j];
809 if (!(odp->flags & FLAG_NONAME))
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 );
819 for (i = 0; i < nb_imports; i++)
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 );
828 /* output the import thunks of a Win32 module */
829 static void output_immediate_import_thunks( FILE *outfile )
831 int i, j, pos;
832 int nb_imm = nb_imports - nb_delayed;
833 static const char import_thunks[] = "__wine_spec_import_thunks";
835 if (!nb_imm) return;
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));
842 for (i = pos = 0; i < nb_imports; i++)
844 if (dll_imports[i]->delay) continue;
845 for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += get_ptr_size())
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 );
851 pos += get_ptr_size();
853 output_function_size( outfile, import_thunks );
856 /* output the delayed import table of a Win32 module */
857 static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
859 int i, j;
861 if (!nb_delayed) return;
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") );
868 /* list of dlls */
870 for (i = j = 0; i < nb_imports; i++)
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;
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 */
896 fprintf( outfile, "\n.L__wine_delay_IAT:\n" );
897 for (i = 0; i < nb_imports; i++)
899 if (!dll_imports[i]->delay) continue;
900 for (j = 0; j < dll_imports[i]->nb_imports; j++)
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 );
909 fprintf( outfile, "\n.L__wine_delay_INT:\n" );
910 for (i = 0; i < nb_imports; i++)
912 if (!dll_imports[i]->delay) continue;
913 for (j = 0; j < dll_imports[i]->nb_imports; j++)
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 );
924 fprintf( outfile, "\n.L__wine_delay_modules:\n" );
925 for (i = 0; i < nb_imports; i++)
927 if (dll_imports[i]->delay) fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
930 for (i = 0; i < nb_imports; i++)
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 );
938 for (i = 0; i < nb_imports; i++)
940 if (!dll_imports[i]->delay) continue;
941 for (j = 0; j < dll_imports[i]->nb_imports; j++)
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 );
949 output_function_size( outfile, "__wine_spec_delay_imports" );
952 /* output the delayed import thunks of a Win32 module */
953 static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
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";
959 if (!nb_delayed) return;
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)
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;
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));
1014 /* r0 -> r3 (arg1) */
1015 fprintf( outfile, "\tmr %s, %s\n", ppc_reg(3), ppc_reg(0));
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));
1021 /* Call the __wine_delay_load function, arg1 is arg1. */
1022 fprintf( outfile, "\tbl %s\n", asm_name("__wine_spec_delay_load") );
1024 /* Load return value from call into ctr register */
1025 fprintf( outfile, "\tmtctr %s\n", ppc_reg(3));
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));
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);
1044 /* branch to ctr register. */
1045 fprintf( outfile, "\tbctr\n");
1046 break;
1048 output_function_size( outfile, "__wine_delay_load_asm" );
1049 fprintf( outfile, "\n" );
1051 for (i = idx = 0; i < nb_imports; i++)
1053 if (!dll_imports[i]->delay) continue;
1054 for (j = 0; j < dll_imports[i]->nb_imports; j++)
1056 ORDDEF *odp = dll_imports[i]->imports[j];
1057 const char *name = odp->name ? odp->name : odp->export_name;
1059 fprintf( outfile, ".L__wine_delay_imp_%d_%s:\n", i, name );
1060 switch(target_cpu)
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)
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;
1105 break;
1108 idx++;
1110 output_function_size( outfile, delayed_import_loaders );
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++)
1116 if (!dll_imports[i]->delay) continue;
1117 for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += get_ptr_size())
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 );
1124 output_function_size( outfile, delayed_import_thunks );
1127 /* output import stubs for exported entry points that link to external symbols */
1128 static void output_external_link_imports( FILE *outfile, DLLSPEC *spec )
1130 unsigned int i, pos;
1132 if (!ext_link_imports.count) return; /* nothing to do */
1134 sort_names( &ext_link_imports );
1136 /* get rid of duplicate names */
1137 for (i = 1; i < ext_link_imports.count; i++)
1139 if (!strcmp( ext_link_imports.names[i-1], ext_link_imports.names[i] ))
1140 remove_name( &ext_link_imports, i-- );
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]) );
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") );
1154 for (i = pos = 0; i < ext_link_imports.count; i++)
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();
1161 output_function_size( outfile, "__wine_spec_external_link_thunks" );
1164 /*******************************************************************
1165 * output_stubs
1167 * Output the functions for stub entry points
1169 void output_stubs( FILE *outfile, DLLSPEC *spec )
1171 const char *name, *exp_name;
1172 int i, pos;
1174 if (!has_stubs( spec )) return;
1176 fprintf( outfile, "\n/* stub functions */\n\n" );
1177 fprintf( outfile, "\t.text\n" );
1179 for (i = pos = 0; i < spec->nb_entry_points; i++)
1181 ORDDEF *odp = &spec->entry_points[i];
1182 if (odp->type != TYPE_STUB) continue;
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) );
1190 if (UsePIC)
1192 fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
1193 fprintf( outfile, "1:" );
1194 if (exp_name)
1196 fprintf( outfile, "\tleal .L__wine_stub_strings+%d-1b(%%eax),%%ecx\n", pos );
1197 fprintf( outfile, "\tpushl %%ecx\n" );
1198 pos += strlen(exp_name) + 1;
1200 else
1201 fprintf( outfile, "\tpushl $%d\n", odp->ordinal );
1202 fprintf( outfile, "\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
1203 fprintf( outfile, "\tpushl %%ecx\n" );
1205 else
1207 if (exp_name)
1209 fprintf( outfile, "\tpushl $.L__wine_stub_strings+%d\n", pos );
1210 pos += strlen(exp_name) + 1;
1212 else
1213 fprintf( outfile, "\tpushl $%d\n", odp->ordinal );
1214 fprintf( outfile, "\tpushl $.L__wine_spec_file_name\n" );
1216 fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
1217 output_function_size( outfile, name );
1220 if (pos)
1222 fprintf( outfile, "\t%s\n", get_asm_string_section() );
1223 fprintf( outfile, ".L__wine_stub_strings:\n" );
1224 for (i = 0; i < spec->nb_entry_points; i++)
1226 ORDDEF *odp = &spec->entry_points[i];
1227 if (odp->type != TYPE_STUB) continue;
1228 exp_name = odp->name ? odp->name : odp->export_name;
1229 if (exp_name)
1230 fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), exp_name );
1235 /* output the import and delayed import tables of a Win32 module */
1236 void output_imports( FILE *outfile, DLLSPEC *spec )
1238 output_immediate_imports( outfile );
1239 output_delayed_imports( outfile, spec );
1240 output_immediate_import_thunks( outfile );
1241 output_delayed_import_thunks( outfile, spec );
1242 output_external_link_imports( outfile, spec );
1243 if (nb_imports || ext_link_imports.count || has_stubs(spec)) output_get_pc_thunk( outfile );