source: trunk/tools/pebuild/import.c@ 10366

Last change on this file since 10366 was 10298, checked in by sandervl, 22 years ago

added

File size: 40.9 KB
Line 
1/*
2 * DLL imports support
3 *
4 * Copyright 2000 Alexandre Julliard
5 * 2000 Eric Pouech
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include "config.h"
23#include "port.h"
24
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
32
33#include "build.h"
34
35struct func
36{
37 char *name; /* function name */
38 int ordinal; /* function ordinal */
39 int ord_only; /* non-zero if function is imported by ordinal */
40};
41
42struct import
43{
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 */
50};
51
52static char **undef_symbols; /* list of undefined symbols */
53static int nb_undef_symbols = -1;
54static int undef_size;
55
56static char **ignore_symbols; /* list of symbols to ignore */
57static int nb_ignore_symbols;
58static int ignore_size;
59
60static char *ld_tmp_file; /* ld temp file name */
61
62static struct import **dll_imports = NULL;
63static int nb_imports = 0; /* number of imported dlls (delayed or not) */
64static int nb_delayed = 0; /* number of delayed dlls */
65static int total_imports = 0; /* total number of imported functions */
66static int total_delayed = 0; /* total number of imported functions in delayed DLLs */
67
68/* list of symbols that are ignored by default */
69static const char * const default_ignored_symbols[] =
70{
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"
119};
120
121#ifdef __powerpc__
122# ifdef __APPLE__
123# define ppc_high(mem) "ha16(" mem ")"
124# define ppc_low(mem) "lo16(" mem ")"
125static const char * const ppc_reg[32] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
126 "r8", "r9", "r10","r11","r12","r13","r14","r15",
127 "r16","r17","r18","r19","r20","r21","r22","r23",
128 "r24","r25","r26","r27","r28","r29","r30","r31" };
129# else /* __APPLE__ */
130# define ppc_high(mem) "(" mem ")@hi"
131# define ppc_low(mem) "(" mem ")@l"
132static const char * const ppc_reg[32] = { "0", "1", "2", "3", "4", "5", "6", "7",
133 "8", "9", "10","11","12","13","14","15",
134 "16","17","18","19","20","21","22","23",
135 "24","25","26","27","28","29","30","31" };
136# endif /* __APPLE__ */
137#endif /* __powerpc__ */
138
139/* compare function names; helper for resolve_imports */
140static int name_cmp( const void *name, const void *entry )
141{
142 return strcmp( *(char **)name, *(char **)entry );
143}
144
145/* compare function names; helper for resolve_imports */
146static int func_cmp( const void *func1, const void *func2 )
147{
148 return strcmp( ((struct func *)func1)->name, ((struct func *)func2)->name );
149}
150
151/* locate a symbol in a (sorted) list */
152inline static const char *find_symbol( const char *name, char **table, int size )
153{
154 char **res = NULL;
155
156 if (table) {
157 res = bsearch( &name, table, size, sizeof(*table), name_cmp );
158 }
159
160 return res ? *res : NULL;
161}
162
163/* locate an export in a (sorted) export list */
164inline static struct func *find_export( const char *name, struct func *table, int size )
165{
166 struct func func, *res = NULL;
167
168 func.name = (char *)name;
169 func.ordinal = -1;
170 if (table) res = bsearch( &func, table, size, sizeof(*table), func_cmp );
171 return res;
172}
173
174/* sort a symbol table */
175inline static void sort_symbols( char **table, int size )
176{
177 if (table )
178 qsort( table, size, sizeof(*table), name_cmp );
179}
180
181/* free an import structure */
182static void free_imports( struct import *imp )
183{
184 int i;
185
186 for (i = 0; i < imp->nb_exports; i++) free( imp->exports[i].name );
187 for (i = 0; i < imp->nb_imports; i++) free( imp->imports[i].name );
188 free( imp->exports );
189 free( imp->imports );
190 free( imp->dll );
191 free( imp );
192}
193
194/* remove the temp file at exit */
195static void remove_ld_tmp_file(void)
196{
197 if (ld_tmp_file) unlink( ld_tmp_file );
198}
199
200/* check whether a given dll has already been imported */
201static int is_already_imported( const char *name )
202{
203 int i;
204
205 for (i = 0; i < nb_imports; i++)
206 {
207 if (!strcmp( dll_imports[i]->dll, name )) return 1;
208 }
209 return 0;
210}
211
212/* open the .so library for a given dll in a specified path */
213static char *try_library_path( const char *path, const char *name )
214{
215 char *buffer;
216 int fd;
217
218 buffer = xmalloc( strlen(path) + strlen(name) + 9 );
219 sprintf( buffer, "%s/lib%s.def", path, name );
220
221 /* check if the file exists */
222 if ((fd = open( buffer, O_RDONLY )) != -1)
223 {
224 close( fd );
225 return buffer;
226 }
227 free( buffer );
228 return NULL;
229}
230
231/* open the .so library for a given dll */
232static char *open_library( const char *name )
233{
234 char *fullname;
235 int i;
236
237 for (i = 0; i < nb_lib_paths; i++)
238 {
239 if ((fullname = try_library_path( lib_path[i], name ))) return fullname;
240 }
241 if (!(fullname = try_library_path( ".", name )))
242 fatal_error( "could not open .def file for %s\n", name );
243 return fullname;
244}
245
246/* skip whitespace until the next token */
247static char *skip_whitespace( char *p )
248{
249 while (*p && isspace(*p)) p++;
250 if (!*p || *p == ';') p = NULL;
251 return p;
252}
253
254/* skip to the start of the next token, null terminating the current one */
255static char *next_token( char *p )
256{
257 while (*p && !isspace(*p)) p++;
258 if (*p) *p++ = 0;
259 return skip_whitespace( p );
260}
261
262/* remove the @nn suffix from stdcall names */
263static char *remove_stdcall_decoration( char *buffer )
264{
265 char *p = buffer + strlen(buffer) - 1;
266 while (p > buffer && isdigit(*p)) p--;
267 if (p > buffer && *p == '@') *p = 0;
268 return buffer;
269}
270
271/* read in the list of exported symbols of an import library */
272static int read_import_lib( const char *name, struct import *imp )
273{
274 FILE *f;
275 char buffer[1024];
276 char *fullname;
277 int size;
278
279 imp->exports = NULL;
280 imp->nb_exports = size = 0;
281
282 fullname = open_library( name );
283 f = open_input_file( NULL, fullname );
284 free( fullname );
285
286 while (fgets( buffer, sizeof(buffer), f ))
287 {
288 char *name, *flags;
289 int ordinal = 0, ord_only = 0;
290
291 char *p = buffer + strlen(buffer) - 1;
292 if (p < buffer) goto next;
293 if (*p == '\n') *p-- = 0;
294
295 p = buffer;
296 if (!(p = skip_whitespace(p))) goto next;
297 name = p;
298 p = next_token( name );
299
300 if (!strcmp( name, "LIBRARY" ))
301 {
302 if (!p)
303 {
304 error( "Expected name after LIBRARY\n" );
305 goto next;
306 }
307 name = p;
308 p = next_token( name );
309 if (p)
310 {
311 error( "Garbage after LIBRARY statement\n" );
312 goto next;
313 }
314 if (is_already_imported( name ))
315 {
316 close_input_file( f );
317 return 0; /* ignore this dll */
318 }
319 free( imp->dll );
320 imp->dll = xstrdup( name );
321 goto next;
322 }
323 if (!strcmp( name, "EXPORTS" )) goto next;
324
325 /* check for ordinal */
326 if (!p)
327 {
328 error( "Expected ordinal after function name\n" );
329 goto next;
330 }
331 if (*p != '@' || !isdigit(p[1]))
332 {
333 error( "Expected ordinal after function name '%s'\n", name );
334 goto next;
335 }
336 ordinal = strtol( p+1, &p, 10 );
337 if (ordinal >= MAX_ORDINALS)
338 {
339 error( "Invalid ordinal number %d\n", ordinal );
340 goto next;
341 }
342
343 /* check for optional flags */
344 while (p && (p = skip_whitespace(p)))
345 {
346 flags = p;
347 p = next_token( flags );
348 if (!strcmp( flags, "NONAME" ))
349 {
350 ord_only = 1;
351 if (!ordinal)
352 {
353 error( "Invalid ordinal number %d\n", ordinal );
354 goto next;
355 }
356 }
357 else if (!strcmp( flags, "CONSTANT" ) || !strcmp( flags, "DATA" ))
358 {
359 /* we don't support importing non-function entry points */
360 goto next;
361 }
362 else if (!strcmp( flags, "PRIVATE" ))
363 {
364 /* function must not be imported */
365 goto next;
366 }
367 else
368 {
369 error( "Garbage after ordinal declaration\n" );
370 goto next;
371 }
372 }
373
374 if (imp->nb_exports == size)
375 {
376 size += 128;
377 imp->exports = xrealloc( imp->exports, size * sizeof(*imp->exports) );
378 }
379 if ((p = strchr( name, '=' ))) *p = 0;
380 remove_stdcall_decoration( name );
381 imp->exports[imp->nb_exports].name = xstrdup( name );
382 imp->exports[imp->nb_exports].ordinal = ordinal;
383 imp->exports[imp->nb_exports].ord_only = ord_only;
384 imp->nb_exports++;
385 next:
386 current_line++;
387 }
388 close_input_file( f );
389 if (imp->nb_exports)
390 qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp );
391 return !nb_errors;
392}
393
394/* add a dll to the list of imports */
395void add_import_dll( const char *name, int delay )
396{
397 struct import *imp;
398 char *fullname;
399
400 fullname = xmalloc( strlen(name) + 5 );
401 strcpy( fullname, name );
402 if (!strchr( fullname, '.' )) strcat( fullname, ".dll" );
403
404 /* check if we already imported it */
405 if (is_already_imported( fullname ))
406 {
407 free( fullname );
408 return;
409 }
410
411 imp = xmalloc( sizeof(*imp) );
412 imp->dll = fullname;
413 imp->delay = delay;
414 imp->imports = NULL;
415 imp->nb_imports = 0;
416
417 if (delay) nb_delayed++;
418
419 if (read_import_lib( name, imp ))
420 {
421 dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) );
422 dll_imports[nb_imports++] = imp;
423 }
424 else
425 {
426 free_imports( imp );
427 if (nb_errors) exit(1);
428 }
429}
430
431/* remove an imported dll, based on its index in the dll_imports array */
432static void remove_import_dll( int index )
433{
434 struct import *imp = dll_imports[index];
435
436 memmove( &dll_imports[index], &dll_imports[index+1], sizeof(imp) * (nb_imports - index - 1) );
437 nb_imports--;
438 if (imp->delay) nb_delayed--;
439 free_imports( imp );
440}
441
442/* initialize the list of ignored symbols */
443static void init_ignored_symbols(void)
444{
445 int i;
446
447 nb_ignore_symbols = sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]);
448 ignore_size = nb_ignore_symbols + 32;
449 ignore_symbols = xmalloc( ignore_size * sizeof(*ignore_symbols) );
450 for (i = 0; i < nb_ignore_symbols; i++)
451 ignore_symbols[i] = xstrdup( default_ignored_symbols[i] );
452}
453
454/* add a symbol to the ignored symbol list */
455/* if the name starts with '-' the symbol is removed instead */
456void add_ignore_symbol( const char *name )
457{
458 int i;
459
460 if (!ignore_symbols) init_ignored_symbols(); /* first time around, fill list with defaults */
461
462 if (name[0] == '-') /* remove it */
463 {
464 if (!name[1]) /* remove everything */
465 {
466 for (i = 0; i < nb_ignore_symbols; i++) free( ignore_symbols[i] );
467 nb_ignore_symbols = 0;
468 }
469 else
470 {
471 for (i = 0; i < nb_ignore_symbols; i++)
472 {
473 if (!strcmp( ignore_symbols[i], name+1 ))
474 {
475 free( ignore_symbols[i] );
476 memmove( &ignore_symbols[i], &ignore_symbols[i+1], nb_ignore_symbols - i - 1 );
477 nb_ignore_symbols--;
478 }
479 }
480 }
481 }
482 else
483 {
484 if (nb_ignore_symbols == ignore_size)
485 {
486 ignore_size += 32;
487 ignore_symbols = xrealloc( ignore_symbols, ignore_size * sizeof(*ignore_symbols) );
488 }
489 ignore_symbols[nb_ignore_symbols++] = xstrdup( name );
490 }
491}
492
493/* add a function to the list of imports from a given dll */
494static void add_import_func( struct import *imp, const struct func *func )
495{
496 imp->imports = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) );
497 imp->imports[imp->nb_imports].name = xstrdup( func->name );
498 imp->imports[imp->nb_imports].ordinal = func->ordinal;
499 imp->imports[imp->nb_imports].ord_only = func->ord_only;
500 imp->nb_imports++;
501 total_imports++;
502 if (imp->delay) total_delayed++;
503}
504
505/* add a symbol to the undef list */
506inline static void add_undef_symbol( const char *name )
507{
508 if (nb_undef_symbols == undef_size)
509 {
510 undef_size += 128;
511 undef_symbols = xrealloc( undef_symbols, undef_size * sizeof(*undef_symbols) );
512 }
513 undef_symbols[nb_undef_symbols++] = xstrdup( name );
514}
515
516/* remove all the holes in the undefined symbol list; return the number of removed symbols */
517static int remove_symbol_holes(void)
518{
519 int i, off;
520 for (i = off = 0; i < nb_undef_symbols; i++)
521 {
522 if (!undef_symbols[i]) off++;
523 else undef_symbols[i - off] = undef_symbols[i];
524 }
525 nb_undef_symbols -= off;
526 return off;
527}
528
529/* add a symbol to the extra list, but only if needed */
530static int add_extra_symbol( const char **extras, int *count, const char *name )
531{
532 int i;
533
534 if (!find_symbol( name, undef_symbols, nb_undef_symbols ))
535 {
536 /* check if the symbol is being exported by this dll */
537 for (i = 0; i < nb_entry_points; i++)
538 {
539 ORDDEF *odp = EntryPoints[i];
540 if (odp->type == TYPE_STDCALL ||
541 odp->type == TYPE_CDECL ||
542 odp->type == TYPE_VARARGS ||
543 odp->type == TYPE_EXTERN)
544 {
545 if (odp->name && !strcmp( odp->name, name )) return 0;
546 }
547 }
548 extras[*count] = name;
549 (*count)++;
550 }
551 return 1;
552}
553
554/* add the extra undefined symbols that will be contained in the generated spec file itself */
555static void add_extra_undef_symbols(void)
556{
557 const char *extras[10];
558 int i, count = 0, nb_stubs = 0, nb_regs = 0;
559 int kernel_imports = 0, ntdll_imports = 0;
560
561 sort_symbols( undef_symbols, nb_undef_symbols );
562
563 for (i = 0; i < nb_entry_points; i++)
564 {
565 ORDDEF *odp = EntryPoints[i];
566 if (odp->type == TYPE_STUB) nb_stubs++;
567 if (odp->flags & FLAG_REGISTER) nb_regs++;
568 }
569
570 /* add symbols that will be contained in the spec file itself */
571 switch (SpecMode)
572 {
573 case SPEC_MODE_DLL:
574 break;
575 case SPEC_MODE_GUIEXE:
576 kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" );
577 kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" );
578 kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" );
579 /* fall through */
580 case SPEC_MODE_CUIEXE:
581 kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
582 break;
583 case SPEC_MODE_GUIEXE_UNICODE:
584 kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" );
585 kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" );
586 kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" );
587 /* fall through */
588 case SPEC_MODE_CUIEXE_UNICODE:
589 kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
590 break;
591 }
592 if (nb_delayed)
593 {
594 kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA" );
595 kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress" );
596 }
597 if (nb_regs)
598 ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs" );
599 if (nb_delayed || nb_stubs)
600 ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException" );
601
602 /* make sure we import the dlls that contain these functions */
603 if (kernel_imports) add_import_dll( "kernel32", 0 );
604 if (ntdll_imports) add_import_dll( "ntdll", 0 );
605
606 if (count)
607 {
608 for (i = 0; i < count; i++) add_undef_symbol( extras[i] );
609 sort_symbols( undef_symbols, nb_undef_symbols );
610 }
611}
612
613/* check if a given imported dll is not needed, taking forwards into account */
614static int check_unused( const struct import* imp )
615{
616 int i;
617 size_t len = strlen(imp->dll);
618 const char *p = strchr( imp->dll, '.' );
619 if (p && !strcasecmp( p, ".dll" )) len = p - imp->dll;
620
621 for (i = Base; i <= Limit; i++)
622 {
623 ORDDEF *odp = Ordinals[i];
624 if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
625 if (!strncasecmp( odp->link_name, imp->dll, len ) &&
626 odp->link_name[len] == '.')
627 return 0; /* found a forward, it is used */
628 }
629 return 1;
630}
631
632/* combine a list of object files with ld into a single object file */
633/* returns the name of the combined file */
634static const char *ldcombine_files( char **argv )
635{
636 int i, len = 0;
637 char *cmd;
638 int fd, err;
639
640 if (output_file_name && output_file_name[0])
641 {
642 ld_tmp_file = xmalloc( strlen(output_file_name) + 10 );
643 strcpy( ld_tmp_file, output_file_name );
644 strcat( ld_tmp_file, ".XXXXXX.o" );
645 }
646 else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" );
647
648 if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" );
649 close( fd );
650 atexit( remove_ld_tmp_file );
651
652 for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
653 cmd = xmalloc( len + strlen(ld_tmp_file) + 10 );
654 sprintf( cmd, "ld -r -o %s", ld_tmp_file );
655 for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] );
656 err = system( cmd );
657 if (err) fatal_error( "ld -r failed with status %d\n", err );
658 free( cmd );
659 return ld_tmp_file;
660}
661
662/* read in the list of undefined symbols */
663void read_undef_symbols( char **argv )
664{
665 FILE *f;
666 char buffer[1024];
667 int err;
668 const char *name;
669
670 if (!argv[0]) return;
671
672 undef_size = nb_undef_symbols = 0;
673
674 /* if we have multiple object files, link them together */
675 if (argv[1]) name = ldcombine_files( argv );
676 else name = argv[0];
677
678 sprintf( buffer, "nm -u %s", name );
679 if (!(f = popen( buffer, "r" )))
680 fatal_error( "Cannot execute '%s'\n", buffer );
681
682 while (fgets( buffer, sizeof(buffer), f ))
683 {
684 char *p = buffer + strlen(buffer) - 1;
685 if (p < buffer) continue;
686 if (*p == '\n') *p-- = 0;
687 p = buffer;
688 while (*p == ' ') p++;
689 if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
690 add_undef_symbol( p );
691 }
692 if ((err = pclose( f ))) warning( "nm -u %s error %d\n", name, err );
693}
694
695static void remove_ignored_symbols(void)
696{
697 int i;
698
699 if (!ignore_symbols) init_ignored_symbols();
700 sort_symbols( ignore_symbols, nb_ignore_symbols );
701 for (i = 0; i < nb_undef_symbols; i++)
702 {
703 if (find_symbol( undef_symbols[i], ignore_symbols, nb_ignore_symbols ))
704 {
705 free( undef_symbols[i] );
706 undef_symbols[i] = NULL;
707 }
708 }
709 remove_symbol_holes();
710}
711
712/* resolve the imports for a Win32 module */
713int resolve_imports( void )
714{
715 int i, j;
716
717 if (nb_undef_symbols == -1) return 0; /* no symbol file specified */
718
719 add_extra_undef_symbols();
720 remove_ignored_symbols();
721
722 for (i = 0; i < nb_imports; i++)
723 {
724 struct import *imp = dll_imports[i];
725
726 for (j = 0; j < nb_undef_symbols; j++)
727 {
728 struct func *func = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
729 if (func)
730 {
731 add_import_func( imp, func );
732 free( undef_symbols[j] );
733 undef_symbols[j] = NULL;
734 }
735 }
736 /* remove all the holes in the undef symbols list */
737 if (!remove_symbol_holes() && check_unused( imp ))
738 {
739 /* the dll is not used, get rid of it */
740 warning( "%s imported but no symbols used\n", imp->dll );
741 remove_import_dll( i );
742 i--;
743 }
744 }
745 return 1;
746}
747
748/* output the import table of a Win32 module */
749static int output_immediate_imports( FILE *outfile )
750{
751 int i, j, pos;
752 int nb_imm = nb_imports - nb_delayed;
753
754 if (!nb_imm) goto done;
755
756 /* main import header */
757
758 fprintf( outfile, "\nstatic struct {\n" );
759 fprintf( outfile, " struct {\n" );
760 fprintf( outfile, " void *OriginalFirstThunk;\n" );
761 fprintf( outfile, " unsigned int TimeDateStamp;\n" );
762 fprintf( outfile, " unsigned int ForwarderChain;\n" );
763 fprintf( outfile, " const char *Name;\n" );
764 fprintf( outfile, " void *FirstThunk;\n" );
765 fprintf( outfile, " } imp[%d];\n", nb_imm+1 );
766 fprintf( outfile, " const char *data[%d];\n",
767 total_imports - total_delayed + nb_imm );
768 fprintf( outfile, "} imports = {\n {\n" );
769
770 /* list of dlls */
771
772 for (i = j = 0; i < nb_imports; i++)
773 {
774 if (dll_imports[i]->delay) continue;
775 fprintf( outfile, " { 0, 0, 0, \"%s\", &imports.data[%d] },\n",
776 dll_imports[i]->dll, j );
777 j += dll_imports[i]->nb_imports + 1;
778 }
779
780 fprintf( outfile, " { 0, 0, 0, 0, 0 },\n" );
781 fprintf( outfile, " },\n {\n" );
782
783 /* list of imported functions */
784
785 for (i = 0; i < nb_imports; i++)
786 {
787 if (dll_imports[i]->delay) continue;
788 fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
789 for (j = 0; j < dll_imports[i]->nb_imports; j++)
790 {
791 struct func *import = &dll_imports[i]->imports[j];
792 if (!import->ord_only)
793 {
794 unsigned short ord = import->ordinal;
795 fprintf( outfile, " \"\\%03o\\%03o%s\",\n",
796 *(unsigned char *)&ord, *((unsigned char *)&ord + 1), import->name );
797 }
798 else
799 fprintf( outfile, " (char *)%d,\n", import->ordinal );
800 }
801 fprintf( outfile, " 0,\n" );
802 }
803 fprintf( outfile, " }\n};\n\n" );
804
805#if 0
806 /* thunks for imported functions */
807
808 fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
809 pos = 20 * (nb_imm + 1); /* offset of imports.data from start of imports */
810 fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
811 for (i = 0; i < nb_imports; i++)
812 {
813 if (dll_imports[i]->delay) continue;
814 for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
815 {
816 struct func *import = &dll_imports[i]->imports[j];
817 fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name );
818 fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name );
819 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", import->name);
820
821#if defined(__i386__)
822 if (strstr( import->name, "__wine_call_from_16" ))
823 fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos );
824 else
825 fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos );
826#elif defined(__sparc__)
827 if ( !UsePIC )
828 {
829 fprintf( outfile, "sethi %%hi(imports+%d), %%g1\\n\\t", pos );
830 fprintf( outfile, "ld [%%g1+%%lo(imports+%d)], %%g1\\n\\t", pos );
831 fprintf( outfile, "jmp %%g1\\n\\tnop\\n" );
832 }
833 else
834 {
835 /* Hmpf. Stupid sparc assembler always interprets global variable
836 names as GOT offsets, so we have to do it the long way ... */
837 fprintf( outfile, "save %%sp, -96, %%sp\\n" );
838 fprintf( outfile, "0:\\tcall 1f\\n\\tnop\\n" );
839 fprintf( outfile, "1:\\tsethi %%hi(imports+%d-0b), %%g1\\n\\t", pos );
840 fprintf( outfile, "or %%g1, %%lo(imports+%d-0b), %%g1\\n\\t", pos );
841 fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
842 fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
843 }
844
845#elif defined(__powerpc__)
846 fprintf(outfile, "\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
847 fprintf(outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
848 fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
849 fprintf(outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
850 fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
851 fprintf(outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
852
853 fprintf(outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
854 fprintf(outfile, "\t\"\\tla %s, " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
855 fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
856 fprintf(outfile, "\t\"\\tmctr %s\\n\"\n", ppc_reg[7]);
857
858 fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
859 fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
860 fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
861 fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
862 fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
863 fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
864 fprintf(outfile, "\t\"\\tbctr\\n");
865#else
866#error You need to define import thunks for your architecture!
867#endif
868 fprintf( outfile, "\"\n" );
869 }
870 pos += 4;
871 }
872#endif
873 fprintf( outfile, "\".section\\t\\\".text\\\"\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
874
875 done:
876 return nb_imm;
877}
878
879/* output the delayed import table of a Win32 module */
880static int output_delayed_imports( FILE *outfile )
881{
882 int i, idx, j, pos;
883
884 if (!nb_delayed) goto done;
885
886 for (i = 0; i < nb_imports; i++)
887 {
888 if (!dll_imports[i]->delay) continue;
889 fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i);
890 for (j = 0; j < dll_imports[i]->nb_imports; j++)
891 {
892 fprintf( outfile, "void __wine_delay_imp_%d_%s();\n",
893 i, dll_imports[i]->imports[j].name );
894 }
895 }
896 fprintf( outfile, "\n" );
897 fprintf( outfile, "static struct {\n" );
898 fprintf( outfile, " struct ImgDelayDescr {\n" );
899 fprintf( outfile, " unsigned int grAttrs;\n" );
900 fprintf( outfile, " const char *szName;\n" );
901 fprintf( outfile, " void **phmod;\n" );
902 fprintf( outfile, " void **pIAT;\n" );
903 fprintf( outfile, " const char **pINT;\n" );
904 fprintf( outfile, " void* pBoundIAT;\n" );
905 fprintf( outfile, " void* pUnloadIAT;\n" );
906 fprintf( outfile, " unsigned long dwTimeStamp;\n" );
907 fprintf( outfile, " } imp[%d];\n", nb_delayed );
908 fprintf( outfile, " void *IAT[%d];\n", total_delayed );
909 fprintf( outfile, " const char *INT[%d];\n", total_delayed );
910 fprintf( outfile, "} delay_imports = {\n" );
911 fprintf( outfile, " {\n" );
912 for (i = j = 0; i < nb_imports; i++)
913 {
914 if (!dll_imports[i]->delay) continue;
915 fprintf( outfile, " { 0, \"%s\", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n",
916 dll_imports[i]->dll, i, j, j );
917 j += dll_imports[i]->nb_imports;
918 }
919 fprintf( outfile, " },\n {\n" );
920 for (i = 0; i < nb_imports; i++)
921 {
922 if (!dll_imports[i]->delay) continue;
923 fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
924 for (j = 0; j < dll_imports[i]->nb_imports; j++)
925 {
926 fprintf( outfile, " &__wine_delay_imp_%d_%s,\n", i, dll_imports[i]->imports[j].name);
927 }
928 }
929 fprintf( outfile, " },\n {\n" );
930 for (i = 0; i < nb_imports; i++)
931 {
932 if (!dll_imports[i]->delay) continue;
933 fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
934 for (j = 0; j < dll_imports[i]->nb_imports; j++)
935 {
936 struct func *import = &dll_imports[i]->imports[j];
937 if (import->ord_only)
938 fprintf( outfile, " (char *)%d,\n", import->ordinal );
939 else
940 fprintf( outfile, " \"%s\",\n", import->name );
941 }
942 }
943 fprintf( outfile, " }\n};\n\n" );
944
945 /* check if there's some stub defined. if so, exception struct
946 * is already defined, so don't emit it twice
947 */
948 for (i = 0; i < nb_entry_points; i++) if (EntryPoints[i]->type == TYPE_STUB) break;
949
950 if (i == nb_entry_points) {
951 fprintf( outfile, "struct exc_record {\n" );
952 fprintf( outfile, " unsigned int code, flags;\n" );
953 fprintf( outfile, " void *rec, *addr;\n" );
954 fprintf( outfile, " unsigned int params;\n" );
955 fprintf( outfile, " const void *info[15];\n" );
956 fprintf( outfile, "};\n\n" );
957 fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n" );
958 }
959
960 fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n");
961 fprintf( outfile, "extern void * __stdcall GetProcAddress(void *, const char*);\n");
962 fprintf( outfile, "\n" );
963
964 fprintf( outfile, "void *__stdcall __wine_delay_load( int idx_nr )\n" );
965 fprintf( outfile, "{\n" );
966 fprintf( outfile, " int idx = idx_nr >> 16, nr = idx_nr & 0xffff;\n" );
967 fprintf( outfile, " struct ImgDelayDescr *imd = delay_imports.imp + idx;\n" );
968 fprintf( outfile, " void **pIAT = imd->pIAT + nr;\n" );
969 fprintf( outfile, " const char** pINT = imd->pINT + nr;\n" );
970 fprintf( outfile, " void *fn;\n\n" );
971
972 fprintf( outfile, " if (!*imd->phmod) *imd->phmod = LoadLibraryA(imd->szName);\n" );
973 fprintf( outfile, " if (*imd->phmod && (fn = GetProcAddress(*imd->phmod, *pINT)))\n");
974 fprintf( outfile, " /* patch IAT with final value */\n" );
975 fprintf( outfile, " return *pIAT = fn;\n" );
976 fprintf( outfile, " else {\n");
977 fprintf( outfile, " struct exc_record rec;\n" );
978 fprintf( outfile, " rec.code = 0x80000100;\n" );
979 fprintf( outfile, " rec.flags = 1;\n" );
980 fprintf( outfile, " rec.rec = 0;\n" );
981 fprintf( outfile, " rec.params = 2;\n" );
982 fprintf( outfile, " rec.info[0] = imd->szName;\n" );
983 fprintf( outfile, " rec.info[1] = *pINT + 2;\n" );
984 fprintf( outfile, "#ifdef __GNUC__\n" );
985 fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
986 fprintf( outfile, "#else\n" );
987 fprintf( outfile, " rec.addr = 0;\n" );
988 fprintf( outfile, "#endif\n" );
989 fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n" );
990 fprintf( outfile, " return 0; /* shouldn't go here */\n" );
991 fprintf( outfile, " }\n}\n\n" );
992
993 fprintf( outfile, "#ifndef __GNUC__\n" );
994 fprintf( outfile, "static void __asm__dummy_delay_import(void) {\n" );
995 fprintf( outfile, "#endif\n" );
996
997 fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) );
998 fprintf( outfile, " \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
999 fprintf( outfile, " \"" __ASM_NAME("__wine_delay_load_asm") ":\\n\"\n" );
1000#if defined(__i386__)
1001 fprintf( outfile, " \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
1002 fprintf( outfile, " \"\\tcall __wine_delay_load\\n\"\n" );
1003 fprintf( outfile, " \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
1004#elif defined(__sparc__)
1005 fprintf( outfile, " \"\\tsave %%sp, -96, %%sp\\n\"\n" );
1006 fprintf( outfile, " \"\\tcall __wine_delay_load\\n\"\n" );
1007 fprintf( outfile, " \"\\tmov %%g1, %%o0\\n\"\n" );
1008 fprintf( outfile, " \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
1009#elif defined(__powerpc__)
1010 /* Save all callee saved registers into a stackframe. */
1011 fprintf( outfile, " \"\\tstwu %s, -48, %s\\n\"\n", ppc_reg[1], ppc_reg[1]);
1012 fprintf( outfile, " \"\\tstw %s, 4, %s\\n\"\n", ppc_reg[3], ppc_reg[1]);
1013 fprintf( outfile, " \"\\tstw %s, 8, %s\\n\"\n", ppc_reg[4], ppc_reg[1]);
1014 fprintf( outfile, " \"\\tstw %s, 12, %s\\n\"\n", ppc_reg[5], ppc_reg[1]);
1015 fprintf( outfile, " \"\\tstw %s, 16, %s\\n\"\n", ppc_reg[6], ppc_reg[1]);
1016 fprintf( outfile, " \"\\tstw %s, 20, %s\\n\"\n", ppc_reg[7], ppc_reg[1]);
1017 fprintf( outfile, " \"\\tstw %s, 24, %s\\n\"\n", ppc_reg[8], ppc_reg[1]);
1018 fprintf( outfile, " \"\\tstw %s, 28, %s\\n\"\n", ppc_reg[9], ppc_reg[1]);
1019 fprintf( outfile, " \"\\tstw %s, 32, %s\\n\"\n", ppc_reg[10], ppc_reg[1]);
1020 fprintf( outfile, " \"\\tstw %s, 36, %s\\n\"\n", ppc_reg[11], ppc_reg[1]);
1021 fprintf( outfile, " \"\\tstw %s, 40, %s\\n\"\n", ppc_reg[12], ppc_reg[1]);
1022
1023 /* r0 -> r3 (arg1) */
1024 fprintf( outfile, " \"\\tmr %s, %s\\n\"\n", ppc_reg[3], ppc_reg[0]);
1025
1026 /* save return address */
1027 fprintf( outfile, " \"\\tmflr %s\\n\"\n", ppc_reg[0]);
1028 fprintf( outfile, " \"\\tstw %s, 44, %s\\n\"\n", ppc_reg[0], ppc_reg[1]);
1029
1030 /* Call the __wine_delay_load function, arg1 is arg1. */
1031 fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_delay_load") "\\n\"\n");
1032
1033 /* Load return value from call into ctr register */
1034 fprintf( outfile, " \"\\tmtctr %s\\n\"\n", ppc_reg[3]);
1035
1036 /* restore all saved registers and drop stackframe. */
1037 fprintf( outfile, " \"\\tlwz %s, 4, %s\\n\"\n", ppc_reg[3], ppc_reg[1]);
1038 fprintf( outfile, " \"\\tlwz %s, 8, %s\\n\"\n", ppc_reg[4], ppc_reg[1]);
1039 fprintf( outfile, " \"\\tlwz %s, 12, %s\\n\"\n", ppc_reg[5], ppc_reg[1]);
1040 fprintf( outfile, " \"\\tlwz %s, 16, %s\\n\"\n", ppc_reg[6], ppc_reg[1]);
1041 fprintf( outfile, " \"\\tlwz %s, 20, %s\\n\"\n", ppc_reg[7], ppc_reg[1]);
1042 fprintf( outfile, " \"\\tlwz %s, 24, %s\\n\"\n", ppc_reg[8], ppc_reg[1]);
1043 fprintf( outfile, " \"\\tlwz %s, 28, %s\\n\"\n", ppc_reg[9], ppc_reg[1]);
1044 fprintf( outfile, " \"\\tlwz %s, 32, %s\\n\"\n", ppc_reg[10], ppc_reg[1]);
1045 fprintf( outfile, " \"\\tlwz %s, 36, %s\\n\"\n", ppc_reg[11], ppc_reg[1]);
1046 fprintf( outfile, " \"\\tlwz %s, 40, %s\\n\"\n", ppc_reg[12], ppc_reg[1]);
1047
1048 /* Load return value from call into return register */
1049 fprintf( outfile, " \"\\tlwz %s, 44, %s\\n\"\n", ppc_reg[0], ppc_reg[1]);
1050 fprintf( outfile, " \"\\tmtlr %s\\n\"\n", ppc_reg[0]);
1051 fprintf( outfile, " \"\\taddi %s, %s, 48\\n\"\n", ppc_reg[1], ppc_reg[1]);
1052
1053 /* branch to ctr register. */
1054 fprintf( outfile, "\"bctr\\n\"\n");
1055#else
1056#error You need to defined delayed import thunks for your architecture!
1057#endif
1058
1059 for (i = idx = 0; i < nb_imports; i++)
1060 {
1061 if (!dll_imports[i]->delay) continue;
1062 for (j = 0; j < dll_imports[i]->nb_imports; j++)
1063 {
1064 char buffer[128];
1065 sprintf( buffer, "__wine_delay_imp_%d_%s", i, dll_imports[i]->imports[j].name );
1066 fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer );
1067 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", buffer );
1068#if defined(__i386__)
1069 fprintf( outfile, " \"\\tmovl $%d, %%eax\\n\"\n", (idx << 16) | j );
1070 fprintf( outfile, " \"\\tjmp __wine_delay_load_asm\\n\"\n" );
1071#elif defined(__sparc__)
1072 fprintf( outfile, " \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
1073 fprintf( outfile, " \"\\tb,a __wine_delay_load_asm\\n\"\n" );
1074#elif defined(__powerpc__)
1075 /* g0 is a function scratch register or so I understand. */
1076 /* First load the upper half-word, and then the lower part */
1077 fprintf( outfile, " \"\\lis %s, %d\\n\"\n", ppc_reg[0], idx);
1078 fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[0], j);
1079 fprintf( outfile, " \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
1080#else
1081#error You need to defined delayed import thunks for your architecture!
1082#endif
1083 }
1084 idx++;
1085 }
1086
1087 fprintf( outfile, "\n \".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
1088 pos = nb_delayed * 32;
1089 for (i = 0; i < nb_imports; i++)
1090 {
1091 if (!dll_imports[i]->delay) continue;
1092 for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
1093 {
1094 struct func *import = &dll_imports[i]->imports[j];
1095 fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name );
1096 fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name );
1097 fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t\"", import->name);
1098#if defined(__i386__)
1099 if (strstr( import->name, "__wine_call_from_16" ))
1100 fprintf( outfile, "\".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n\"", pos );
1101 else
1102 fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos );
1103#elif defined(__sparc__)
1104 if ( !UsePIC )
1105 {
1106 fprintf( outfile, "\"sethi %%hi(delay_imports+%d), %%g1\\n\\t\"", pos );
1107 fprintf( outfile, "\"ld [%%g1+%%lo(delay_imports+%d)], %%g1\\n\\t\"", pos );
1108 fprintf( outfile, "\"jmp %%g1\\n\\tnop\\n\"" );
1109 }
1110 else
1111 {
1112 /* Hmpf. Stupid sparc assembler always interprets global variable
1113 names as GOT offsets, so we have to do it the long way ... */
1114 fprintf( outfile, "\"save %%sp, -96, %%sp\\n\"" );
1115 fprintf( outfile, "\"0:\\tcall 1f\\n\\tnop\\n\"" );
1116 fprintf( outfile, "\"1:\\tsethi %%hi(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1117 fprintf( outfile, "\"or %%g1, %%lo(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1118 fprintf( outfile, "\"ld [%%g1+%%o7], %%g1\\n\\t\"" );
1119 fprintf( outfile, "\"jmp %%g1\\n\\trestore\\n\"" );
1120 }
1121
1122#elif defined(__powerpc__)
1123 fprintf( outfile, "\t addi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1124 fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
1125 fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1126 fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
1127 fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1128 fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
1129 fprintf( outfile, "\t\"\\tlis %s " ppc_high(__ASM_NAME("imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
1130 fprintf( outfile, "\t\"\\tla %s " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
1131 fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
1132 fprintf( outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
1133
1134 fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
1135 fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1136 fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
1137 fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1138 fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
1139 fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1140 fprintf( outfile, "\t\"\\tbctr\\n");
1141#else
1142#error You need to define delayed import thunks for your architecture!
1143#endif
1144 fprintf( outfile, "\n" );
1145 }
1146 }
1147 fprintf( outfile, "\".section \\\".text\\\"\");\n" );
1148 fprintf( outfile, "#ifndef __GNUC__\n" );
1149 fprintf( outfile, "}\n" );
1150 fprintf( outfile, "#endif\n" );
1151 fprintf( outfile, "\n" );
1152
1153 done:
1154 return nb_delayed;
1155}
1156
1157/* output the import and delayed import tables of a Win32 module
1158 * returns number of DLLs exported in 'immediate' mode
1159 */
1160int output_imports( FILE *outfile )
1161{
1162 output_delayed_imports( outfile );
1163 return output_immediate_imports( outfile );
1164}
Note: See TracBrowser for help on using the repository browser.