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