- Fixed memory leak in AVISaveOptions.
[wine/dcerpc.git] / tools / winebuild / import.c
blob6e22f6b49245e0268afe2555eeeb2d4632ae6bed
1 /*
2 * DLL imports support
4 * Copyright 2000 Alexandre Julliard
5 * 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 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 #endif
33 #include "build.h"
35 struct func
37 char *name; /* function name */
38 int ordinal; /* function ordinal */
39 int ord_only; /* non-zero if function is imported by ordinal */
42 struct import
44 char *dll; /* dll name */
45 int delay; /* delay or not dll loading ? */
46 struct func *exports; /* functions exported from this dll */
47 int nb_exports; /* number of exported functions */
48 struct func *imports; /* functions we want to import from this dll */
49 int nb_imports; /* number of imported functions */
52 static char **undef_symbols; /* list of undefined symbols */
53 static int nb_undef_symbols = -1;
54 static int undef_size;
56 static char **ignore_symbols; /* list of symbols to ignore */
57 static int nb_ignore_symbols;
58 static int ignore_size;
60 static char *ld_tmp_file; /* ld temp file name */
62 static struct import **dll_imports = NULL;
63 static int nb_imports = 0; /* number of imported dlls (delayed or not) */
64 static int nb_delayed = 0; /* number of delayed dlls */
65 static int total_imports = 0; /* total number of imported functions */
66 static int total_delayed = 0; /* total number of imported functions in delayed DLLs */
68 /* list of symbols that are ignored by default */
69 static const char * const default_ignored_symbols[] =
71 "abs",
72 "acos",
73 "asin",
74 "atan",
75 "atan2",
76 "atof",
77 "atoi",
78 "atol",
79 "bsearch",
80 "ceil",
81 "cos",
82 "cosh",
83 "div",
84 "exp",
85 "fabs",
86 "floor",
87 "fmod",
88 "frexp",
89 "labs",
90 "ldiv",
91 "log",
92 "log10",
93 "memchr",
94 "memcmp",
95 "memcpy",
96 "memmove",
97 "memset",
98 "modf",
99 "pow",
100 "qsort",
101 "sin",
102 "sinh",
103 "sqrt",
104 "strcat",
105 "strchr",
106 "strcmp",
107 "strcpy",
108 "strcspn",
109 "strlen",
110 "strncat",
111 "strncmp",
112 "strncpy",
113 "strpbrk",
114 "strrchr",
115 "strspn",
116 "strstr",
117 "tan",
118 "tanh"
121 /* compare function names; helper for resolve_imports */
122 static int name_cmp( const void *name, const void *entry )
124 return strcmp( *(char **)name, *(char **)entry );
127 /* compare function names; helper for resolve_imports */
128 static int func_cmp( const void *func1, const void *func2 )
130 return strcmp( ((struct func *)func1)->name, ((struct func *)func2)->name );
133 /* locate a symbol in a (sorted) list */
134 inline static const char *find_symbol( const char *name, char **table, int size )
136 char **res = NULL;
138 if (table) {
139 res = bsearch( &name, table, size, sizeof(*table), name_cmp );
142 return res ? *res : NULL;
145 /* locate an export in a (sorted) export list */
146 inline static struct func *find_export( const char *name, struct func *table, int size )
148 struct func func, *res = NULL;
150 func.name = (char *)name;
151 func.ordinal = -1;
152 if (table) res = bsearch( &func, table, size, sizeof(*table), func_cmp );
153 return res;
156 /* sort a symbol table */
157 inline static void sort_symbols( char **table, int size )
159 if (table )
160 qsort( table, size, sizeof(*table), name_cmp );
163 /* free an import structure */
164 static void free_imports( struct import *imp )
166 int i;
168 for (i = 0; i < imp->nb_exports; i++) free( imp->exports[i].name );
169 for (i = 0; i < imp->nb_imports; i++) free( imp->imports[i].name );
170 free( imp->exports );
171 free( imp->imports );
172 free( imp->dll );
173 free( imp );
176 /* remove the temp file at exit */
177 static void remove_ld_tmp_file(void)
179 if (ld_tmp_file) unlink( ld_tmp_file );
182 /* check whether a given dll has already been imported */
183 static int is_already_imported( const char *name )
185 int i;
187 for (i = 0; i < nb_imports; i++)
189 if (!strcmp( dll_imports[i]->dll, name )) return 1;
191 return 0;
194 /* open the .so library for a given dll in a specified path */
195 static char *try_library_path( const char *path, const char *name )
197 char *buffer;
198 int fd;
200 buffer = xmalloc( strlen(path) + strlen(name) + 9 );
201 sprintf( buffer, "%s/lib%s.def", path, name );
203 /* check if the file exists */
204 if ((fd = open( buffer, O_RDONLY )) != -1)
206 close( fd );
207 return buffer;
209 free( buffer );
210 return NULL;
213 /* open the .so library for a given dll */
214 static char *open_library( const char *name )
216 char *fullname;
217 int i;
219 for (i = 0; i < nb_lib_paths; i++)
221 if ((fullname = try_library_path( lib_path[i], name ))) return fullname;
223 if (!(fullname = try_library_path( ".", name )))
224 fatal_error( "could not open .def file for %s\n", name );
225 return fullname;
228 /* skip whitespace until the next token */
229 static char *skip_whitespace( char *p )
231 while (*p && isspace(*p)) p++;
232 if (!*p || *p == ';') p = NULL;
233 return p;
236 /* skip to the start of the next token, null terminating the current one */
237 static char *next_token( char *p )
239 while (*p && !isspace(*p)) p++;
240 if (*p) *p++ = 0;
241 return skip_whitespace( p );
244 /* remove the @nn suffix from stdcall names */
245 static char *remove_stdcall_decoration( char *buffer )
247 char *p = buffer + strlen(buffer) - 1;
248 while (p > buffer && isdigit(*p)) p--;
249 if (p > buffer && *p == '@') *p = 0;
250 return buffer;
253 /* read in the list of exported symbols of an import library */
254 static int read_import_lib( const char *name, struct import *imp )
256 FILE *f;
257 char buffer[1024];
258 char *fullname;
259 int size;
261 imp->exports = NULL;
262 imp->nb_exports = size = 0;
264 fullname = open_library( name );
265 f = open_input_file( NULL, fullname );
266 free( fullname );
268 while (fgets( buffer, sizeof(buffer), f ))
270 char *name, *flags;
271 int ordinal = 0, ord_only = 0;
273 char *p = buffer + strlen(buffer) - 1;
274 if (p < buffer) goto next;
275 if (*p == '\n') *p-- = 0;
277 p = buffer;
278 if (!(p = skip_whitespace(p))) goto next;
279 name = p;
280 p = next_token( name );
282 if (!strcmp( name, "LIBRARY" ))
284 if (!p)
286 error( "Expected name after LIBRARY\n" );
287 goto next;
289 name = p;
290 p = next_token( name );
291 if (p)
293 error( "Garbage after LIBRARY statement\n" );
294 goto next;
296 if (is_already_imported( name ))
298 close_input_file( f );
299 return 0; /* ignore this dll */
301 free( imp->dll );
302 imp->dll = xstrdup( name );
303 goto next;
305 if (!strcmp( name, "EXPORTS" )) goto next;
307 /* check for ordinal */
308 if (!p)
310 error( "Expected ordinal after function name\n" );
311 goto next;
313 if (*p != '@' || !isdigit(p[1]))
315 error( "Expected ordinal after function name '%s'\n", name );
316 goto next;
318 ordinal = strtol( p+1, &p, 10 );
319 if (ordinal >= MAX_ORDINALS)
321 error( "Invalid ordinal number %d\n", ordinal );
322 goto next;
325 /* check for optional flags */
326 while (p && (p = skip_whitespace(p)))
328 flags = p;
329 p = next_token( flags );
330 if (!strcmp( flags, "NONAME" ))
332 ord_only = 1;
333 if (!ordinal)
335 error( "Invalid ordinal number %d\n", ordinal );
336 goto next;
339 else if (!strcmp( flags, "CONSTANT" ) || !strcmp( flags, "DATA" ))
341 /* we don't support importing non-function entry points */
342 goto next;
344 else
346 error( "Garbage after ordinal declaration\n" );
347 goto next;
351 if (imp->nb_exports == size)
353 size += 128;
354 imp->exports = xrealloc( imp->exports, size * sizeof(*imp->exports) );
356 if ((p = strchr( name, '=' ))) *p = 0;
357 remove_stdcall_decoration( name );
358 imp->exports[imp->nb_exports].name = xstrdup( name );
359 imp->exports[imp->nb_exports].ordinal = ordinal;
360 imp->exports[imp->nb_exports].ord_only = ord_only;
361 imp->nb_exports++;
362 next:
363 current_line++;
365 close_input_file( f );
366 if (imp->nb_exports)
367 qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp );
368 return !nb_errors;
371 /* add a dll to the list of imports */
372 void add_import_dll( const char *name, int delay )
374 struct import *imp;
375 char *fullname;
377 fullname = xmalloc( strlen(name) + 5 );
378 strcpy( fullname, name );
379 if (!strchr( fullname, '.' )) strcat( fullname, ".dll" );
381 /* check if we already imported it */
382 if (is_already_imported( fullname ))
384 free( fullname );
385 return;
388 imp = xmalloc( sizeof(*imp) );
389 imp->dll = fullname;
390 imp->delay = delay;
391 imp->imports = NULL;
392 imp->nb_imports = 0;
394 if (delay) nb_delayed++;
396 if (read_import_lib( name, imp ))
398 dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) );
399 dll_imports[nb_imports++] = imp;
401 else
403 free_imports( imp );
404 if (nb_errors) exit(1);
408 /* remove an imported dll, based on its index in the dll_imports array */
409 static void remove_import_dll( int index )
411 struct import *imp = dll_imports[index];
413 memmove( &dll_imports[index], &dll_imports[index+1], sizeof(imp) * (nb_imports - index - 1) );
414 nb_imports--;
415 if (imp->delay) nb_delayed--;
416 free_imports( imp );
419 /* initialize the list of ignored symbols */
420 static void init_ignored_symbols(void)
422 int i;
424 nb_ignore_symbols = sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]);
425 ignore_size = nb_ignore_symbols + 32;
426 ignore_symbols = xmalloc( ignore_size * sizeof(*ignore_symbols) );
427 for (i = 0; i < nb_ignore_symbols; i++)
428 ignore_symbols[i] = xstrdup( default_ignored_symbols[i] );
431 /* add a symbol to the ignored symbol list */
432 /* if the name starts with '-' the symbol is removed instead */
433 void add_ignore_symbol( const char *name )
435 int i;
437 if (!ignore_symbols) init_ignored_symbols(); /* first time around, fill list with defaults */
439 if (name[0] == '-') /* remove it */
441 if (!name[1]) /* remove everything */
443 for (i = 0; i < nb_ignore_symbols; i++) free( ignore_symbols[i] );
444 nb_ignore_symbols = 0;
446 else
448 for (i = 0; i < nb_ignore_symbols; i++)
450 if (!strcmp( ignore_symbols[i], name+1 ))
452 free( ignore_symbols[i] );
453 memmove( &ignore_symbols[i], &ignore_symbols[i+1], nb_ignore_symbols - i - 1 );
454 nb_ignore_symbols--;
459 else
461 if (nb_ignore_symbols == ignore_size)
463 ignore_size += 32;
464 ignore_symbols = xrealloc( ignore_symbols, ignore_size * sizeof(*ignore_symbols) );
466 ignore_symbols[nb_ignore_symbols++] = xstrdup( name );
470 /* add a function to the list of imports from a given dll */
471 static void add_import_func( struct import *imp, const struct func *func )
473 imp->imports = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) );
474 imp->imports[imp->nb_imports].name = xstrdup( func->name );
475 imp->imports[imp->nb_imports].ordinal = func->ordinal;
476 imp->imports[imp->nb_imports].ord_only = func->ord_only;
477 imp->nb_imports++;
478 total_imports++;
479 if (imp->delay) total_delayed++;
482 /* add a symbol to the undef list */
483 inline static void add_undef_symbol( const char *name )
485 if (nb_undef_symbols == undef_size)
487 undef_size += 128;
488 undef_symbols = xrealloc( undef_symbols, undef_size * sizeof(*undef_symbols) );
490 undef_symbols[nb_undef_symbols++] = xstrdup( name );
493 /* remove all the holes in the undefined symbol list; return the number of removed symbols */
494 static int remove_symbol_holes(void)
496 int i, off;
497 for (i = off = 0; i < nb_undef_symbols; i++)
499 if (!undef_symbols[i]) off++;
500 else undef_symbols[i - off] = undef_symbols[i];
502 nb_undef_symbols -= off;
503 return off;
506 /* add a symbol to the extra list, but only if needed */
507 static int add_extra_symbol( const char **extras, int *count, const char *name )
509 int i;
511 if (!find_symbol( name, undef_symbols, nb_undef_symbols ))
513 /* check if the symbol is being exported by this dll */
514 for (i = 0; i < nb_entry_points; i++)
516 ORDDEF *odp = EntryPoints[i];
517 if (odp->type == TYPE_STDCALL ||
518 odp->type == TYPE_CDECL ||
519 odp->type == TYPE_VARARGS ||
520 odp->type == TYPE_EXTERN)
522 if (odp->name && !strcmp( odp->name, name )) return 0;
525 extras[*count] = name;
526 (*count)++;
528 return 1;
531 /* add the extra undefined symbols that will be contained in the generated spec file itself */
532 static void add_extra_undef_symbols(void)
534 const char *extras[10];
535 int i, count = 0, nb_stubs = 0, nb_regs = 0;
536 int kernel_imports = 0, ntdll_imports = 0;
538 sort_symbols( undef_symbols, nb_undef_symbols );
540 for (i = 0; i < nb_entry_points; i++)
542 ORDDEF *odp = EntryPoints[i];
543 if (odp->type == TYPE_STUB) nb_stubs++;
544 if (odp->flags & FLAG_REGISTER) nb_regs++;
547 /* add symbols that will be contained in the spec file itself */
548 switch (SpecMode)
550 case SPEC_MODE_DLL:
551 break;
552 case SPEC_MODE_GUIEXE:
553 kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" );
554 kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" );
555 kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" );
556 /* fall through */
557 case SPEC_MODE_CUIEXE:
558 kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
559 break;
560 case SPEC_MODE_GUIEXE_UNICODE:
561 kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" );
562 kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" );
563 kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" );
564 /* fall through */
565 case SPEC_MODE_CUIEXE_UNICODE:
566 kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
567 break;
569 if (nb_delayed)
571 kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA" );
572 kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress" );
574 if (nb_regs)
575 ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs" );
576 if (nb_delayed || nb_stubs)
577 ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException" );
579 /* make sure we import the dlls that contain these functions */
580 if (kernel_imports) add_import_dll( "kernel32", 0 );
581 if (ntdll_imports) add_import_dll( "ntdll", 0 );
583 if (count)
585 for (i = 0; i < count; i++) add_undef_symbol( extras[i] );
586 sort_symbols( undef_symbols, nb_undef_symbols );
590 /* check if a given imported dll is not needed, taking forwards into account */
591 static int check_unused( const struct import* imp )
593 int i;
594 size_t len = strlen(imp->dll);
595 const char *p = strchr( imp->dll, '.' );
596 if (p && !strcasecmp( p, ".dll" )) len = p - imp->dll;
598 for (i = Base; i <= Limit; i++)
600 ORDDEF *odp = Ordinals[i];
601 if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
602 if (!strncasecmp( odp->link_name, imp->dll, len ) &&
603 odp->link_name[len] == '.')
604 return 0; /* found a forward, it is used */
606 return 1;
609 /* combine a list of object files with ld into a single object file */
610 /* returns the name of the combined file */
611 static const char *ldcombine_files( char **argv )
613 int i, len = 0;
614 char *cmd;
615 int fd, err;
617 if (output_file_name && output_file_name[0])
619 ld_tmp_file = xmalloc( strlen(output_file_name) + 10 );
620 strcpy( ld_tmp_file, output_file_name );
621 strcat( ld_tmp_file, ".XXXXXX.o" );
623 else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" );
625 if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" );
626 close( fd );
627 atexit( remove_ld_tmp_file );
629 for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
630 cmd = xmalloc( len + strlen(ld_tmp_file) + 10 );
631 sprintf( cmd, "ld -r -o %s", ld_tmp_file );
632 for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] );
633 err = system( cmd );
634 if (err) fatal_error( "ld -r failed with status %d\n", err );
635 free( cmd );
636 return ld_tmp_file;
639 /* read in the list of undefined symbols */
640 void read_undef_symbols( char **argv )
642 FILE *f;
643 char buffer[1024];
644 int err;
645 const char *name;
647 if (!argv[0]) return;
649 undef_size = nb_undef_symbols = 0;
651 /* if we have multiple object files, link them together */
652 if (argv[1]) name = ldcombine_files( argv );
653 else name = argv[0];
655 sprintf( buffer, "nm -u %s", name );
656 if (!(f = popen( buffer, "r" )))
657 fatal_error( "Cannot execute '%s'\n", buffer );
659 while (fgets( buffer, sizeof(buffer), f ))
661 char *p = buffer + strlen(buffer) - 1;
662 if (p < buffer) continue;
663 if (*p == '\n') *p-- = 0;
664 p = buffer;
665 while (*p == ' ') p++;
666 if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
667 add_undef_symbol( p );
669 if ((err = pclose( f ))) warning( "nm -u %s error %d\n", name, err );
672 static void remove_ignored_symbols(void)
674 int i;
676 if (!ignore_symbols) init_ignored_symbols();
677 sort_symbols( ignore_symbols, nb_ignore_symbols );
678 for (i = 0; i < nb_undef_symbols; i++)
680 if (find_symbol( undef_symbols[i], ignore_symbols, nb_ignore_symbols ))
682 free( undef_symbols[i] );
683 undef_symbols[i] = NULL;
686 remove_symbol_holes();
689 /* resolve the imports for a Win32 module */
690 int resolve_imports( void )
692 int i, j;
694 if (nb_undef_symbols == -1) return 0; /* no symbol file specified */
696 add_extra_undef_symbols();
697 remove_ignored_symbols();
699 for (i = 0; i < nb_imports; i++)
701 struct import *imp = dll_imports[i];
703 for (j = 0; j < nb_undef_symbols; j++)
705 struct func *func = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
706 if (func)
708 add_import_func( imp, func );
709 free( undef_symbols[j] );
710 undef_symbols[j] = NULL;
713 /* remove all the holes in the undef symbols list */
714 if (!remove_symbol_holes() && check_unused( imp ))
716 /* the dll is not used, get rid of it */
717 warning( "%s imported but no symbols used\n", imp->dll );
718 remove_import_dll( i );
719 i--;
722 return 1;
725 /* output the import table of a Win32 module */
726 static int output_immediate_imports( FILE *outfile )
728 int i, j, pos;
729 int nb_imm = nb_imports - nb_delayed;
731 if (!nb_imm) goto done;
733 /* main import header */
735 fprintf( outfile, "\nstatic struct {\n" );
736 fprintf( outfile, " struct {\n" );
737 fprintf( outfile, " void *OriginalFirstThunk;\n" );
738 fprintf( outfile, " unsigned int TimeDateStamp;\n" );
739 fprintf( outfile, " unsigned int ForwarderChain;\n" );
740 fprintf( outfile, " const char *Name;\n" );
741 fprintf( outfile, " void *FirstThunk;\n" );
742 fprintf( outfile, " } imp[%d];\n", nb_imm+1 );
743 fprintf( outfile, " const char *data[%d];\n",
744 total_imports - total_delayed + nb_imm );
745 fprintf( outfile, "} imports = {\n {\n" );
747 /* list of dlls */
749 for (i = j = 0; i < nb_imports; i++)
751 if (dll_imports[i]->delay) continue;
752 fprintf( outfile, " { 0, 0, 0, \"%s\", &imports.data[%d] },\n",
753 dll_imports[i]->dll, j );
754 j += dll_imports[i]->nb_imports + 1;
757 fprintf( outfile, " { 0, 0, 0, 0, 0 },\n" );
758 fprintf( outfile, " },\n {\n" );
760 /* list of imported functions */
762 for (i = 0; i < nb_imports; i++)
764 if (dll_imports[i]->delay) continue;
765 fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
766 for (j = 0; j < dll_imports[i]->nb_imports; j++)
768 struct func *import = &dll_imports[i]->imports[j];
769 if (!import->ord_only)
771 unsigned short ord = import->ordinal;
772 fprintf( outfile, " \"\\%03o\\%03o%s\",\n",
773 *(unsigned char *)&ord, *((unsigned char *)&ord + 1), import->name );
775 else
776 fprintf( outfile, " (char *)%d,\n", import->ordinal );
778 fprintf( outfile, " 0,\n" );
780 fprintf( outfile, " }\n};\n\n" );
782 /* thunks for imported functions */
784 fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
785 pos = 20 * (nb_imm + 1); /* offset of imports.data from start of imports */
786 fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
787 for (i = 0; i < nb_imports; i++)
789 if (dll_imports[i]->delay) continue;
790 for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
792 struct func *import = &dll_imports[i]->imports[j];
793 fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name );
794 fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name );
795 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", import->name);
797 #if defined(__i386__)
798 if (strstr( import->name, "__wine_call_from_16" ))
799 fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos );
800 else
801 fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos );
802 #elif defined(__sparc__)
803 if ( !UsePIC )
805 fprintf( outfile, "sethi %%hi(imports+%d), %%g1\\n\\t", pos );
806 fprintf( outfile, "ld [%%g1+%%lo(imports+%d)], %%g1\\n\\t", pos );
807 fprintf( outfile, "jmp %%g1\\n\\tnop\\n" );
809 else
811 /* Hmpf. Stupid sparc assembler always interprets global variable
812 names as GOT offsets, so we have to do it the long way ... */
813 fprintf( outfile, "save %%sp, -96, %%sp\\n" );
814 fprintf( outfile, "0:\\tcall 1f\\n\\tnop\\n" );
815 fprintf( outfile, "1:\\tsethi %%hi(imports+%d-0b), %%g1\\n\\t", pos );
816 fprintf( outfile, "or %%g1, %%lo(imports+%d-0b), %%g1\\n\\t", pos );
817 fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
818 fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
821 #elif defined(__PPC__)
822 fprintf(outfile, "\taddi 1, 1, -0x4\\n\"\n");
823 fprintf(outfile, "\t\"\\tstw 9, 0(1)\\n\"\n");
824 fprintf(outfile, "\t\"\\taddi 1, 1, -0x4\\n\"\n");
825 fprintf(outfile, "\t\"\\tstw 8, 0(1)\\n\"\n");
826 fprintf(outfile, "\t\"\\taddi 1, 1, -0x4\\n\"\n");
827 fprintf(outfile, "\t\"\\tstw 7, 0(1)\\n\"\n");
829 fprintf(outfile, "\t\"\\tlis 9,imports+%d@ha\\n\"\n", pos);
830 fprintf(outfile, "\t\"\\tla 8,imports+%d@l(9)\\n\"\n", pos);
831 fprintf(outfile, "\t\"\\tlwz 7, 0(8)\\n\"\n");
832 fprintf(outfile, "\t\"\\tmtctr 7\\n\"\n");
834 fprintf(outfile, "\t\"\\tlwz 7, 0(1)\\n\"\n");
835 fprintf(outfile, "\t\"\\taddi 1, 1, 0x4\\n\"\n");
836 fprintf(outfile, "\t\"\\tlwz 8, 0(1)\\n\"\n");
837 fprintf(outfile, "\t\"\\taddi 1, 1, 0x4\\n\"\n");
838 fprintf(outfile, "\t\"\\tlwz 9, 0(1)\\n\"\n");
839 fprintf(outfile, "\t\"\\taddi 1, 1, 0x4\\n\"\n");
840 fprintf(outfile, "\t\"\\tbctr\\n");
841 #else
842 #error You need to define import thunks for your architecture!
843 #endif
844 fprintf( outfile, "\"\n" );
846 pos += 4;
848 fprintf( outfile, "\".section\\t\\\".text\\\"\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
850 done:
851 return nb_imm;
854 /* output the delayed import table of a Win32 module */
855 static int output_delayed_imports( FILE *outfile )
857 int i, idx, j, pos;
859 if (!nb_delayed) goto done;
861 for (i = 0; i < nb_imports; i++)
863 if (!dll_imports[i]->delay) continue;
864 fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i);
865 for (j = 0; j < dll_imports[i]->nb_imports; j++)
867 fprintf( outfile, "void __wine_delay_imp_%d_%s();\n",
868 i, dll_imports[i]->imports[j].name );
871 fprintf( outfile, "\n" );
872 fprintf( outfile, "static struct {\n" );
873 fprintf( outfile, " struct ImgDelayDescr {\n" );
874 fprintf( outfile, " unsigned int grAttrs;\n" );
875 fprintf( outfile, " const char *szName;\n" );
876 fprintf( outfile, " void **phmod;\n" );
877 fprintf( outfile, " void **pIAT;\n" );
878 fprintf( outfile, " const char **pINT;\n" );
879 fprintf( outfile, " void* pBoundIAT;\n" );
880 fprintf( outfile, " void* pUnloadIAT;\n" );
881 fprintf( outfile, " unsigned long dwTimeStamp;\n" );
882 fprintf( outfile, " } imp[%d];\n", nb_delayed );
883 fprintf( outfile, " void *IAT[%d];\n", total_delayed );
884 fprintf( outfile, " const char *INT[%d];\n", total_delayed );
885 fprintf( outfile, "} delay_imports = {\n" );
886 fprintf( outfile, " {\n" );
887 for (i = j = 0; i < nb_imports; i++)
889 if (!dll_imports[i]->delay) continue;
890 fprintf( outfile, " { 0, \"%s\", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n",
891 dll_imports[i]->dll, i, j, j );
892 j += dll_imports[i]->nb_imports;
894 fprintf( outfile, " },\n {\n" );
895 for (i = 0; i < nb_imports; i++)
897 if (!dll_imports[i]->delay) continue;
898 fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
899 for (j = 0; j < dll_imports[i]->nb_imports; j++)
901 fprintf( outfile, " &__wine_delay_imp_%d_%s,\n", i, dll_imports[i]->imports[j].name);
904 fprintf( outfile, " },\n {\n" );
905 for (i = 0; i < nb_imports; i++)
907 if (!dll_imports[i]->delay) continue;
908 fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
909 for (j = 0; j < dll_imports[i]->nb_imports; j++)
911 struct func *import = &dll_imports[i]->imports[j];
912 if (import->ord_only)
913 fprintf( outfile, " (char *)%d,\n", import->ordinal );
914 else
915 fprintf( outfile, " \"%s\",\n", import->name );
918 fprintf( outfile, " }\n};\n\n" );
920 /* check if there's some stub defined. if so, exception struct
921 * is already defined, so don't emit it twice
923 for (i = 0; i < nb_entry_points; i++) if (EntryPoints[i]->type == TYPE_STUB) break;
925 if (i == nb_entry_points) {
926 fprintf( outfile, "struct exc_record {\n" );
927 fprintf( outfile, " unsigned int code, flags;\n" );
928 fprintf( outfile, " void *rec, *addr;\n" );
929 fprintf( outfile, " unsigned int params;\n" );
930 fprintf( outfile, " const void *info[15];\n" );
931 fprintf( outfile, "};\n\n" );
932 fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n" );
935 fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n");
936 fprintf( outfile, "extern void * __stdcall GetProcAddress(void *, const char*);\n");
937 fprintf( outfile, "\n" );
939 fprintf( outfile, "void *__stdcall __wine_delay_load( int idx_nr )\n" );
940 fprintf( outfile, "{\n" );
941 fprintf( outfile, " int idx = idx_nr >> 16, nr = idx_nr & 0xffff;\n" );
942 fprintf( outfile, " struct ImgDelayDescr *imd = delay_imports.imp + idx;\n" );
943 fprintf( outfile, " void **pIAT = imd->pIAT + nr;\n" );
944 fprintf( outfile, " const char** pINT = imd->pINT + nr;\n" );
945 fprintf( outfile, " void *fn;\n\n" );
947 fprintf( outfile, " if (!*imd->phmod) *imd->phmod = LoadLibraryA(imd->szName);\n" );
948 fprintf( outfile, " if (*imd->phmod && (fn = GetProcAddress(*imd->phmod, *pINT)))\n");
949 fprintf( outfile, " /* patch IAT with final value */\n" );
950 fprintf( outfile, " return *pIAT = fn;\n" );
951 fprintf( outfile, " else {\n");
952 fprintf( outfile, " struct exc_record rec;\n" );
953 fprintf( outfile, " rec.code = 0x80000100;\n" );
954 fprintf( outfile, " rec.flags = 1;\n" );
955 fprintf( outfile, " rec.rec = 0;\n" );
956 fprintf( outfile, " rec.params = 2;\n" );
957 fprintf( outfile, " rec.info[0] = imd->szName;\n" );
958 fprintf( outfile, " rec.info[1] = *pINT + 2;\n" );
959 fprintf( outfile, "#ifdef __GNUC__\n" );
960 fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
961 fprintf( outfile, "#else\n" );
962 fprintf( outfile, " rec.addr = 0;\n" );
963 fprintf( outfile, "#endif\n" );
964 fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n" );
965 fprintf( outfile, " return 0; /* shouldn't go here */\n" );
966 fprintf( outfile, " }\n}\n\n" );
968 fprintf( outfile, "#ifndef __GNUC__\n" );
969 fprintf( outfile, "static void __asm__dummy_delay_import(void) {\n" );
970 fprintf( outfile, "#endif\n" );
972 fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) );
973 fprintf( outfile, " \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
974 fprintf( outfile, " \"" __ASM_NAME("__wine_delay_load_asm") ":\\n\"\n" );
975 #if defined(__i386__)
976 fprintf( outfile, " \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
977 fprintf( outfile, " \"\\tcall __wine_delay_load\\n\"\n" );
978 fprintf( outfile, " \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
979 #elif defined(__sparc__)
980 fprintf( outfile, " \"\\tsave %%sp, -96, %%sp\\n\"\n" );
981 fprintf( outfile, " \"\\tcall __wine_delay_load\\n\"\n" );
982 fprintf( outfile, " \"\\tmov %%g1, %%o0\\n\"\n" );
983 fprintf( outfile, " \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
984 #elif defined(__PPC__)
985 /* Save all callee saved registers into a stackframe. */
986 fprintf( outfile, " \"\\tstwu %%r1, -48(%%r1)\\n\"\n" );
987 fprintf( outfile, " \"\\tstw %%r3, 4(%%r1)\\n\"\n" );
988 fprintf( outfile, " \"\\tstw %%r4, 8(%%r1)\\n\"\n" );
989 fprintf( outfile, " \"\\tstw %%r5, 12(%%r1)\\n\"\n" );
990 fprintf( outfile, " \"\\tstw %%r6, 16(%%r1)\\n\"\n" );
991 fprintf( outfile, " \"\\tstw %%r7, 20(%%r1)\\n\"\n" );
992 fprintf( outfile, " \"\\tstw %%r8, 24(%%r1)\\n\"\n" );
993 fprintf( outfile, " \"\\tstw %%r9, 28(%%r1)\\n\"\n" );
994 fprintf( outfile, " \"\\tstw %%r10, 32(%%r1)\\n\"\n" );
995 fprintf( outfile, " \"\\tstw %%r11, 36(%%r1)\\n\"\n" );
996 fprintf( outfile, " \"\\tstw %%r12, 40(%%r1)\\n\"\n" );
998 /* r0 -> r3 (arg1) */
999 fprintf( outfile, " \"\\tmr %%r3, %%r0\\n\"\n" );
1001 /* save return address */
1002 fprintf( outfile, " \"\\tmflr %%r0\\n\"\n" );
1003 fprintf( outfile, " \"\\tstw %%r0, 44(%%r1)\\n\"\n" );
1005 /* Call the __wine_delay_load function, arg1 is arg1. */
1006 fprintf( outfile, " \"\\tbl __wine_delay_load\\n\"\n" );
1008 /* Load return value from call into ctr register */
1009 fprintf( outfile, " \"\\tmtctr %%r3\\n\"\n" );
1011 /* restore all saved registers and drop stackframe. */
1012 fprintf( outfile, " \"\\tlwz %%r3, 4(%%r1)\\n\"\n" );
1013 fprintf( outfile, " \"\\tlwz %%r4, 8(%%r1)\\n\"\n" );
1014 fprintf( outfile, " \"\\tlwz %%r5, 12(%%r1)\\n\"\n" );
1015 fprintf( outfile, " \"\\tlwz %%r6, 16(%%r1)\\n\"\n" );
1016 fprintf( outfile, " \"\\tlwz %%r7, 20(%%r1)\\n\"\n" );
1017 fprintf( outfile, " \"\\tlwz %%r8, 24(%%r1)\\n\"\n" );
1018 fprintf( outfile, " \"\\tlwz %%r9, 28(%%r1)\\n\"\n" );
1019 fprintf( outfile, " \"\\tlwz %%r10, 32(%%r1)\\n\"\n" );
1020 fprintf( outfile, " \"\\tlwz %%r11, 36(%%r1)\\n\"\n" );
1021 fprintf( outfile, " \"\\tlwz %%r12, 40(%%r1)\\n\"\n" );
1022 /* Load return value from call into return register */
1023 fprintf( outfile, " \"\\tlwz %%r0, 44(%%r1)\\n\"\n" );
1024 fprintf( outfile, " \"\\tmtlr %%r0\\n\"\n" );
1025 fprintf( outfile, " \"\\taddi %%r1, %%r1, 48\\n\"\n" );
1026 /* branch to ctr register. */
1027 fprintf( outfile, " \"\\tbctr\\n\"\n" );
1029 #else
1030 #error You need to defined delayed import thunks for your architecture!
1031 #endif
1033 for (i = idx = 0; i < nb_imports; i++)
1035 if (!dll_imports[i]->delay) continue;
1036 for (j = 0; j < dll_imports[i]->nb_imports; j++)
1038 char buffer[128];
1039 sprintf( buffer, "__wine_delay_imp_%d_%s", i, dll_imports[i]->imports[j].name );
1040 fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer );
1041 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", buffer );
1042 #if defined(__i386__)
1043 fprintf( outfile, " \"\\tmovl $%d, %%eax\\n\"\n", (idx << 16) | j );
1044 fprintf( outfile, " \"\\tjmp __wine_delay_load_asm\\n\"\n" );
1045 #elif defined(__sparc__)
1046 fprintf( outfile, " \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
1047 fprintf( outfile, " \"\\tb,a __wine_delay_load_asm\\n\"\n" );
1048 #elif defined(__PPC__)
1049 /* g0 is a function scratch register or so I understand. */
1050 fprintf( outfile, " \"\\tli %%r0, %d\\n\"\n", (idx << 16) | j );
1051 fprintf( outfile, " \"\\tb __wine_delay_load_asm\\n\"\n" );
1052 #else
1053 #error You need to defined delayed import thunks for your architecture!
1054 #endif
1056 idx++;
1059 fprintf( outfile, "\n \".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
1060 pos = nb_delayed * 32;
1061 for (i = 0; i < nb_imports; i++)
1063 if (!dll_imports[i]->delay) continue;
1064 for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
1066 struct func *import = &dll_imports[i]->imports[j];
1067 fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name );
1068 fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name );
1069 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t\"", import->name);
1070 #if defined(__i386__)
1071 if (strstr( import->name, "__wine_call_from_16" ))
1072 fprintf( outfile, "\".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n\"", pos );
1073 else
1074 fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos );
1075 #elif defined(__sparc__)
1076 if ( !UsePIC )
1078 fprintf( outfile, "\"sethi %%hi(delay_imports+%d), %%g1\\n\\t\"", pos );
1079 fprintf( outfile, "\"ld [%%g1+%%lo(delay_imports+%d)], %%g1\\n\\t\"", pos );
1080 fprintf( outfile, "\"jmp %%g1\\n\\tnop\\n\"" );
1082 else
1084 /* Hmpf. Stupid sparc assembler always interprets global variable
1085 names as GOT offsets, so we have to do it the long way ... */
1086 fprintf( outfile, "\"save %%sp, -96, %%sp\\n\"" );
1087 fprintf( outfile, "\"0:\\tcall 1f\\n\\tnop\\n\"" );
1088 fprintf( outfile, "\"1:\\tsethi %%hi(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1089 fprintf( outfile, "\"or %%g1, %%lo(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1090 fprintf( outfile, "\"ld [%%g1+%%o7], %%g1\\n\\t\"" );
1091 fprintf( outfile, "\"jmp %%g1\\n\\trestore\\n\"" );
1094 #elif defined(__PPC__)
1095 fprintf(outfile, "\t\"addi 1, 1, -0x4\\n\"\n");
1096 fprintf(outfile, "\t\"\\tstw 9, 0(1)\\n\"\n");
1097 fprintf(outfile, "\t\"\\taddi 1, 1, -0x4\\n\"\n");
1098 fprintf(outfile, "\t\"\\tstw 8, 0(1)\\n\"\n");
1099 fprintf(outfile, "\t\"\\taddi 1, 1, -0x4\\n\"\n");
1100 fprintf(outfile, "\t\"\\tstw 7, 0(1)\\n\"\n");
1102 fprintf(outfile, "\t\"\\tlis 9,delay_imports+%d@ha\\n\"\n", pos);
1103 fprintf(outfile, "\t\"\\tla 8,delay_imports+%d@l(9)\\n\"\n", pos);
1104 fprintf(outfile, "\t\"\\tlwz 7, 0(8)\\n\"\n");
1105 fprintf(outfile, "\t\"\\tmtctr 7\\n\"\n");
1107 fprintf(outfile, "\t\"\\tlwz 7, 0(1)\\n\"\n");
1108 fprintf(outfile, "\t\"\\taddi 1, 1, 0x4\\n\"\n");
1109 fprintf(outfile, "\t\"\\tlwz 8, 0(1)\\n\"\n");
1110 fprintf(outfile, "\t\"\\taddi 1, 1, 0x4\\n\"\n");
1111 fprintf(outfile, "\t\"\\tlwz 9, 0(1)\\n\"\n");
1112 fprintf(outfile, "\t\"\\taddi 1, 1, 0x4\\n\"\n");
1113 fprintf(outfile, "\t\"\\tbctr\\n\"");
1115 /*fprintf(outfile, "\t\"li r0,delay_imports\\n\\t\"\n" );
1116 fprintf(outfile, "\t\"lwz r0, %d(r0)\\n\\t\"\n", pos);
1117 fprintf(outfile, "\t\"mtctr r0\\n\\t\"\n");
1118 fprintf(outfile, "\t\"bctr\\n\"");*/
1119 #else
1120 #error You need to define delayed import thunks for your architecture!
1121 #endif
1122 fprintf( outfile, "\n" );
1125 fprintf( outfile, "\".section \\\".text\\\"\");\n" );
1126 fprintf( outfile, "#ifndef __GNUC__\n" );
1127 fprintf( outfile, "}\n" );
1128 fprintf( outfile, "#endif\n" );
1129 fprintf( outfile, "\n" );
1131 done:
1132 return nb_delayed;
1135 /* output the import and delayed import tables of a Win32 module
1136 * returns number of DLLs exported in 'immediate' mode
1138 int output_imports( FILE *outfile )
1140 output_delayed_imports( outfile );
1141 return output_immediate_imports( outfile );