Store the winsock per-thread data in NtCurrentTeb()->WinSockData
[wine/testsucceed.git] / tools / winebuild / import.c
blobb04eb81ccdb1dfab5764f8597b2bf0c43e257e59
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 <ctype.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #ifdef HAVE_SYS_STAT_H
31 # include <sys/stat.h>
32 #endif
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif
37 #include "windef.h"
38 #include "winbase.h"
39 #include "wine/exception.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 static char **undef_symbols; /* list of undefined symbols */
56 static int nb_undef_symbols = -1;
57 static int undef_size;
59 static char **ignore_symbols; /* list of symbols to ignore */
60 static int nb_ignore_symbols;
61 static int ignore_size;
63 static char *ld_tmp_file; /* ld temp file name */
65 static struct import **dll_imports = NULL;
66 static int nb_imports = 0; /* number of imported dlls (delayed or not) */
67 static int nb_delayed = 0; /* number of delayed dlls */
68 static int total_imports = 0; /* total number of imported functions */
69 static int total_delayed = 0; /* total number of imported functions in delayed DLLs */
70 static char **delayed_imports; /* names of delayed import dlls */
71 static int nb_delayed_imports; /* size of the delayed_imports array */
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"
124 #ifdef __powerpc__
125 # ifdef __APPLE__
126 # define ppc_high(mem) "ha16(" mem ")"
127 # define ppc_low(mem) "lo16(" mem ")"
128 static const char * const ppc_reg[32] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
129 "r8", "r9", "r10","r11","r12","r13","r14","r15",
130 "r16","r17","r18","r19","r20","r21","r22","r23",
131 "r24","r25","r26","r27","r28","r29","r30","r31" };
132 # else /* __APPLE__ */
133 # define ppc_high(mem) "(" mem ")@hi"
134 # define ppc_low(mem) "(" mem ")@l"
135 static const char * const ppc_reg[32] = { "0", "1", "2", "3", "4", "5", "6", "7",
136 "8", "9", "10","11","12","13","14","15",
137 "16","17","18","19","20","21","22","23",
138 "24","25","26","27","28","29","30","31" };
139 # endif /* __APPLE__ */
140 #endif /* __powerpc__ */
142 /* compare function names; helper for resolve_imports */
143 static int name_cmp( const void *name, const void *entry )
145 return strcmp( *(const char* const *)name, *(const char* const *)entry );
148 /* compare function names; helper for resolve_imports */
149 static int func_cmp( const void *func1, const void *func2 )
151 const ORDDEF *odp1 = *(const ORDDEF * const *)func1;
152 const ORDDEF *odp2 = *(const ORDDEF * const *)func2;
153 return strcmp( odp1->name ? odp1->name : odp1->export_name,
154 odp2->name ? odp2->name : odp2->export_name );
157 /* locate a symbol in a (sorted) list */
158 inline static const char *find_symbol( const char *name, char **table, int size )
160 char **res = NULL;
162 if (table) {
163 res = bsearch( &name, table, size, sizeof(*table), name_cmp );
166 return res ? *res : NULL;
169 /* locate an export in a (sorted) export list */
170 inline static ORDDEF *find_export( const char *name, ORDDEF **table, int size )
172 ORDDEF func, *odp, **res = NULL;
174 func.name = (char *)name;
175 func.ordinal = -1;
176 odp = &func;
177 if (table) res = bsearch( &odp, table, size, sizeof(*table), func_cmp );
178 return res ? *res : NULL;
181 /* sort a symbol table */
182 inline static void sort_symbols( char **table, int size )
184 if (table )
185 qsort( table, size, sizeof(*table), name_cmp );
188 inline static void output_function_size( FILE *outfile, const char *name )
190 #ifdef HAVE_ASM_DOT_SIZE
191 fprintf( outfile, " \"\\t.size " __ASM_NAME("%s") ", . - " __ASM_NAME("%s") "\\n\"\n", name, name);
192 #endif
195 /* free an import structure */
196 static void free_imports( struct import *imp )
198 free( imp->exports );
199 free( imp->imports );
200 free_dll_spec( imp->spec );
201 free( imp->full_name );
202 free( imp );
205 /* remove the temp file at exit */
206 static void remove_ld_tmp_file(void)
208 if (ld_tmp_file) unlink( ld_tmp_file );
211 /* check whether a given dll is imported in delayed mode */
212 static int is_delayed_import( const char *name )
214 int i;
216 for (i = 0; i < nb_delayed_imports; i++)
218 if (!strcmp( delayed_imports[i], name )) return 1;
220 return 0;
223 /* check whether a given dll has already been imported */
224 static struct import *is_already_imported( const char *name )
226 int i;
228 for (i = 0; i < nb_imports; i++)
230 if (!strcmp( dll_imports[i]->spec->file_name, name )) return dll_imports[i];
232 return NULL;
235 /* open the .so library for a given dll in a specified path */
236 static char *try_library_path( const char *path, const char *name )
238 char *buffer;
239 int fd;
241 buffer = xmalloc( strlen(path) + strlen(name) + 9 );
242 sprintf( buffer, "%s/lib%s.def", path, name );
244 /* check if the file exists */
245 if ((fd = open( buffer, O_RDONLY )) != -1)
247 close( fd );
248 return buffer;
250 free( buffer );
251 return NULL;
254 /* find the .def import library for a given dll */
255 static char *find_library( const char *name )
257 char *fullname;
258 int i;
260 for (i = 0; i < nb_lib_paths; i++)
262 if ((fullname = try_library_path( lib_path[i], name ))) return fullname;
264 fatal_error( "could not open .def file for %s\n", name );
265 return NULL;
268 /* read in the list of exported symbols of an import library */
269 static int read_import_lib( struct import *imp )
271 FILE *f;
272 int i, ret;
273 struct stat stat;
274 struct import *prev_imp;
275 DLLSPEC *spec = imp->spec;
277 f = open_input_file( NULL, imp->full_name );
278 fstat( fileno(f), &stat );
279 imp->dev = stat.st_dev;
280 imp->ino = stat.st_ino;
281 ret = parse_def_file( f, spec );
282 close_input_file( f );
283 if (!ret) return 0;
285 /* check if we already imported that library from a different file */
286 if ((prev_imp = is_already_imported( spec->file_name )))
288 if (prev_imp->dev != imp->dev || prev_imp->ino != imp->ino)
289 fatal_error( "%s and %s have the same export name '%s'\n",
290 prev_imp->full_name, imp->full_name, spec->file_name );
291 return 0; /* the same file was already loaded, ignore this one */
294 if (is_delayed_import( spec->file_name ))
296 imp->delay = 1;
297 nb_delayed++;
300 imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) );
302 for (i = 0; i < spec->nb_entry_points; i++)
304 ORDDEF *odp = &spec->entry_points[i];
306 if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
307 if (odp->flags & FLAG_PRIVATE) continue;
308 imp->exports[imp->nb_exports++] = odp;
310 imp->exports = xrealloc( imp->exports, imp->nb_exports * sizeof(*imp->exports) );
311 if (imp->nb_exports)
312 qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp );
313 return 1;
316 /* build the dll exported name from the import lib name or path */
317 static char *get_dll_name( const char *name, const char *filename )
319 char *ret;
321 if (filename)
323 const char *basename = strrchr( filename, '/' );
324 if (!basename) basename = filename;
325 else basename++;
326 if (!strncmp( basename, "lib", 3 )) basename += 3;
327 ret = xmalloc( strlen(basename) + 5 );
328 strcpy( ret, basename );
329 if (strendswith( ret, ".def" )) ret[strlen(ret)-4] = 0;
331 else
333 ret = xmalloc( strlen(name) + 5 );
334 strcpy( ret, name );
336 if (!strchr( ret, '.' )) strcat( ret, ".dll" );
337 return ret;
340 /* add a dll to the list of imports */
341 void add_import_dll( const char *name, const char *filename )
343 struct import *imp = xmalloc( sizeof(*imp) );
345 imp->spec = alloc_dll_spec();
346 imp->spec->file_name = get_dll_name( name, filename );
347 imp->delay = 0;
348 imp->imports = NULL;
349 imp->nb_imports = 0;
350 imp->exports = NULL;
351 imp->nb_exports = 0;
353 if (filename) imp->full_name = xstrdup( filename );
354 else imp->full_name = find_library( name );
356 if (read_import_lib( imp ))
358 dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) );
359 dll_imports[nb_imports++] = imp;
361 else
363 free_imports( imp );
364 if (nb_errors) exit(1);
368 /* add a library to the list of delayed imports */
369 void add_delayed_import( const char *name )
371 struct import *imp;
372 char *fullname = get_dll_name( name, NULL );
374 delayed_imports = xrealloc( delayed_imports, (nb_delayed_imports+1) * sizeof(*delayed_imports) );
375 delayed_imports[nb_delayed_imports++] = fullname;
376 if ((imp = is_already_imported( fullname )) && !imp->delay)
378 imp->delay = 1;
379 nb_delayed++;
383 /* remove an imported dll, based on its index in the dll_imports array */
384 static void remove_import_dll( int index )
386 struct import *imp = dll_imports[index];
388 memmove( &dll_imports[index], &dll_imports[index+1], sizeof(imp) * (nb_imports - index - 1) );
389 nb_imports--;
390 if (imp->delay) nb_delayed--;
391 free_imports( imp );
394 /* initialize the list of ignored symbols */
395 static void init_ignored_symbols(void)
397 int i;
399 nb_ignore_symbols = sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]);
400 ignore_size = nb_ignore_symbols + 32;
401 ignore_symbols = xmalloc( ignore_size * sizeof(*ignore_symbols) );
402 for (i = 0; i < nb_ignore_symbols; i++)
403 ignore_symbols[i] = xstrdup( default_ignored_symbols[i] );
406 /* add a symbol to the ignored symbol list */
407 /* if the name starts with '-' the symbol is removed instead */
408 void add_ignore_symbol( const char *name )
410 int i;
412 if (!ignore_symbols) init_ignored_symbols(); /* first time around, fill list with defaults */
414 if (name[0] == '-') /* remove it */
416 if (!name[1]) /* remove everything */
418 for (i = 0; i < nb_ignore_symbols; i++) free( ignore_symbols[i] );
419 nb_ignore_symbols = 0;
421 else
423 for (i = 0; i < nb_ignore_symbols; i++)
425 if (!strcmp( ignore_symbols[i], name+1 ))
427 free( ignore_symbols[i] );
428 memmove( &ignore_symbols[i], &ignore_symbols[i+1], nb_ignore_symbols - i - 1 );
429 nb_ignore_symbols--;
434 else
436 if (nb_ignore_symbols == ignore_size)
438 ignore_size += 32;
439 ignore_symbols = xrealloc( ignore_symbols, ignore_size * sizeof(*ignore_symbols) );
441 ignore_symbols[nb_ignore_symbols++] = xstrdup( name );
445 /* add a function to the list of imports from a given dll */
446 static void add_import_func( struct import *imp, ORDDEF *func )
448 imp->imports = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) );
449 imp->imports[imp->nb_imports++] = func;
450 total_imports++;
451 if (imp->delay) total_delayed++;
454 /* add a symbol to the undef list */
455 inline static void add_undef_symbol( const char *name )
457 if (nb_undef_symbols == undef_size)
459 undef_size += 128;
460 undef_symbols = xrealloc( undef_symbols, undef_size * sizeof(*undef_symbols) );
462 undef_symbols[nb_undef_symbols++] = xstrdup( name );
465 /* remove all the holes in the undefined symbol list; return the number of removed symbols */
466 static int remove_symbol_holes(void)
468 int i, off;
469 for (i = off = 0; i < nb_undef_symbols; i++)
471 if (!undef_symbols[i]) off++;
472 else undef_symbols[i - off] = undef_symbols[i];
474 nb_undef_symbols -= off;
475 return off;
478 /* add a symbol to the extra list, but only if needed */
479 static int add_extra_symbol( const char **extras, int *count, const char *name, const DLLSPEC *spec )
481 int i;
483 if (!find_symbol( name, undef_symbols, nb_undef_symbols ))
485 /* check if the symbol is being exported by this dll */
486 for (i = 0; i < spec->nb_entry_points; i++)
488 ORDDEF *odp = &spec->entry_points[i];
489 if (odp->type == TYPE_STDCALL ||
490 odp->type == TYPE_CDECL ||
491 odp->type == TYPE_VARARGS ||
492 odp->type == TYPE_EXTERN)
494 if (odp->name && !strcmp( odp->name, name )) return 0;
497 extras[*count] = name;
498 (*count)++;
500 return 1;
503 /* add the extra undefined symbols that will be contained in the generated spec file itself */
504 static void add_extra_undef_symbols( const DLLSPEC *spec )
506 const char *extras[10];
507 int i, count = 0, nb_stubs = 0;
508 int kernel_imports = 0, ntdll_imports = 0;
510 sort_symbols( undef_symbols, nb_undef_symbols );
512 for (i = 0; i < spec->nb_entry_points; i++)
514 ORDDEF *odp = &spec->entry_points[i];
515 if (odp->type == TYPE_STUB) nb_stubs++;
518 /* add symbols that will be contained in the spec file itself */
519 if (!(spec->characteristics & IMAGE_FILE_DLL))
521 switch (spec->subsystem)
523 case IMAGE_SUBSYSTEM_WINDOWS_GUI:
524 case IMAGE_SUBSYSTEM_WINDOWS_CUI:
525 kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec );
526 kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA", spec );
527 kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA", spec );
528 kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
529 break;
532 if (nb_delayed)
534 kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA", spec );
535 kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress", spec );
536 kernel_imports += add_extra_symbol( extras, &count, "RaiseException", spec );
538 if (nb_stubs)
539 ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException", spec );
541 /* make sure we import the dlls that contain these functions */
542 if (kernel_imports) add_import_dll( "kernel32", NULL );
543 if (ntdll_imports) add_import_dll( "ntdll", NULL );
545 if (count)
547 for (i = 0; i < count; i++) add_undef_symbol( extras[i] );
548 sort_symbols( undef_symbols, nb_undef_symbols );
552 /* check if a given imported dll is not needed, taking forwards into account */
553 static int check_unused( const struct import* imp, const DLLSPEC *spec )
555 int i;
556 const char *file_name = imp->spec->file_name;
557 size_t len = strlen( file_name );
558 const char *p = strchr( file_name, '.' );
559 if (p && !strcasecmp( p, ".dll" )) len = p - file_name;
561 for (i = spec->base; i <= spec->limit; i++)
563 ORDDEF *odp = spec->ordinals[i];
564 if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
565 if (!strncasecmp( odp->link_name, file_name, len ) &&
566 odp->link_name[len] == '.')
567 return 0; /* found a forward, it is used */
569 return 1;
572 /* combine a list of object files with ld into a single object file */
573 /* returns the name of the combined file */
574 static const char *ldcombine_files( char **argv )
576 int i, len = 0;
577 char *cmd;
578 int fd, err;
580 if (output_file_name && output_file_name[0])
582 ld_tmp_file = xmalloc( strlen(output_file_name) + 10 );
583 strcpy( ld_tmp_file, output_file_name );
584 strcat( ld_tmp_file, ".XXXXXX.o" );
586 else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" );
588 if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" );
589 close( fd );
590 atexit( remove_ld_tmp_file );
592 for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
593 cmd = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ld_command) );
594 sprintf( cmd, "%s -r -o %s", ld_command, ld_tmp_file );
595 for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] );
596 err = system( cmd );
597 if (err) fatal_error( "%s -r failed with status %d\n", ld_command, err );
598 free( cmd );
599 return ld_tmp_file;
602 /* read in the list of undefined symbols */
603 void read_undef_symbols( char **argv )
605 static const char name_prefix[] = __ASM_NAME("");
606 static const int prefix_len = sizeof(name_prefix) - 1;
607 FILE *f;
608 char *cmd, buffer[1024];
609 int err;
610 const char *name;
612 if (!argv[0]) return;
614 undef_size = nb_undef_symbols = 0;
616 /* if we have multiple object files, link them together */
617 if (argv[1]) name = ldcombine_files( argv );
618 else name = argv[0];
620 cmd = xmalloc( strlen(nm_command) + strlen(name) + 5 );
621 sprintf( cmd, "%s -u %s", nm_command, name );
622 if (!(f = popen( cmd, "r" )))
623 fatal_error( "Cannot execute '%s'\n", cmd );
625 while (fgets( buffer, sizeof(buffer), f ))
627 char *p = buffer + strlen(buffer) - 1;
628 if (p < buffer) continue;
629 if (*p == '\n') *p-- = 0;
630 p = buffer;
631 while (*p == ' ') p++;
632 if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
633 if (prefix_len && !strncmp( p, name_prefix, prefix_len )) p += prefix_len;
634 add_undef_symbol( p );
636 if ((err = pclose( f ))) warning( "%s failed with status %d\n", cmd, err );
637 free( cmd );
640 static void remove_ignored_symbols(void)
642 int i;
644 if (!ignore_symbols) init_ignored_symbols();
645 sort_symbols( ignore_symbols, nb_ignore_symbols );
646 for (i = 0; i < nb_undef_symbols; i++)
648 if (find_symbol( undef_symbols[i], ignore_symbols, nb_ignore_symbols ))
650 free( undef_symbols[i] );
651 undef_symbols[i] = NULL;
654 remove_symbol_holes();
657 /* resolve the imports for a Win32 module */
658 int resolve_imports( DLLSPEC *spec )
660 int i, j;
662 if (nb_undef_symbols == -1) return 0; /* no symbol file specified */
664 add_extra_undef_symbols( spec );
665 remove_ignored_symbols();
667 for (i = 0; i < nb_imports; i++)
669 struct import *imp = dll_imports[i];
671 for (j = 0; j < nb_undef_symbols; j++)
673 ORDDEF *odp = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
674 if (odp)
676 add_import_func( imp, odp );
677 free( undef_symbols[j] );
678 undef_symbols[j] = NULL;
681 /* remove all the holes in the undef symbols list */
682 if (!remove_symbol_holes() && check_unused( imp, spec ))
684 /* the dll is not used, get rid of it */
685 warning( "%s imported but no symbols used\n", imp->spec->file_name );
686 remove_import_dll( i );
687 i--;
690 return 1;
693 /* output the import table of a Win32 module */
694 static int output_immediate_imports( FILE *outfile )
696 int i, j, pos;
697 int nb_imm = nb_imports - nb_delayed;
698 static const char import_thunks[] = "__wine_spec_import_thunks";
700 if (!nb_imm) goto done;
702 /* main import header */
704 fprintf( outfile, "\nstatic struct {\n" );
705 fprintf( outfile, " struct {\n" );
706 fprintf( outfile, " void *OriginalFirstThunk;\n" );
707 fprintf( outfile, " unsigned int TimeDateStamp;\n" );
708 fprintf( outfile, " unsigned int ForwarderChain;\n" );
709 fprintf( outfile, " const char *Name;\n" );
710 fprintf( outfile, " void *FirstThunk;\n" );
711 fprintf( outfile, " } imp[%d];\n", nb_imm+1 );
712 fprintf( outfile, " const char *data[%d];\n",
713 total_imports - total_delayed + nb_imm );
714 fprintf( outfile, "} imports = {\n {\n" );
716 /* list of dlls */
718 for (i = j = 0; i < nb_imports; i++)
720 if (dll_imports[i]->delay) continue;
721 fprintf( outfile, " { 0, 0, 0, \"%s\", &imports.data[%d] },\n",
722 dll_imports[i]->spec->file_name, j );
723 j += dll_imports[i]->nb_imports + 1;
726 fprintf( outfile, " { 0, 0, 0, 0, 0 },\n" );
727 fprintf( outfile, " },\n {\n" );
729 /* list of imported functions */
731 for (i = 0; i < nb_imports; i++)
733 if (dll_imports[i]->delay) continue;
734 fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name );
735 for (j = 0; j < dll_imports[i]->nb_imports; j++)
737 ORDDEF *odp = dll_imports[i]->imports[j];
738 if (!(odp->flags & FLAG_NONAME))
740 unsigned short ord = odp->ordinal;
741 fprintf( outfile, " \"\\%03o\\%03o%s\",\n",
742 *(unsigned char *)&ord, *((unsigned char *)&ord + 1), odp->name );
744 else
745 fprintf( outfile, " (char *)%d,\n", odp->ordinal );
747 fprintf( outfile, " 0,\n" );
749 fprintf( outfile, " }\n};\n\n" );
751 /* thunks for imported functions */
753 fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
754 pos = (sizeof(void *) + 2*sizeof(unsigned int) + sizeof(const char *) + sizeof(void *)) *
755 (nb_imm + 1); /* offset of imports.data from start of imports */
756 fprintf( outfile, "asm(\".text\\n\\t.align %d\\n\"\n", get_alignment(8) );
757 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", import_thunks);
759 for (i = 0; i < nb_imports; i++)
761 if (dll_imports[i]->delay) continue;
762 for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += sizeof(const char *))
764 ORDDEF *odp = dll_imports[i]->imports[j];
765 const char *name = odp->name ? odp->name : odp->export_name;
766 fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
767 fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
768 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", name);
770 #if defined(__i386__)
771 if (strstr( name, "__wine_call_from_16" ))
772 fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos );
773 else
774 fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos );
775 #elif defined(__sparc__)
776 if ( !UsePIC )
778 fprintf( outfile, "sethi %%hi(imports+%d), %%g1\\n\\t", pos );
779 fprintf( outfile, "ld [%%g1+%%lo(imports+%d)], %%g1\\n\\t", pos );
780 fprintf( outfile, "jmp %%g1\\n\\tnop\\n" );
782 else
784 /* Hmpf. Stupid sparc assembler always interprets global variable
785 names as GOT offsets, so we have to do it the long way ... */
786 fprintf( outfile, "save %%sp, -96, %%sp\\n" );
787 fprintf( outfile, "0:\\tcall 1f\\n\\tnop\\n" );
788 fprintf( outfile, "1:\\tsethi %%hi(imports+%d-0b), %%g1\\n\\t", pos );
789 fprintf( outfile, "or %%g1, %%lo(imports+%d-0b), %%g1\\n\\t", pos );
790 fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
791 fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
794 #elif defined(__powerpc__)
795 fprintf(outfile, "\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
796 fprintf(outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
797 fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
798 fprintf(outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
799 fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
800 fprintf(outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
802 fprintf(outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
803 fprintf(outfile, "\t\"\\tla %s, " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
804 fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
805 fprintf(outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
807 fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
808 fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
809 fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
810 fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
811 fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
812 fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
813 fprintf(outfile, "\t\"\\tbctr\\n");
814 #elif defined(__ALPHA__)
815 fprintf( outfile, "\tlda $0,imports\\n\"\n" );
816 fprintf( outfile, "\t\"\\tlda $0,%d($0)\\n\"\n", pos);
817 fprintf( outfile, "\t\"\\tjmp $31,($0)\\n" );
818 #else
819 #error You need to define import thunks for your architecture!
820 #endif
821 fprintf( outfile, "\"\n" );
822 output_function_size( outfile, name );
824 pos += 4;
826 output_function_size( outfile, import_thunks );
827 fprintf( outfile, " \".text\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
829 done:
830 return nb_imm;
833 /* output the delayed import table of a Win32 module */
834 static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
836 int i, idx, j, pos;
837 static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders";
838 static const char delayed_import_thunks[] = "__wine_spec_delayed_import_thunks";
840 if (!nb_delayed) goto done;
842 for (i = 0; i < nb_imports; i++)
844 if (!dll_imports[i]->delay) continue;
845 fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i);
846 for (j = 0; j < dll_imports[i]->nb_imports; j++)
848 ORDDEF *odp = dll_imports[i]->imports[j];
849 const char *name = odp->name ? odp->name : odp->export_name;
850 fprintf( outfile, "void __wine_delay_imp_%d_%s();\n", i, name );
853 fprintf( outfile, "\n" );
854 fprintf( outfile, "static struct {\n" );
855 fprintf( outfile, " struct ImgDelayDescr {\n" );
856 fprintf( outfile, " unsigned int grAttrs;\n" );
857 fprintf( outfile, " const char *szName;\n" );
858 fprintf( outfile, " void **phmod;\n" );
859 fprintf( outfile, " void **pIAT;\n" );
860 fprintf( outfile, " const char **pINT;\n" );
861 fprintf( outfile, " void* pBoundIAT;\n" );
862 fprintf( outfile, " void* pUnloadIAT;\n" );
863 fprintf( outfile, " unsigned long dwTimeStamp;\n" );
864 fprintf( outfile, " } imp[%d];\n", nb_delayed );
865 fprintf( outfile, " void *IAT[%d];\n", total_delayed );
866 fprintf( outfile, " const char *INT[%d];\n", total_delayed );
867 fprintf( outfile, "} delay_imports = {\n" );
868 fprintf( outfile, " {\n" );
869 for (i = j = 0; i < nb_imports; i++)
871 if (!dll_imports[i]->delay) continue;
872 fprintf( outfile, " { 0, \"%s\", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n",
873 dll_imports[i]->spec->file_name, i, j, j );
874 j += dll_imports[i]->nb_imports;
876 fprintf( outfile, " },\n {\n" );
877 for (i = 0; i < nb_imports; i++)
879 if (!dll_imports[i]->delay) continue;
880 fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name );
881 for (j = 0; j < dll_imports[i]->nb_imports; j++)
883 ORDDEF *odp = dll_imports[i]->imports[j];
884 const char *name = odp->name ? odp->name : odp->export_name;
885 fprintf( outfile, " &__wine_delay_imp_%d_%s,\n", i, name );
888 fprintf( outfile, " },\n {\n" );
889 for (i = 0; i < nb_imports; i++)
891 if (!dll_imports[i]->delay) continue;
892 fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name );
893 for (j = 0; j < dll_imports[i]->nb_imports; j++)
895 ORDDEF *odp = dll_imports[i]->imports[j];
896 if (!odp->name)
897 fprintf( outfile, " (char *)%d,\n", odp->ordinal );
898 else
899 fprintf( outfile, " \"%s\",\n", odp->name );
902 fprintf( outfile, " }\n};\n\n" );
904 fprintf( outfile, "extern void __stdcall RaiseException(unsigned int, unsigned int, unsigned int, const void *args[]);\n" );
905 fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n");
906 fprintf( outfile, "extern void * __stdcall GetProcAddress(void *, const char*);\n");
907 fprintf( outfile, "\n" );
909 fprintf( outfile, "void *__stdcall __wine_delay_load( int idx_nr )\n" );
910 fprintf( outfile, "{\n" );
911 fprintf( outfile, " int idx = idx_nr >> 16, nr = idx_nr & 0xffff;\n" );
912 fprintf( outfile, " struct ImgDelayDescr *imd = delay_imports.imp + idx;\n" );
913 fprintf( outfile, " void **pIAT = imd->pIAT + nr;\n" );
914 fprintf( outfile, " const char** pINT = imd->pINT + nr;\n" );
915 fprintf( outfile, " void *fn;\n\n" );
917 fprintf( outfile, " if (!*imd->phmod) *imd->phmod = LoadLibraryA(imd->szName);\n" );
918 fprintf( outfile, " if (*imd->phmod && (fn = GetProcAddress(*imd->phmod, *pINT)))\n");
919 fprintf( outfile, " /* patch IAT with final value */\n" );
920 fprintf( outfile, " return *pIAT = fn;\n" );
921 fprintf( outfile, " else {\n");
922 fprintf( outfile, " const void *args[2];\n" );
923 fprintf( outfile, " args[0] = imd->szName;\n" );
924 fprintf( outfile, " args[1] = *pINT;\n" );
925 fprintf( outfile, " RaiseException( 0x%08x, %d, 2, args );\n",
926 EXCEPTION_WINE_STUB, EH_NONCONTINUABLE );
927 fprintf( outfile, " return 0;\n" );
928 fprintf( outfile, " }\n}\n\n" );
930 fprintf( outfile, "#ifndef __GNUC__\n" );
931 fprintf( outfile, "static void __asm__dummy_delay_import(void) {\n" );
932 fprintf( outfile, "#endif\n" );
934 fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) );
935 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_loaders);
936 fprintf( outfile, " \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
937 fprintf( outfile, " \"" __ASM_NAME("__wine_delay_load_asm") ":\\n\"\n" );
938 #if defined(__i386__)
939 fprintf( outfile, " \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
940 fprintf( outfile, " \"\\tcall __wine_delay_load\\n\"\n" );
941 fprintf( outfile, " \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
942 #elif defined(__sparc__)
943 fprintf( outfile, " \"\\tsave %%sp, -96, %%sp\\n\"\n" );
944 fprintf( outfile, " \"\\tcall __wine_delay_load\\n\"\n" );
945 fprintf( outfile, " \"\\tmov %%g1, %%o0\\n\"\n" );
946 fprintf( outfile, " \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
947 #elif defined(__powerpc__)
948 # if defined(__APPLE__)
949 /* On darwin an extra 56 bytes must be allowed for the linkage area+param area */
950 # define extra_stack_storage 56
951 # else
952 # define extra_stack_storage 0
953 # endif
954 /* Save all callee saved registers into a stackframe. */
955 fprintf( outfile, " \"\\tstwu %s, -%d(%s)\\n\"\n",ppc_reg[1], 48+extra_stack_storage, ppc_reg[1]);
956 fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[3], 4+extra_stack_storage, ppc_reg[1]);
957 fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[4], 8+extra_stack_storage, ppc_reg[1]);
958 fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]);
959 fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]);
960 fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]);
961 fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]);
962 fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]);
963 fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]);
964 fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]);
965 fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]);
967 /* r0 -> r3 (arg1) */
968 fprintf( outfile, " \"\\tmr %s, %s\\n\"\n", ppc_reg[3], ppc_reg[0]);
970 /* save return address */
971 fprintf( outfile, " \"\\tmflr %s\\n\"\n", ppc_reg[0]);
972 fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[0], 44+extra_stack_storage, ppc_reg[1]);
974 /* Call the __wine_delay_load function, arg1 is arg1. */
975 fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_delay_load") "\\n\"\n");
977 /* Load return value from call into ctr register */
978 fprintf( outfile, " \"\\tmtctr %s\\n\"\n", ppc_reg[3]);
980 /* restore all saved registers and drop stackframe. */
981 fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[3], 4+extra_stack_storage, ppc_reg[1]);
982 fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[4], 8+extra_stack_storage, ppc_reg[1]);
983 fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]);
984 fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]);
985 fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]);
986 fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]);
987 fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]);
988 fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]);
989 fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]);
990 fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]);
992 /* Load return value from call into return register */
993 fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[0], 44+extra_stack_storage, ppc_reg[1]);
994 fprintf( outfile, " \"\\tmtlr %s\\n\"\n", ppc_reg[0]);
995 fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[1], ppc_reg[1], 48+extra_stack_storage);
997 /* branch to ctr register. */
998 fprintf( outfile, " \"bctr\\n\"\n");
999 #elif defined(__ALPHA__)
1000 fprintf( outfile, " \"\\tjsr $26,__wine_delay_load\\n\"\n" );
1001 fprintf( outfile, " \"\\tjmp $31,($0)\\n\"\n" );
1002 #else
1003 #error You need to defined delayed import thunks for your architecture!
1004 #endif
1005 output_function_size( outfile, "__wine_delay_load_asm" );
1007 for (i = idx = 0; i < nb_imports; i++)
1009 if (!dll_imports[i]->delay) continue;
1010 for (j = 0; j < dll_imports[i]->nb_imports; j++)
1012 char buffer[128];
1013 ORDDEF *odp = dll_imports[i]->imports[j];
1014 const char *name = odp->name ? odp->name : odp->export_name;
1016 sprintf( buffer, "__wine_delay_imp_%d_%s", i, name );
1017 fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer );
1018 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", buffer );
1019 #if defined(__i386__)
1020 fprintf( outfile, " \"\\tmovl $%d, %%eax\\n\"\n", (idx << 16) | j );
1021 fprintf( outfile, " \"\\tjmp __wine_delay_load_asm\\n\"\n" );
1022 #elif defined(__sparc__)
1023 fprintf( outfile, " \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
1024 fprintf( outfile, " \"\\tb,a __wine_delay_load_asm\\n\"\n" );
1025 #elif defined(__powerpc__)
1026 #ifdef __APPLE__
1027 /* On Darwin we can use r0 and r2 */
1028 /* Upper part in r2 */
1029 fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg[2], idx);
1030 /* Lower part + r2 -> r0, Note we can't use r0 directly */
1031 fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[2], j);
1032 fprintf( outfile, " \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
1033 #else /* __APPLE__ */
1034 /* On linux we can't use r2 since r2 is not a scratch register (hold the TOC) */
1035 /* Save r13 on the stack */
1036 fprintf( outfile, " \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1037 fprintf( outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[13], ppc_reg[1]);
1038 /* Upper part in r13 */
1039 fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg[13], idx);
1040 /* Lower part + r13 -> r0, Note we can't use r0 directly */
1041 fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[13], j);
1042 /* Restore r13 */
1043 fprintf( outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[13], ppc_reg[1]);
1044 fprintf( outfile, " \"\\taddic %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1045 fprintf( outfile, " \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
1046 #endif /* __APPLE__ */
1047 #elif defined(__ALPHA__)
1048 fprintf( outfile, " \"\\tlda $0,%d($31)\\n\"\n", j);
1049 fprintf( outfile, " \"\\tldah $0,%d($0)\\n\"\n", idx);
1050 fprintf( outfile, " \"\\tjmp $31,__wine_delay_load_asm\\n\"\n" );
1051 #else
1052 #error You need to defined delayed import thunks for your architecture!
1053 #endif
1054 output_function_size( outfile, name );
1056 idx++;
1058 output_function_size( outfile, delayed_import_loaders );
1060 fprintf( outfile, "\n \".align %d\\n\"\n", get_alignment(8) );
1061 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_thunks);
1062 pos = nb_delayed * 32;
1063 for (i = 0; i < nb_imports; i++)
1065 if (!dll_imports[i]->delay) continue;
1066 for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
1068 ORDDEF *odp = dll_imports[i]->imports[j];
1069 const char *name = odp->name ? odp->name : odp->export_name;
1071 fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
1072 fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
1073 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t\"", name );
1074 #if defined(__i386__)
1075 if (strstr( name, "__wine_call_from_16" ))
1076 fprintf( outfile, "\".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n\"", pos );
1077 else
1078 fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos );
1079 #elif defined(__sparc__)
1080 if ( !UsePIC )
1082 fprintf( outfile, "\"sethi %%hi(delay_imports+%d), %%g1\\n\\t\"", pos );
1083 fprintf( outfile, "\"ld [%%g1+%%lo(delay_imports+%d)], %%g1\\n\\t\"", pos );
1084 fprintf( outfile, "\"jmp %%g1\\n\\tnop\\n\"" );
1086 else
1088 /* Hmpf. Stupid sparc assembler always interprets global variable
1089 names as GOT offsets, so we have to do it the long way ... */
1090 fprintf( outfile, "\"save %%sp, -96, %%sp\\n\"" );
1091 fprintf( outfile, "\"0:\\tcall 1f\\n\\tnop\\n\"" );
1092 fprintf( outfile, "\"1:\\tsethi %%hi(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1093 fprintf( outfile, "\"or %%g1, %%lo(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1094 fprintf( outfile, "\"ld [%%g1+%%o7], %%g1\\n\\t\"" );
1095 fprintf( outfile, "\"jmp %%g1\\n\\trestore\\n\"" );
1098 #elif defined(__powerpc__)
1099 fprintf( outfile, "\t\"addi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1100 fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
1101 fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1102 fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
1103 fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1104 fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
1106 fprintf( outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("delay_imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
1107 fprintf( outfile, "\t\"\\tla %s, " ppc_low (__ASM_NAME("delay_imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
1108 fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
1109 fprintf( outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
1111 fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
1112 fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1113 fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
1114 fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1115 fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
1116 fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1117 fprintf( outfile, "\t\"\\tbctr\\n\"");
1118 #elif defined(__ALPHA__)
1119 fprintf( outfile, "\t\"lda $0,delay_imports\\n\"\n" );
1120 fprintf( outfile, "\t\"\\tlda $0,%d($0)\\n\"\n", pos);
1121 fprintf( outfile, "\t\"\\tjmp $31,($0)\\n\"" );
1122 #else
1123 #error You need to define delayed import thunks for your architecture!
1124 #endif
1125 fprintf( outfile, "\n" );
1126 output_function_size( outfile, name );
1129 output_function_size( outfile, delayed_import_thunks );
1130 fprintf( outfile, ");\n" );
1131 fprintf( outfile, "#ifndef __GNUC__\n" );
1132 fprintf( outfile, "}\n" );
1133 fprintf( outfile, "#endif\n" );
1134 fprintf( outfile, "\n" );
1136 done:
1137 return nb_delayed;
1140 /* output the import and delayed import tables of a Win32 module
1141 * returns number of DLLs exported in 'immediate' mode
1143 int output_imports( FILE *outfile, DLLSPEC *spec )
1145 output_delayed_imports( outfile, spec );
1146 return output_immediate_imports( outfile );