Initial revision
[binutils.git] / binutils / dlltool.c
blobed5cf5e3fccedc51cc1226e5969b8a5efbd711f8
1 /* dlltool.c -- tool to generate stuff for PE style DLLs
2 Copyright (C) 1995, 96, 97, 98, 1999 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
23 This program allows you to build the files necessary to create
24 DLLs to run on a system which understands PE format image files.
25 (eg, Windows NT)
27 See "Peering Inside the PE: A Tour of the Win32 Portable Executable
28 File Format", MSJ 1994, Volume 9 for more information.
29 Also see "Microsoft Portable Executable and Common Object File Format,
30 Specification 4.1" for more information.
32 A DLL contains an export table which contains the information
33 which the runtime loader needs to tie up references from a
34 referencing program.
36 The export table is generated by this program by reading
37 in a .DEF file or scanning the .a and .o files which will be in the
38 DLL. A .o file can contain information in special ".drectve" sections
39 with export information.
41 A DEF file contains any number of the following commands:
44 NAME <name> [ , <base> ]
45 The result is going to be <name>.EXE
47 LIBRARY <name> [ , <base> ]
48 The result is going to be <name>.DLL
50 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] ) *
51 Declares name1 as an exported symbol from the
52 DLL, with optional ordinal number <integer>
54 IMPORTS ( ( <internal-name> = <module-name> . <integer> )
55 | ( [ <internal-name> = ] <module-name> . <external-name> )) *
56 Declares that <external-name> or the exported function whoes ordinal number
57 is <integer> is to be imported from the file <module-name>. If
58 <internal-name> is specified then this is the name that the imported
59 function will be refered to in the body of the DLL.
61 DESCRIPTION <string>
62 Puts <string> into output .exp file in the .rdata section
64 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
65 Generates --stack|--heap <number-reserve>,<number-commit>
66 in the output .drectve section. The linker will
67 see this and act upon it.
69 [CODE|DATA] <attr>+
70 SECTIONS ( <sectionname> <attr>+ )*
71 <attr> = READ | WRITE | EXECUTE | SHARED
72 Generates --attr <sectionname> <attr> in the output
73 .drectve section. The linker will see this and act
74 upon it.
77 A -export:<name> in a .drectve section in an input .o or .a
78 file to this program is equivalent to a EXPORTS <name>
79 in a .DEF file.
83 The program generates output files with the prefix supplied
84 on the command line, or in the def file, or taken from the first
85 supplied argument.
87 The .exp.s file contains the information necessary to export
88 the routines in the DLL. The .lib.s file contains the information
89 necessary to use the DLL's routines from a referencing program.
93 Example:
95 file1.c:
96 asm (".section .drectve");
97 asm (".ascii \"-export:adef\"");
99 void adef (char * s)
101 printf ("hello from the dll %s\n", s);
104 void bdef (char * s)
106 printf ("hello from the dll and the other entry point %s\n", s);
109 file2.c:
110 asm (".section .drectve");
111 asm (".ascii \"-export:cdef\"");
112 asm (".ascii \"-export:ddef\"");
114 void cdef (char * s)
116 printf ("hello from the dll %s\n", s);
119 void ddef (char * s)
121 printf ("hello from the dll and the other entry point %s\n", s);
124 printf()
126 return 9;
129 main.c
131 void main()
133 cdef();
136 thedll.def
138 LIBRARY thedll
139 HEAPSIZE 0x40000, 0x2000
140 EXPORTS bdef @ 20
141 cdef @ 30 NONAME
143 SECTIONS donkey READ WRITE
144 aardvark EXECUTE
146 # compile up the parts of the dll
148 gcc -c file1.c
149 gcc -c file2.c
151 # put them in a library (you don't have to, you
152 # could name all the .os on the dlltool line)
154 ar qcv thedll.in file1.o file2.o
155 ranlib thedll.in
157 # run this tool over the library and the def file
158 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
160 # build the dll with the library with file1.o, file2.o and the export table
161 ld -o thedll.dll thedll.o thedll.in
163 # build the mainline
164 gcc -c themain.c
166 # link the executable with the import library
167 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
171 /* .idata section description
173 The .idata section is the import table. It is a collection of several
174 subsections used to keep the pieces for each dll together: .idata$[234567].
175 IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
177 .idata$2 = Import Directory Table
178 = array of IMAGE_IMPORT_DESCRIPTOR's.
180 DWORD Import Lookup Table; - pointer to .idata$4
181 DWORD TimeDateStamp; - currently always 0
182 DWORD ForwarderChain; - currently always 0
183 DWORD Name; - pointer to dll's name
184 PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
186 .idata$3 = null terminating entry for .idata$2.
188 .idata$4 = Import Lookup Table
189 = array of array of pointers to hint name table.
190 There is one for each dll being imported from, and each dll's set is
191 terminated by a trailing NULL.
193 .idata$5 = Import Address Table
194 = array of array of pointers to hint name table.
195 There is one for each dll being imported from, and each dll's set is
196 terminated by a trailing NULL.
197 Initially, this table is identical to the Import Lookup Table. However,
198 at load time, the loader overwrites the entries with the address of the
199 function.
201 .idata$6 = Hint Name Table
202 = Array of { short, asciz } entries, one for each imported function.
203 The `short' is the function's ordinal number.
205 .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
208 /* AIX requires this to be the first thing in the file. */
209 #ifndef __GNUC__
210 # ifdef _AIX
211 #pragma alloca
212 #endif
213 #endif
215 #define show_allnames 0
217 #define PAGE_SIZE 4096
218 #define PAGE_MASK (-PAGE_SIZE)
219 #include "bfd.h"
220 #include "libiberty.h"
221 #include "bucomm.h"
222 #include "getopt.h"
223 #include "demangle.h"
224 #include "dlltool.h"
226 #include <ctype.h>
227 #include <time.h>
228 #ifdef __STDC__
229 #include <stdarg.h>
230 #else
231 #include <varargs.h>
232 #endif
234 #ifdef DLLTOOL_ARM
235 #include "coff/arm.h"
236 #include "coff/internal.h"
237 #endif
239 #ifdef HAVE_SYS_WAIT_H
240 #include <sys/wait.h>
241 #else /* ! HAVE_SYS_WAIT_H */
242 #if ! defined (_WIN32) || defined (__CYGWIN32__)
243 #ifndef WIFEXITED
244 #define WIFEXITED(w) (((w)&0377) == 0)
245 #endif
246 #ifndef WIFSIGNALED
247 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
248 #endif
249 #ifndef WTERMSIG
250 #define WTERMSIG(w) ((w) & 0177)
251 #endif
252 #ifndef WEXITSTATUS
253 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
254 #endif
255 #else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
256 #ifndef WIFEXITED
257 #define WIFEXITED(w) (((w) & 0xff) == 0)
258 #endif
259 #ifndef WIFSIGNALED
260 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
261 #endif
262 #ifndef WTERMSIG
263 #define WTERMSIG(w) ((w) & 0x7f)
264 #endif
265 #ifndef WEXITSTATUS
266 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
267 #endif
268 #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
269 #endif /* ! HAVE_SYS_WAIT_H */
271 /* ifunc and ihead data structures: ttk@cygnus.com 1997
273 When IMPORT declarations are encountered in a .def file the
274 function import information is stored in a structure referenced by
275 the global variable IMPORT_LIST. The structure is a linked list
276 containing the names of the dll files each function is imported
277 from and a linked list of functions being imported from that dll
278 file. This roughly parallels the structure of the .idata section
279 in the PE object file.
281 The contents of .def file are interpreted from within the
282 process_def_file function. Every time an IMPORT declaration is
283 encountered, it is broken up into its component parts and passed to
284 def_import. IMPORT_LIST is initialized to NULL in function main. */
286 typedef struct ifunct
288 char *name; /* name of function being imported */
289 int ord; /* two-byte ordinal value associated with function */
290 struct ifunct *next;
291 } ifunctype;
293 typedef struct iheadt
295 char *dllname; /* name of dll file imported from */
296 long nfuncs; /* number of functions in list */
297 struct ifunct *funchead; /* first function in list */
298 struct ifunct *functail; /* last function in list */
299 struct iheadt *next; /* next dll file in list */
300 } iheadtype;
302 /* Structure containing all import information as defined in .def file
303 (qv "ihead structure"). */
305 static iheadtype *import_list = NULL;
307 static char *as_name = "as";
308 static char * as_flags = "";
310 static int no_idata4;
311 static int no_idata5;
312 static char *exp_name;
313 static char *imp_name;
314 static char *head_label;
315 static char *imp_name_lab;
316 static char *dll_name;
318 static int add_indirect = 0;
319 static int add_underscore = 0;
320 static int dontdeltemps = 0;
322 #ifdef DLLTOOL_ARM
323 static int interwork = 0;
324 #endif
326 /* True if we should export all symbols. Otherwise, we only export
327 symbols listed in .drectve sections or in the def file. */
328 static boolean export_all_symbols;
330 /* True if we should exclude the symbols in DEFAULT_EXCLUDES when
331 exporting all symbols. */
332 static boolean do_default_excludes;
334 /* Default symbols to exclude when exporting all the symbols. */
335 static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr";
337 static char *def_file;
339 extern char * program_name;
341 static int machine;
342 static int killat;
343 static int add_stdcall_alias;
344 static int verbose;
345 static FILE *output_def;
346 static FILE *base_file;
348 #ifdef DLLTOOL_BEOS
349 static const char *mname = "beos";
350 #endif
352 #ifdef DLLTOOL_ARM
353 static const char *mname = "arm";
354 #endif
356 #ifdef DLLTOOL_I386
357 static const char *mname = "i386";
358 #endif
360 #ifdef DLLTOOL_PPC
361 static const char *mname = "ppc";
362 #endif
364 #define PATHMAX 250 /* What's the right name for this ? */
366 #define TMP_ASM "dc.s"
367 #define TMP_HEAD_S "dh.s"
368 #define TMP_HEAD_O "dh.o"
369 #define TMP_TAIL_S "dt.s"
370 #define TMP_TAIL_O "dt.o"
371 #define TMP_STUB "ds"
373 /* This bit of assemly does jmp * ....
374 s set how_jtab_roff to mark where the 32bit abs branch should go */
375 static const unsigned char i386_jtab[] =
377 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
380 static const unsigned char arm_jtab[] =
382 0x00, 0xc0, 0x9f, 0xe5,
383 0x00, 0xf0, 0x9c, 0xe5,
384 0, 0, 0, 0
387 static const unsigned char thumb_jtab[] =
389 0xc0, 0xb4,
390 0x02, 0x4e,
391 0x36, 0x68,
392 0x01, 0x96,
393 0x40, 0xbd,
394 0xc0, 0x46,
395 0, 0, 0, 0
398 /* This is the glue sequence for PowerPC PE. There is a */
399 /* tocrel16-tocdefn reloc against the first instruction. */
400 /* We also need a IMGLUE reloc against the glue function */
401 /* to restore the toc saved by the third instruction in */
402 /* the glue. */
403 static const unsigned char ppc_jtab[] =
405 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
406 /* Reloc TOCREL16 __imp_xxx */
407 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
408 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
409 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
410 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
411 0x20, 0x04, 0x80, 0x4E /* bctr */
414 #ifdef DLLTOOL_PPC
415 /* the glue instruction, picks up the toc from the stw in */
416 /* the above code: "lwz r2,4(r1)" */
417 static bfd_vma ppc_glue_insn = 0x80410004;
418 #endif
420 /* The outfile array must be big enough to contain a fully
421 qualified path name, plus an arbitary series of command
422 line switches. We hope that PATH_MAX times two will be
423 enough. */
424 static char outfile [PATHMAX * 2];
426 struct mac
428 const char *type;
429 const char *how_byte;
430 const char *how_short;
431 const char *how_long;
432 const char *how_asciz;
433 const char *how_comment;
434 const char *how_jump;
435 const char *how_global;
436 const char *how_space;
437 const char *how_align_short;
438 const char *how_align_long;
439 const char *how_bfd_target;
440 enum bfd_architecture how_bfd_arch;
441 const unsigned char *how_jtab;
442 int how_jtab_size; /* size of the jtab entry */
443 int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
446 static const struct mac
447 mtable[] =
450 #define MARM 0
451 "arm", ".byte", ".short", ".long", ".asciz", "@",
452 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
453 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
454 arm_jtab, sizeof (arm_jtab), 8
458 #define M386 1
459 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
460 i386_jtab, sizeof (i386_jtab), 2
464 #define MPPC 2
465 "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc,
466 ppc_jtab, sizeof (ppc_jtab), 0
470 #define MTHUMB 3
471 "thumb", ".byte", ".short", ".long", ".asciz", "@",
472 "push\t{r6, r7}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tstr\tr6, [sp, #4]\n\tpop\t{r6, pc}\n\tnop",
473 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
474 thumb_jtab, sizeof (thumb_jtab), 12
477 { 0}
480 typedef struct dlist
482 char *text;
483 struct dlist *next;
485 dlist_type;
487 typedef struct export
489 const char *name;
490 const char *internal_name;
491 int ordinal;
492 int constant;
493 int noname;
494 int data;
495 int hint;
496 struct export *next;
498 export_type;
500 /* A list of symbols which we should not export. */
502 struct string_list
504 struct string_list *next;
505 char *string;
508 static struct string_list *excludes;
510 static const char *rvaafter PARAMS ((int));
511 static const char *rvabefore PARAMS ((int));
512 static const char *asm_prefix PARAMS ((int));
513 static void append_import PARAMS ((const char *, const char *, int));
514 static void run PARAMS ((const char *, char *));
515 static void scan_drectve_symbols PARAMS ((bfd *));
516 static void scan_filtered_symbols PARAMS ((bfd *, PTR, long, unsigned int));
517 static void add_excludes PARAMS ((const char *));
518 static boolean match_exclude PARAMS ((const char *));
519 static void set_default_excludes PARAMS ((void));
520 static long filter_symbols PARAMS ((bfd *, PTR, long, unsigned int));
521 static void scan_all_symbols PARAMS ((bfd *));
522 static void scan_open_obj_file PARAMS ((bfd *));
523 static void scan_obj_file PARAMS ((const char *));
524 static void dump_def_info PARAMS ((FILE *));
525 static int sfunc PARAMS ((const void *, const void *));
526 static void flush_page PARAMS ((FILE *, long *, int, int));
527 static void gen_def_file PARAMS ((void));
528 static void generate_idata_ofile PARAMS ((FILE *));
529 static void gen_exp_file PARAMS ((void));
530 static const char *xlate PARAMS ((const char *));
531 #if 0
532 static void dump_iat PARAMS ((FILE *, export_type *));
533 #endif
534 static char *make_label PARAMS ((const char *, const char *));
535 static bfd *make_one_lib_file PARAMS ((export_type *, int));
536 static bfd *make_head PARAMS ((void));
537 static bfd *make_tail PARAMS ((void));
538 static void gen_lib_file PARAMS ((void));
539 static int pfunc PARAMS ((const void *, const void *));
540 static int nfunc PARAMS ((const void *, const void *));
541 static void remove_null_names PARAMS ((export_type **));
542 static void dtab PARAMS ((export_type **));
543 static void process_duplicates PARAMS ((export_type **));
544 static void fill_ordinals PARAMS ((export_type **));
545 static int alphafunc PARAMS ((const void *, const void *));
546 static void mangle_defs PARAMS ((void));
547 static void usage PARAMS ((FILE *, int));
548 static void display PARAMS ((const char *, va_list));
549 static void inform PARAMS ((const char *, ...));
550 static void warn PARAMS ((const char *, ...));
552 static void
553 display (message, args)
554 const char * message;
555 va_list args;
557 if (program_name != NULL)
558 fprintf (stderr, "%s: ", program_name);
560 vfprintf (stderr, message, args);
562 if (message [strlen (message) - 1] != '\n')
563 fputc ('\n', stderr);
567 static void
568 #ifdef __STDC__
569 inform (const char * message, ...)
570 #else
571 inform (message, va_alist)
572 const char * message;
573 va_dcl
574 #endif
576 va_list args;
578 if (!verbose)
579 return;
581 #ifdef __STDC__
582 va_start (args, message);
583 #else
584 va_start (args);
585 #endif
587 display (message, args);
589 va_end (args);
592 static void
593 #ifdef __STDC__
594 warn (const char * message, ...)
595 #else
596 warn (message, va_alist)
597 const char * message;
598 va_dcl
599 #endif
601 va_list args;
603 #ifdef __STDC__
604 va_start (args, message);
605 #else
606 va_start (args);
607 #endif
609 display (message, args);
611 va_end (args);
614 static const char *
615 rvaafter (machine)
616 int machine;
618 switch (machine)
620 case MARM:
621 case M386:
622 case MPPC:
623 case MTHUMB:
624 break;
625 default:
626 /* xgettext:c-format */
627 fatal (_("Internal error: Unknown machine type: %d\n"), machine);
628 break;
630 return "";
633 static const char *
634 rvabefore (machine)
635 int machine;
637 switch (machine)
639 case MARM:
640 case M386:
641 case MPPC:
642 case MTHUMB:
643 return ".rva\t";
644 default:
645 /* xgettext:c-format */
646 fatal (_("Internal error: Unknown machine type: %d\n"), machine);
647 break;
649 return "";
652 static const char *
653 asm_prefix (machine)
654 int machine;
656 switch (machine)
658 case MARM:
659 case MPPC:
660 case MTHUMB:
661 break;
662 case M386:
663 return "_";
664 default:
665 /* xgettext:c-format */
666 fatal (_("Internal error: Unknown machine type: %d\n"), machine);
667 break;
669 return "";
672 #define ASM_BYTE mtable[machine].how_byte
673 #define ASM_SHORT mtable[machine].how_short
674 #define ASM_LONG mtable[machine].how_long
675 #define ASM_TEXT mtable[machine].how_asciz
676 #define ASM_C mtable[machine].how_comment
677 #define ASM_JUMP mtable[machine].how_jump
678 #define ASM_GLOBAL mtable[machine].how_global
679 #define ASM_SPACE mtable[machine].how_space
680 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
681 #define ASM_RVA_BEFORE rvabefore(machine)
682 #define ASM_RVA_AFTER rvaafter(machine)
683 #define ASM_PREFIX asm_prefix(machine)
684 #define ASM_ALIGN_LONG mtable[machine].how_align_long
685 #define HOW_BFD_TARGET 0 /* always default*/
686 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
687 #define HOW_JTAB mtable[machine].how_jtab
688 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size
689 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
690 static char **oav;
692 void
693 process_def_file (name)
694 const char *name;
696 FILE *f = fopen (name, FOPEN_RT);
698 if (!f)
699 /* xgettext:c-format */
700 fatal (_("Can't open def file: %s"), name);
702 yyin = f;
704 /* xgettext:c-format */
705 inform (_("Processing def file: %s"), name);
707 yyparse ();
709 inform (_("Processed def file"));
712 /**********************************************************************/
714 /* Communications with the parser */
716 static const char *d_name; /* Arg to NAME or LIBRARY */
717 static int d_nfuncs; /* Number of functions exported */
718 static int d_named_nfuncs; /* Number of named functions exported */
719 static int d_low_ord; /* Lowest ordinal index */
720 static int d_high_ord; /* Highest ordinal index */
721 static export_type *d_exports; /*list of exported functions */
722 static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
723 static dlist_type *d_list; /* Descriptions */
724 static dlist_type *a_list; /* Stuff to go in directives */
726 static int d_is_dll;
727 static int d_is_exe;
730 yyerror (err)
731 const char *err;
733 /* xgettext:c-format */
734 warn (_("Syntax error in def file %s:%d\n"), def_file, linenumber);
736 return 0;
739 void
740 def_exports (name, internal_name, ordinal, noname, constant, data)
741 const char *name;
742 const char *internal_name;
743 int ordinal;
744 int noname;
745 int constant;
746 int data;
748 struct export *p = (struct export *) xmalloc (sizeof (*p));
750 p->name = name;
751 p->internal_name = internal_name ? internal_name : name;
752 p->ordinal = ordinal;
753 p->constant = constant;
754 p->noname = noname;
755 p->data = data;
756 p->next = d_exports;
757 d_exports = p;
758 d_nfuncs++;
761 void
762 def_name (name, base)
763 const char *name;
764 int base;
766 /* xgettext:c-format */
767 inform (_("NAME: %s base: %x"), name, base);
769 if (d_is_dll)
770 warn (_("Can't have LIBRARY and NAME\n"));
772 d_name = name;
773 /* if --dllname not provided, use the one in the DEF file.
774 FIXME: Is this appropriate for executables? */
775 if (! dll_name)
776 dll_name = xstrdup (name);
777 d_is_exe = 1;
780 void
781 def_library (name, base)
782 const char *name;
783 int base;
785 /* xgettext:c-format */
786 inform (_("LIBRARY: %s base: %x"), name, base);
788 if (d_is_exe)
789 warn (_("%s: Can't have LIBRARY and NAME\n"), program_name);
791 d_name = name;
792 /* if --dllname not provided, use the one in the DEF file. */
793 if (! dll_name)
794 dll_name = xstrdup (name);
795 d_is_dll = 1;
798 void
799 def_description (desc)
800 const char *desc;
802 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
803 d->text = xstrdup (desc);
804 d->next = d_list;
805 d_list = d;
808 void
809 new_directive (dir)
810 char *dir;
812 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
813 d->text = xstrdup (dir);
814 d->next = a_list;
815 a_list = d;
818 void
819 def_heapsize (reserve, commit)
820 int reserve;
821 int commit;
823 char b[200];
824 if (commit > 0)
825 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
826 else
827 sprintf (b, "-heap 0x%x ", reserve);
828 new_directive (xstrdup (b));
831 void
832 def_stacksize (reserve, commit)
833 int reserve;
834 int commit;
836 char b[200];
837 if (commit > 0)
838 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
839 else
840 sprintf (b, "-stack 0x%x ", reserve);
841 new_directive (xstrdup (b));
844 /* append_import simply adds the given import definition to the global
845 import_list. It is used by def_import. */
847 static void
848 append_import (symbol_name, dll_name, func_ordinal)
849 const char *symbol_name;
850 const char *dll_name;
851 int func_ordinal;
853 iheadtype **pq;
854 iheadtype *q;
856 for (pq = &import_list; *pq != NULL; pq = &(*pq)->next)
858 if (strcmp ((*pq)->dllname, dll_name) == 0)
860 q = *pq;
861 q->functail->next = xmalloc (sizeof (ifunctype));
862 q->functail = q->functail->next;
863 q->functail->ord = func_ordinal;
864 q->functail->name = xstrdup (symbol_name);
865 q->functail->next = NULL;
866 q->nfuncs++;
867 return;
871 q = xmalloc (sizeof (iheadtype));
872 q->dllname = xstrdup (dll_name);
873 q->nfuncs = 1;
874 q->funchead = xmalloc (sizeof (ifunctype));
875 q->functail = q->funchead;
876 q->next = NULL;
877 q->functail->name = xstrdup (symbol_name);
878 q->functail->ord = func_ordinal;
879 q->functail->next = NULL;
881 *pq = q;
884 /* def_import is called from within defparse.y when an IMPORT
885 declaration is encountered. Depending on the form of the
886 declaration, the module name may or may not need ".dll" to be
887 appended to it, the name of the function may be stored in internal
888 or entry, and there may or may not be an ordinal value associated
889 with it. */
891 /* A note regarding the parse modes:
892 In defparse.y we have to accept import declarations which follow
893 any one of the following forms:
894 <func_name_in_app> = <dll_name>.<func_name_in_dll>
895 <func_name_in_app> = <dll_name>.<number>
896 <dll_name>.<func_name_in_dll>
897 <dll_name>.<number>
898 Furthermore, the dll's name may or may not end with ".dll", which
899 complicates the parsing a little. Normally the dll's name is
900 passed to def_import() in the "module" parameter, but when it ends
901 with ".dll" it gets passed in "module" sans ".dll" and that needs
902 to be reappended.
904 def_import gets five parameters:
905 APP_NAME - the name of the function in the application, if
906 present, or NULL if not present.
907 MODULE - the name of the dll, possibly sans extension (ie, '.dll').
908 DLLEXT - the extension of the dll, if present, NULL if not present.
909 ENTRY - the name of the function in the dll, if present, or NULL.
910 ORD_VAL - the numerical tag of the function in the dll, if present,
911 or NULL. Exactly one of <entry> or <ord_val> must be
912 present (i.e., not NULL). */
914 void
915 def_import (app_name, module, dllext, entry, ord_val)
916 const char *app_name;
917 const char *module;
918 const char *dllext;
919 const char *entry;
920 int ord_val;
922 const char *application_name;
923 char *buf;
925 if (entry != NULL)
926 application_name = entry;
927 else
929 if (app_name != NULL)
930 application_name = app_name;
931 else
932 application_name = "";
935 if (dllext != NULL)
937 buf = (char *) alloca (strlen (module) + strlen (dllext) + 2);
938 sprintf (buf, "%s.%s", module, dllext);
939 module = buf;
942 append_import (application_name, module, ord_val);
945 void
946 def_version (major, minor)
947 int major;
948 int minor;
950 printf ("VERSION %d.%d\n", major, minor);
953 void
954 def_section (name, attr)
955 const char *name;
956 int attr;
958 char buf[200];
959 char atts[5];
960 char *d = atts;
961 if (attr & 1)
962 *d++ = 'R';
964 if (attr & 2)
965 *d++ = 'W';
966 if (attr & 4)
967 *d++ = 'X';
968 if (attr & 8)
969 *d++ = 'S';
970 *d++ = 0;
971 sprintf (buf, "-attr %s %s", name, atts);
972 new_directive (xstrdup (buf));
975 void
976 def_code (attr)
977 int attr;
980 def_section ("CODE", attr);
983 void
984 def_data (attr)
985 int attr;
987 def_section ("DATA", attr);
990 /**********************************************************************/
992 static void
993 run (what, args)
994 const char *what;
995 char *args;
997 char *s;
998 int pid, wait_status;
999 int i;
1000 const char **argv;
1001 char *errmsg_fmt, *errmsg_arg;
1002 char *temp_base = choose_temp_base ();
1004 inform ("run: %s %s\n", what, args);
1006 /* Count the args */
1007 i = 0;
1008 for (s = args; *s; s++)
1009 if (*s == ' ')
1010 i++;
1011 i++;
1012 argv = alloca (sizeof (char *) * (i + 3));
1013 i = 0;
1014 argv[i++] = what;
1015 s = args;
1016 while (1)
1018 while (*s == ' ')
1019 ++s;
1020 argv[i++] = s;
1021 while (*s != ' ' && *s != 0)
1022 s++;
1023 if (*s == 0)
1024 break;
1025 *s++ = 0;
1027 argv[i++] = NULL;
1029 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
1030 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
1032 if (pid == -1)
1034 inform (strerror (errno));
1036 fatal (errmsg_fmt, errmsg_arg);
1039 pid = pwait (pid, & wait_status, 0);
1041 if (pid == -1)
1043 /* xgettext:c-format */
1044 fatal (_("wait: %s"), strerror (errno));
1046 else if (WIFSIGNALED (wait_status))
1048 /* xgettext:c-format */
1049 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
1051 else if (WIFEXITED (wait_status))
1053 if (WEXITSTATUS (wait_status) != 0)
1054 /* xgettext:c-format */
1055 warn (_("%s exited with status %d\n"),
1056 what, WEXITSTATUS (wait_status));
1058 else
1059 abort ();
1062 /* Look for a list of symbols to export in the .drectve section of
1063 ABFD. Pass each one to def_exports. */
1065 static void
1066 scan_drectve_symbols (abfd)
1067 bfd *abfd;
1069 asection * s;
1070 int size;
1071 char * buf;
1072 char * p;
1073 char * e;
1075 /* Look for .drectve's */
1076 s = bfd_get_section_by_name (abfd, ".drectve");
1078 if (s == NULL)
1079 return;
1081 size = bfd_get_section_size_before_reloc (s);
1082 buf = xmalloc (size);
1084 bfd_get_section_contents (abfd, s, buf, 0, size);
1086 /* xgettext:c-format */
1087 inform (_("Sucking in info from .drective section in %s\n"),
1088 bfd_get_filename (abfd));
1090 /* Search for -export: strings */
1091 p = buf;
1092 e = buf + size;
1093 while (p < e)
1095 if (p[0] == '-'
1096 && strncmp (p, "-export:", 8) == 0)
1098 char * name;
1099 char * c;
1101 p += 8;
1102 name = p;
1103 while (p < e && *p != ' ' && *p != '-')
1104 p++;
1105 c = xmalloc (p - name + 1);
1106 memcpy (c, name, p - name);
1107 c[p - name] = 0;
1109 /* FIXME: The 5th arg is for the `constant' field.
1110 What should it be? Not that it matters since it's not
1111 currently useful. */
1112 def_exports (c, 0, -1, 0, 0, 0);
1114 if (add_stdcall_alias && strchr (c, '@'))
1116 char *exported_name = xstrdup (c);
1117 char *atsym = strchr (exported_name, '@');
1118 *atsym = '\0';
1119 def_exports (exported_name, xstrdup (c), -1, 0, 0, 0);
1122 else
1123 p++;
1125 free (buf);
1128 /* Look through the symbols in MINISYMS, and add each one to list of
1129 symbols to export. */
1131 static void
1132 scan_filtered_symbols (abfd, minisyms, symcount, size)
1133 bfd *abfd;
1134 PTR minisyms;
1135 long symcount;
1136 unsigned int size;
1138 asymbol *store;
1139 bfd_byte *from, *fromend;
1141 store = bfd_make_empty_symbol (abfd);
1142 if (store == NULL)
1143 bfd_fatal (bfd_get_filename (abfd));
1145 from = (bfd_byte *) minisyms;
1146 fromend = from + symcount * size;
1147 for (; from < fromend; from += size)
1149 asymbol *sym;
1150 const char *symbol_name;
1152 sym = bfd_minisymbol_to_symbol (abfd, false, from, store);
1153 if (sym == NULL)
1154 bfd_fatal (bfd_get_filename (abfd));
1156 symbol_name = bfd_asymbol_name (sym);
1157 if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
1158 ++symbol_name;
1160 def_exports (xstrdup (symbol_name) , 0, -1, 0, 0, 0);
1162 if (add_stdcall_alias && strchr (symbol_name, '@'))
1164 char *exported_name = xstrdup (symbol_name);
1165 char *atsym = strchr (exported_name, '@');
1166 *atsym = '\0';
1167 def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0);
1172 /* Add a list of symbols to exclude. */
1174 static void
1175 add_excludes (new_excludes)
1176 const char *new_excludes;
1178 char *local_copy;
1179 char *exclude_string;
1181 local_copy = xstrdup (new_excludes);
1183 exclude_string = strtok (local_copy, ",:");
1184 for (; exclude_string; exclude_string = strtok (NULL, ",:"))
1186 struct string_list *new_exclude;
1188 new_exclude = ((struct string_list *)
1189 xmalloc (sizeof (struct string_list)));
1190 new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
1191 /* FIXME: Is it always right to add a leading underscore? */
1192 sprintf (new_exclude->string, "_%s", exclude_string);
1193 new_exclude->next = excludes;
1194 excludes = new_exclude;
1196 /* xgettext:c-format */
1197 inform (_("Excluding symbol: %s\n"), exclude_string);
1200 free (local_copy);
1203 /* See if STRING is on the list of symbols to exclude. */
1205 static boolean
1206 match_exclude (string)
1207 const char *string;
1209 struct string_list *excl_item;
1211 for (excl_item = excludes; excl_item; excl_item = excl_item->next)
1212 if (strcmp (string, excl_item->string) == 0)
1213 return true;
1214 return false;
1217 /* Add the default list of symbols to exclude. */
1219 static void
1220 set_default_excludes (void)
1222 add_excludes (default_excludes);
1225 /* Choose which symbols to export. */
1227 static long
1228 filter_symbols (abfd, minisyms, symcount, size)
1229 bfd *abfd;
1230 PTR minisyms;
1231 long symcount;
1232 unsigned int size;
1234 bfd_byte *from, *fromend, *to;
1235 asymbol *store;
1237 store = bfd_make_empty_symbol (abfd);
1238 if (store == NULL)
1239 bfd_fatal (bfd_get_filename (abfd));
1241 from = (bfd_byte *) minisyms;
1242 fromend = from + symcount * size;
1243 to = (bfd_byte *) minisyms;
1245 for (; from < fromend; from += size)
1247 int keep = 0;
1248 asymbol *sym;
1250 sym = bfd_minisymbol_to_symbol (abfd, false, (const PTR) from, store);
1251 if (sym == NULL)
1252 bfd_fatal (bfd_get_filename (abfd));
1254 /* Check for external and defined only symbols. */
1255 keep = (((sym->flags & BSF_GLOBAL) != 0
1256 || (sym->flags & BSF_WEAK) != 0
1257 || bfd_is_com_section (sym->section))
1258 && ! bfd_is_und_section (sym->section));
1260 keep = keep && ! match_exclude (sym->name);
1262 if (keep)
1264 memcpy (to, from, size);
1265 to += size;
1269 return (to - (bfd_byte *) minisyms) / size;
1272 /* Export all symbols in ABFD, except for ones we were told not to
1273 export. */
1275 static void
1276 scan_all_symbols (abfd)
1277 bfd *abfd;
1279 long symcount;
1280 PTR minisyms;
1281 unsigned int size;
1283 /* Ignore bfds with an import descriptor table. We assume that any
1284 such BFD contains symbols which are exported from another DLL,
1285 and we don't want to reexport them from here. */
1286 if (bfd_get_section_by_name (abfd, ".idata$4"))
1287 return;
1289 if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
1291 /* xgettext:c-format */
1292 warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
1293 return;
1296 symcount = bfd_read_minisymbols (abfd, false, &minisyms, &size);
1297 if (symcount < 0)
1298 bfd_fatal (bfd_get_filename (abfd));
1300 if (symcount == 0)
1302 /* xgettext:c-format */
1303 warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
1304 return;
1307 /* Discard the symbols we don't want to export. It's OK to do this
1308 in place; we'll free the storage anyway. */
1310 symcount = filter_symbols (abfd, minisyms, symcount, size);
1311 scan_filtered_symbols (abfd, minisyms, symcount, size);
1313 free (minisyms);
1316 /* Look at the object file to decide which symbols to export. */
1318 static void
1319 scan_open_obj_file (abfd)
1320 bfd *abfd;
1322 if (export_all_symbols)
1323 scan_all_symbols (abfd);
1324 else
1325 scan_drectve_symbols (abfd);
1327 /* FIXME: we ought to read in and block out the base relocations */
1329 /* xgettext:c-format */
1330 inform (_("%s: Done reading %s\n"), bfd_get_filename (abfd));
1333 static void
1334 scan_obj_file (filename)
1335 const char *filename;
1337 bfd * f = bfd_openr (filename, 0);
1339 if (!f)
1340 /* xgettext:c-format */
1341 fatal (_("Unable to open object file: %s"), filename);
1343 /* xgettext:c-format */
1344 inform (_("Scanning object file %s"), filename);
1346 if (bfd_check_format (f, bfd_archive))
1348 bfd *arfile = bfd_openr_next_archived_file (f, 0);
1349 while (arfile)
1351 if (bfd_check_format (arfile, bfd_object))
1352 scan_open_obj_file (arfile);
1353 bfd_close (arfile);
1354 arfile = bfd_openr_next_archived_file (f, arfile);
1357 else if (bfd_check_format (f, bfd_object))
1359 scan_open_obj_file (f);
1362 bfd_close (f);
1365 /**********************************************************************/
1367 static void
1368 dump_def_info (f)
1369 FILE *f;
1371 int i;
1372 export_type *exp;
1373 fprintf (f, "%s ", ASM_C);
1374 for (i = 0; oav[i]; i++)
1375 fprintf (f, "%s ", oav[i]);
1376 fprintf (f, "\n");
1377 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1379 fprintf (f, "%s %d = %s %s @ %d %s%s%s\n",
1380 ASM_C,
1382 exp->name,
1383 exp->internal_name,
1384 exp->ordinal,
1385 exp->noname ? "NONAME " : "",
1386 exp->constant ? "CONSTANT" : "",
1387 exp->data ? "DATA" : "");
1391 /* Generate the .exp file */
1393 static int
1394 sfunc (a, b)
1395 const void *a;
1396 const void *b;
1398 return *(const long *) a - *(const long *) b;
1401 static void
1402 flush_page (f, need, page_addr, on_page)
1403 FILE *f;
1404 long *need;
1405 int page_addr;
1406 int on_page;
1408 int i;
1410 /* Flush this page */
1411 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
1412 ASM_LONG,
1413 page_addr,
1414 ASM_C);
1415 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
1416 ASM_LONG,
1417 (on_page * 2) + (on_page & 1) * 2 + 8,
1418 ASM_C);
1419 for (i = 0; i < on_page; i++)
1421 fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
1423 /* And padding */
1424 if (on_page & 1)
1425 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
1428 static void
1429 gen_def_file ()
1431 int i;
1432 export_type *exp;
1434 inform (_("Adding exports to output file"));
1436 fprintf (output_def, ";");
1437 for (i = 0; oav[i]; i++)
1438 fprintf (output_def, " %s", oav[i]);
1440 fprintf (output_def, "\nEXPORTS\n");
1442 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1444 char *quote = strchr (exp->name, '.') ? "\"" : "";
1445 char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
1447 if (strcmp (exp->name, exp->internal_name) == 0)
1450 fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n",
1451 quote,
1452 exp->name,
1453 quote,
1454 exp->ordinal,
1455 exp->noname ? " NONAME" : "",
1456 exp->data ? " DATA" : "",
1457 res ? res : "");
1459 else
1461 char *quote1 = strchr (exp->internal_name, '.') ? "\"" : "";
1462 /* char *alias = */
1463 fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s ; %s\n",
1464 quote,
1465 exp->name,
1466 quote,
1467 quote1,
1468 exp->internal_name,
1469 quote1,
1470 exp->ordinal,
1471 exp->noname ? " NONAME" : "",
1472 exp->data ? " DATA" : "",
1473 res ? res : "");
1475 if (res)
1476 free (res);
1479 inform (_("Added exports to output file"));
1482 /* generate_idata_ofile generates the portable assembly source code
1483 for the idata sections. It appends the source code to the end of
1484 the file. */
1486 static void
1487 generate_idata_ofile (filvar)
1488 FILE *filvar;
1490 iheadtype *headptr;
1491 ifunctype *funcptr;
1492 int headindex;
1493 int funcindex;
1494 int nheads;
1496 if (import_list == NULL)
1497 return;
1499 fprintf (filvar, "%s Import data sections\n", ASM_C);
1500 fprintf (filvar, "\n\t.section\t.idata$2\n");
1501 fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL);
1502 fprintf (filvar, "doi_idata:\n");
1504 nheads = 0;
1505 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1507 fprintf (filvar, "\t%slistone%d%s\t%s %s\n",
1508 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER,
1509 ASM_C, headptr->dllname);
1510 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1511 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1512 fprintf (filvar, "\t%sdllname%d%s\n",
1513 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1514 fprintf (filvar, "\t%slisttwo%d%s\n\n",
1515 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
1516 nheads++;
1519 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */
1520 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */
1521 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section */
1522 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1523 fprintf (filvar, "\t%s\t0\n", ASM_LONG);
1525 fprintf (filvar, "\n\t.section\t.idata$4\n");
1526 headindex = 0;
1527 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1529 fprintf (filvar, "listone%d:\n", headindex);
1530 for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1531 fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1532 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1533 fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1534 headindex++;
1537 fprintf (filvar, "\n\t.section\t.idata$5\n");
1538 headindex = 0;
1539 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1541 fprintf (filvar, "listtwo%d:\n", headindex);
1542 for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
1543 fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
1544 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
1545 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */
1546 headindex++;
1549 fprintf (filvar, "\n\t.section\t.idata$6\n");
1550 headindex = 0;
1551 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1553 funcindex = 0;
1554 for (funcptr = headptr->funchead; funcptr != NULL;
1555 funcptr = funcptr->next)
1557 fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex);
1558 fprintf (filvar,"\t%s\t%d\n", ASM_SHORT,
1559 ((funcptr->ord) & 0xFFFF));
1560 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name);
1561 fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1562 funcindex++;
1564 headindex++;
1567 fprintf (filvar, "\n\t.section\t.idata$7\n");
1568 headindex = 0;
1569 for (headptr = import_list; headptr != NULL; headptr = headptr->next)
1571 fprintf (filvar,"dllname%d:\n", headindex);
1572 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname);
1573 fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
1574 headindex++;
1578 static void
1579 gen_exp_file ()
1581 FILE *f;
1582 int i;
1583 export_type *exp;
1584 dlist_type *dl;
1586 /* xgettext:c-format */
1587 inform (_("Generating export file: %s\n"), exp_name);
1589 f = fopen (TMP_ASM, FOPEN_WT);
1590 if (!f)
1591 /* xgettext:c-format */
1592 fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM);
1594 /* xgettext:c-format */
1595 inform (_("Opened temporary file: %s"), TMP_ASM);
1597 dump_def_info (f);
1599 if (d_exports)
1601 fprintf (f, "\t.section .edata\n\n");
1602 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
1603 fprintf (f, "\t%s 0x%lx %s Time and date\n", ASM_LONG, (long) time(0),
1604 ASM_C);
1605 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
1606 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1607 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
1610 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
1611 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
1612 ASM_C,
1613 d_named_nfuncs, d_low_ord, d_high_ord);
1614 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
1615 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
1616 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1618 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
1619 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1621 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1623 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
1626 fprintf(f,"%s Export address Table\n", ASM_C);
1627 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
1628 fprintf (f, "afuncs:\n");
1629 i = d_low_ord;
1631 for (exp = d_exports; exp; exp = exp->next)
1633 if (exp->ordinal != i)
1635 #if 0
1636 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
1637 ASM_SPACE,
1638 (exp->ordinal - i) * 4,
1639 ASM_C,
1640 i, exp->ordinal - 1);
1641 i = exp->ordinal;
1642 #endif
1643 while (i < exp->ordinal)
1645 fprintf(f,"\t%s\t0\n", ASM_LONG);
1646 i++;
1649 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
1650 ASM_PREFIX,
1651 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
1652 i++;
1655 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
1656 fprintf (f, "anames:\n");
1658 for (i = 0; (exp = d_exports_lexically[i]); i++)
1660 if (!exp->noname || show_allnames)
1661 fprintf (f, "\t%sn%d%s\n",
1662 ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
1665 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
1666 fprintf (f, "anords:\n");
1667 for (i = 0; (exp = d_exports_lexically[i]); i++)
1669 if (!exp->noname || show_allnames)
1670 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
1673 fprintf(f,"%s Export Name Table\n", ASM_C);
1674 for (i = 0; (exp = d_exports_lexically[i]); i++)
1675 if (!exp->noname || show_allnames)
1676 fprintf (f, "n%d: %s \"%s\"\n",
1677 exp->ordinal, ASM_TEXT, exp->name);
1679 if (a_list)
1681 fprintf (f, "\t.section .drectve\n");
1682 for (dl = a_list; dl; dl = dl->next)
1684 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
1687 if (d_list)
1689 fprintf (f, "\t.section .rdata\n");
1690 for (dl = d_list; dl; dl = dl->next)
1692 char *p;
1693 int l;
1694 /* We dont output as ascii 'cause there can
1695 be quote characters in the string */
1697 l = 0;
1698 for (p = dl->text; *p; p++)
1700 if (l == 0)
1701 fprintf (f, "\t%s\t", ASM_BYTE);
1702 else
1703 fprintf (f, ",");
1704 fprintf (f, "%d", *p);
1705 if (p[1] == 0)
1707 fprintf (f, ",0\n");
1708 break;
1710 if (++l == 10)
1712 fprintf (f, "\n");
1713 l = 0;
1721 /* Add to the output file a way of getting to the exported names
1722 without using the import library. */
1723 if (add_indirect)
1725 fprintf (f, "\t.section\t.rdata\n");
1726 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1727 if (!exp->noname || show_allnames)
1729 /* We use a single underscore for MS compatibility, and a
1730 double underscore for backward compatibility with old
1731 cygwin releases. */
1732 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1733 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
1734 fprintf (f, "__imp_%s:\n", exp->name);
1735 fprintf (f, "_imp__%s:\n", exp->name);
1736 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
1740 /* Dump the reloc section if a base file is provided */
1741 if (base_file)
1743 int addr;
1744 long need[PAGE_SIZE];
1745 long page_addr;
1746 int numbytes;
1747 int num_entries;
1748 long *copy;
1749 int j;
1750 int on_page;
1751 fprintf (f, "\t.section\t.init\n");
1752 fprintf (f, "lab:\n");
1754 fseek (base_file, 0, SEEK_END);
1755 numbytes = ftell (base_file);
1756 fseek (base_file, 0, SEEK_SET);
1757 copy = xmalloc (numbytes);
1758 fread (copy, 1, numbytes, base_file);
1759 num_entries = numbytes / sizeof (long);
1762 fprintf (f, "\t.section\t.reloc\n");
1763 if (num_entries)
1765 int src;
1766 int dst = 0;
1767 int last = -1;
1768 int totsize = 0;
1770 qsort (copy, num_entries, sizeof (long), sfunc);
1771 /* Delete duplcates */
1772 for (src = 0; src < num_entries; src++)
1774 if (last != copy[src])
1775 last = copy[dst++] = copy[src];
1777 num_entries = dst;
1778 addr = copy[0];
1779 page_addr = addr & PAGE_MASK; /* work out the page addr */
1780 on_page = 0;
1781 for (j = 0; j < num_entries; j++)
1783 totsize += 2;
1784 addr = copy[j];
1785 if ((addr & PAGE_MASK) != page_addr)
1787 totsize += 8 + (on_page & 1)*2;
1788 flush_page (f, need, page_addr, on_page);
1789 on_page = 0;
1790 page_addr = addr & PAGE_MASK;
1792 need[on_page++] = addr;
1795 /* Pad the section to an even 32-byte boundary. This will make
1796 the BeOS loader much happier, and shouldn't matter for other
1797 OSes. */
1798 while ((totsize + 8 + (on_page & 1)*2) % 32 != 0)
1800 /* 0x0000 is an absolute relocation that should be ignored. */
1801 need[on_page++] = 0x0000;
1802 totsize += 2;
1805 flush_page (f, need, page_addr, on_page);
1807 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1811 generate_idata_ofile (f);
1813 fclose (f);
1815 /* assemble the file */
1816 sprintf (outfile, "%s -o %s %s", as_flags, exp_name, TMP_ASM);
1818 #ifdef DLLTOOL_ARM
1819 if (interwork)
1820 strcat (outfile, " -mthumb-interwork");
1821 #endif
1823 run (as_name, outfile);
1825 if (dontdeltemps == 0)
1826 unlink (TMP_ASM);
1828 inform (_("Generated exports file"));
1831 static const char *
1832 xlate (name)
1833 const char *name;
1835 if (add_underscore)
1837 char *copy = xmalloc (strlen (name) + 2);
1838 copy[0] = '_';
1839 strcpy (copy + 1, name);
1840 name = copy;
1843 if (killat)
1845 char *p;
1846 p = strchr (name, '@');
1847 if (p)
1848 *p = 0;
1850 return name;
1853 /**********************************************************************/
1855 #if 0
1857 static void
1858 dump_iat (f, exp)
1859 FILE *f;
1860 export_type *exp;
1862 if (exp->noname && !show_allnames )
1864 fprintf (f, "\t%s\t0x%08x\n",
1865 ASM_LONG,
1866 exp->ordinal | 0x80000000); /* hint or orindal ?? */
1868 else
1870 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1871 exp->ordinal,
1872 ASM_RVA_AFTER);
1876 #endif
1878 typedef struct
1880 int id;
1881 const char *name;
1882 int flags;
1883 int align;
1884 asection *sec;
1885 asymbol *sym;
1886 asymbol **sympp;
1887 int size;
1888 unsigned char *data;
1889 } sinfo;
1891 #ifndef DLLTOOL_PPC
1893 #define TEXT 0
1894 #define DATA 1
1895 #define BSS 2
1896 #define IDATA7 3
1897 #define IDATA5 4
1898 #define IDATA4 5
1899 #define IDATA6 6
1901 #define NSECS 7
1903 static sinfo secdata[NSECS] =
1905 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 2},
1906 { DATA, ".data", SEC_DATA, 2},
1907 { BSS, ".bss", 0, 2},
1908 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
1909 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
1910 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
1911 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1}
1914 #else
1916 /* Sections numbered to make the order the same as other PowerPC NT */
1917 /* compilers. This also keeps funny alignment thingies from happening. */
1918 #define TEXT 0
1919 #define PDATA 1
1920 #define RDATA 2
1921 #define IDATA5 3
1922 #define IDATA4 4
1923 #define IDATA6 5
1924 #define IDATA7 6
1925 #define DATA 7
1926 #define BSS 8
1928 #define NSECS 9
1930 static sinfo secdata[NSECS] =
1932 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3},
1933 { PDATA, ".pdata", SEC_HAS_CONTENTS, 2},
1934 { RDATA, ".reldata", SEC_HAS_CONTENTS, 2},
1935 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
1936 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
1937 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1},
1938 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
1939 { DATA, ".data", SEC_DATA, 2},
1940 { BSS, ".bss", 0, 2}
1943 #endif
1946 This is what we're trying to make. We generate the imp symbols with
1947 both single and double underscores, for compatibility.
1949 .text
1950 .global _GetFileVersionInfoSizeW@8
1951 .global __imp_GetFileVersionInfoSizeW@8
1952 _GetFileVersionInfoSizeW@8:
1953 jmp * __imp_GetFileVersionInfoSizeW@8
1954 .section .idata$7 # To force loading of head
1955 .long __version_a_head
1956 # Import Address Table
1957 .section .idata$5
1958 __imp_GetFileVersionInfoSizeW@8:
1959 .rva ID2
1961 # Import Lookup Table
1962 .section .idata$4
1963 .rva ID2
1964 # Hint/Name table
1965 .section .idata$6
1966 ID2: .short 2
1967 .asciz "GetFileVersionInfoSizeW"
1970 For the PowerPC, here's the variation on the above scheme:
1972 # Rather than a simple "jmp *", the code to get to the dll function
1973 # looks like:
1974 .text
1975 lwz r11,[tocv]__imp_function_name(r2)
1976 # RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
1977 lwz r12,0(r11)
1978 stw r2,4(r1)
1979 mtctr r12
1980 lwz r2,4(r11)
1981 bctr
1984 static char *
1985 make_label (prefix, name)
1986 const char *prefix;
1987 const char *name;
1989 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
1990 char *copy = xmalloc (len +1 );
1991 strcpy (copy, ASM_PREFIX);
1992 strcat (copy, prefix);
1993 strcat (copy, name);
1994 return copy;
1997 static bfd *
1998 make_one_lib_file (exp, i)
1999 export_type *exp;
2000 int i;
2002 #if 0
2004 FILE *f;
2005 char *prefix="d";
2006 sprintf (outfile, "%ss%05d.s", prefix, i);
2007 f = fopen (outfile, FOPEN_WT);
2008 fprintf (f, "\t.text\n");
2009 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
2010 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
2011 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
2012 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
2013 exp->name, ASM_JUMP, exp->name);
2015 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
2016 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
2019 fprintf (f,"%s Import Address Table\n", ASM_C);
2021 fprintf (f, "\t.section .idata$5\n");
2022 fprintf (f, "__imp_%s:\n", exp->name);
2023 fprintf (f, "_imp__%s:\n", exp->name);
2025 dump_iat (f, exp);
2027 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
2028 fprintf (f, "\t.section .idata$4\n");
2030 dump_iat (f, exp);
2032 if(!exp->noname || show_allnames)
2034 fprintf (f, "%s Hint/Name table\n", ASM_C);
2035 fprintf (f, "\t.section .idata$6\n");
2036 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
2037 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
2040 fclose (f);
2042 sprintf (outfile, "%s -o %ss%05d.o %ss%d.s",
2043 as_flags, prefix, i, prefix, i);
2045 #ifdef DLLTOOL_ARM
2046 if (interwork)
2047 strcat (outfile, " -mthumb-interwork");
2048 #endif
2050 run (as_name, outfile);
2052 #else /* if 0 */
2054 bfd * abfd;
2055 asymbol * exp_label;
2056 asymbol * iname;
2057 asymbol * iname2;
2058 asymbol * iname_lab;
2059 asymbol ** iname_lab_pp;
2060 asymbol ** iname_pp;
2061 #ifdef DLLTOOL_PPC
2062 asymbol ** fn_pp;
2063 asymbol ** toc_pp;
2064 #define EXTRA 2
2065 #endif
2066 #ifndef EXTRA
2067 #define EXTRA 0
2068 #endif
2069 asymbol * ptrs[NSECS + 4 + EXTRA + 1];
2071 char * outname = xmalloc (10);
2072 int oidx = 0;
2075 sprintf (outname, "%s%05d.o", TMP_STUB, i);
2077 abfd = bfd_openw (outname, HOW_BFD_TARGET);
2079 if (!abfd)
2080 /* xgettext:c-format */
2081 fatal (_("bfd_open failed open stub file: %s"), outname);
2083 /* xgettext:c-format */
2084 inform (_("Creating stub file: %s"), outname);
2086 bfd_set_format (abfd, bfd_object);
2087 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
2089 #ifdef DLLTOOL_ARM
2090 if (interwork)
2091 bfd_set_private_flags (abfd, F_INTERWORK);
2092 #endif
2094 /* First make symbols for the sections */
2095 for (i = 0; i < NSECS; i++)
2097 sinfo *si = secdata + i;
2098 if (si->id != i)
2099 abort();
2100 si->sec = bfd_make_section_old_way (abfd, si->name);
2101 bfd_set_section_flags (abfd,
2102 si->sec,
2103 si->flags);
2105 bfd_set_section_alignment(abfd, si->sec, si->align);
2106 si->sec->output_section = si->sec;
2107 si->sym = bfd_make_empty_symbol(abfd);
2108 si->sym->name = si->sec->name;
2109 si->sym->section = si->sec;
2110 si->sym->flags = BSF_LOCAL;
2111 si->sym->value = 0;
2112 ptrs[oidx] = si->sym;
2113 si->sympp = ptrs + oidx;
2114 si->size = 0;
2115 si->data = NULL;
2117 oidx++;
2120 if (! exp->data)
2122 exp_label = bfd_make_empty_symbol (abfd);
2123 exp_label->name = make_label ("", exp->name);
2125 /* On PowerPC, the function name points to a descriptor in
2126 the rdata section, the first element of which is a
2127 pointer to the code (..function_name), and the second
2128 points to the .toc */
2129 #ifdef DLLTOOL_PPC
2130 if (machine == MPPC)
2131 exp_label->section = secdata[RDATA].sec;
2132 else
2133 #endif
2134 exp_label->section = secdata[TEXT].sec;
2136 exp_label->flags = BSF_GLOBAL;
2137 exp_label->value = 0;
2139 #ifdef DLLTOOL_ARM
2140 if (machine == MTHUMB)
2141 bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC);
2142 #endif
2143 ptrs[oidx++] = exp_label;
2146 /* Generate imp symbols with one underscore for Microsoft
2147 compatibility, and with two underscores for backward
2148 compatibility with old versions of cygwin. */
2149 iname = bfd_make_empty_symbol(abfd);
2150 iname->name = make_label ("__imp_", exp->name);
2151 iname->section = secdata[IDATA5].sec;
2152 iname->flags = BSF_GLOBAL;
2153 iname->value = 0;
2155 iname2 = bfd_make_empty_symbol(abfd);
2156 iname2->name = make_label ("_imp__", exp->name);
2157 iname2->section = secdata[IDATA5].sec;
2158 iname2->flags = BSF_GLOBAL;
2159 iname2->value = 0;
2161 iname_lab = bfd_make_empty_symbol(abfd);
2163 iname_lab->name = head_label;
2164 iname_lab->section = (asection *)&bfd_und_section;
2165 iname_lab->flags = 0;
2166 iname_lab->value = 0;
2169 iname_pp = ptrs + oidx;
2170 ptrs[oidx++] = iname;
2171 ptrs[oidx++] = iname2;
2173 iname_lab_pp = ptrs + oidx;
2174 ptrs[oidx++] = iname_lab;
2176 #ifdef DLLTOOL_PPC
2177 /* The symbol refering to the code (.text) */
2179 asymbol *function_name;
2181 function_name = bfd_make_empty_symbol(abfd);
2182 function_name->name = make_label ("..", exp->name);
2183 function_name->section = secdata[TEXT].sec;
2184 function_name->flags = BSF_GLOBAL;
2185 function_name->value = 0;
2187 fn_pp = ptrs + oidx;
2188 ptrs[oidx++] = function_name;
2191 /* The .toc symbol */
2193 asymbol *toc_symbol; /* The .toc symbol */
2195 toc_symbol = bfd_make_empty_symbol (abfd);
2196 toc_symbol->name = make_label (".", "toc");
2197 toc_symbol->section = (asection *)&bfd_und_section;
2198 toc_symbol->flags = BSF_GLOBAL;
2199 toc_symbol->value = 0;
2201 toc_pp = ptrs + oidx;
2202 ptrs[oidx++] = toc_symbol;
2204 #endif
2206 ptrs[oidx] = 0;
2208 for (i = 0; i < NSECS; i++)
2210 sinfo *si = secdata + i;
2211 asection *sec = si->sec;
2212 arelent *rel;
2213 arelent **rpp;
2215 switch (i)
2217 case TEXT:
2218 if (! exp->data)
2220 si->size = HOW_JTAB_SIZE;
2221 si->data = xmalloc (HOW_JTAB_SIZE);
2222 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
2224 /* add the reloc into idata$5 */
2225 rel = xmalloc (sizeof (arelent));
2227 rpp = xmalloc (sizeof (arelent *) * 2);
2228 rpp[0] = rel;
2229 rpp[1] = 0;
2231 rel->address = HOW_JTAB_ROFF;
2232 rel->addend = 0;
2234 if (machine == MPPC)
2236 rel->howto = bfd_reloc_type_lookup (abfd,
2237 BFD_RELOC_16_GOTOFF);
2238 rel->sym_ptr_ptr = iname_pp;
2240 else
2242 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2243 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
2245 sec->orelocation = rpp;
2246 sec->reloc_count = 1;
2248 break;
2249 case IDATA4:
2250 case IDATA5:
2251 /* An idata$4 or idata$5 is one word long, and has an
2252 rva to idata$6 */
2254 si->data = xmalloc (4);
2255 si->size = 4;
2257 if (exp->noname)
2259 si->data[0] = exp->ordinal ;
2260 si->data[1] = exp->ordinal >> 8;
2261 si->data[2] = exp->ordinal >> 16;
2262 si->data[3] = 0x80;
2264 else
2266 sec->reloc_count = 1;
2267 memset (si->data, 0, si->size);
2268 rel = xmalloc (sizeof (arelent));
2269 rpp = xmalloc (sizeof (arelent *) * 2);
2270 rpp[0] = rel;
2271 rpp[1] = 0;
2272 rel->address = 0;
2273 rel->addend = 0;
2274 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2275 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
2276 sec->orelocation = rpp;
2279 break;
2281 case IDATA6:
2282 if (!exp->noname)
2284 /* This used to add 1 to exp->hint. I don't know
2285 why it did that, and it does not match what I see
2286 in programs compiled with the MS tools. */
2287 int idx = exp->hint;
2288 si->size = strlen (xlate (exp->name)) + 3;
2289 si->data = xmalloc (si->size);
2290 si->data[0] = idx & 0xff;
2291 si->data[1] = idx >> 8;
2292 strcpy (si->data + 2, xlate (exp->name));
2294 break;
2295 case IDATA7:
2296 si->size = 4;
2297 si->data =xmalloc(4);
2298 memset (si->data, 0, si->size);
2299 rel = xmalloc (sizeof (arelent));
2300 rpp = xmalloc (sizeof (arelent *) * 2);
2301 rpp[0] = rel;
2302 rel->address = 0;
2303 rel->addend = 0;
2304 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
2305 rel->sym_ptr_ptr = iname_lab_pp;
2306 sec->orelocation = rpp;
2307 sec->reloc_count = 1;
2308 break;
2310 #ifdef DLLTOOL_PPC
2311 case PDATA:
2313 /* The .pdata section is 5 words long. */
2314 /* Think of it as: */
2315 /* struct */
2316 /* { */
2317 /* bfd_vma BeginAddress, [0x00] */
2318 /* EndAddress, [0x04] */
2319 /* ExceptionHandler, [0x08] */
2320 /* HandlerData, [0x0c] */
2321 /* PrologEndAddress; [0x10] */
2322 /* }; */
2324 /* So this pdata section setups up this as a glue linkage to
2325 a dll routine. There are a number of house keeping things
2326 we need to do:
2328 1. In the name of glue trickery, the ADDR32 relocs for 0,
2329 4, and 0x10 are set to point to the same place:
2330 "..function_name".
2331 2. There is one more reloc needed in the pdata section.
2332 The actual glue instruction to restore the toc on
2333 return is saved as the offset in an IMGLUE reloc.
2334 So we need a total of four relocs for this section.
2336 3. Lastly, the HandlerData field is set to 0x03, to indicate
2337 that this is a glue routine.
2339 arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
2341 /* alignment must be set to 2**2 or you get extra stuff */
2342 bfd_set_section_alignment(abfd, sec, 2);
2344 si->size = 4 * 5;
2345 si->data =xmalloc(4 * 5);
2346 memset (si->data, 0, si->size);
2347 rpp = xmalloc (sizeof (arelent *) * 5);
2348 rpp[0] = imglue = xmalloc (sizeof (arelent));
2349 rpp[1] = ba_rel = xmalloc (sizeof (arelent));
2350 rpp[2] = ea_rel = xmalloc (sizeof (arelent));
2351 rpp[3] = pea_rel = xmalloc (sizeof (arelent));
2352 rpp[4] = 0;
2354 /* stick the toc reload instruction in the glue reloc */
2355 bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
2357 imglue->addend = 0;
2358 imglue->howto = bfd_reloc_type_lookup (abfd,
2359 BFD_RELOC_32_GOTOFF);
2360 imglue->sym_ptr_ptr = fn_pp;
2362 ba_rel->address = 0;
2363 ba_rel->addend = 0;
2364 ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2365 ba_rel->sym_ptr_ptr = fn_pp;
2367 bfd_put_32(abfd, 0x18, si->data + 0x04);
2368 ea_rel->address = 4;
2369 ea_rel->addend = 0;
2370 ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2371 ea_rel->sym_ptr_ptr = fn_pp;
2373 /* mark it as glue */
2374 bfd_put_32(abfd, 0x03, si->data + 0x0c);
2376 /* mark the prolog end address */
2377 bfd_put_32(abfd, 0x0D, si->data + 0x10);
2378 pea_rel->address = 0x10;
2379 pea_rel->addend = 0;
2380 pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2381 pea_rel->sym_ptr_ptr = fn_pp;
2383 sec->orelocation = rpp;
2384 sec->reloc_count = 4;
2385 break;
2387 case RDATA:
2388 /* Each external function in a PowerPC PE file has a two word
2389 descriptor consisting of:
2390 1. The address of the code.
2391 2. The address of the appropriate .toc
2392 We use relocs to build this.
2395 si->size = 8;
2396 si->data = xmalloc (8);
2397 memset (si->data, 0, si->size);
2399 rpp = xmalloc (sizeof (arelent *) * 3);
2400 rpp[0] = rel = xmalloc (sizeof (arelent));
2401 rpp[1] = xmalloc (sizeof (arelent));
2402 rpp[2] = 0;
2404 rel->address = 0;
2405 rel->addend = 0;
2406 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2407 rel->sym_ptr_ptr = fn_pp;
2409 rel = rpp[1];
2411 rel->address = 4;
2412 rel->addend = 0;
2413 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
2414 rel->sym_ptr_ptr = toc_pp;
2416 sec->orelocation = rpp;
2417 sec->reloc_count = 2;
2418 break;
2419 #endif /* DLLTOOL_PPC */
2424 bfd_vma vma = 0;
2425 /* Size up all the sections */
2426 for (i = 0; i < NSECS; i++)
2428 sinfo *si = secdata + i;
2430 bfd_set_section_size (abfd, si->sec, si->size);
2431 bfd_set_section_vma (abfd, si->sec, vma);
2433 /* vma += si->size;*/
2436 /* Write them out */
2437 for (i = 0; i < NSECS; i++)
2439 sinfo *si = secdata + i;
2441 if (i == IDATA5 && no_idata5)
2442 continue;
2444 if (i == IDATA4 && no_idata4)
2445 continue;
2447 bfd_set_section_contents (abfd, si->sec,
2448 si->data, 0,
2449 si->size);
2452 bfd_set_symtab (abfd, ptrs, oidx);
2453 bfd_close (abfd);
2454 abfd = bfd_openr (outname, HOW_BFD_TARGET);
2455 return abfd;
2457 #endif
2460 static bfd *
2461 make_head ()
2463 FILE * f = fopen (TMP_HEAD_S, FOPEN_WT);
2465 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
2466 fprintf (f, "\t.section .idata$2\n");
2468 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
2470 fprintf (f, "%s:\n", head_label);
2472 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
2473 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
2475 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
2476 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
2477 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
2478 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
2479 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
2480 ASM_RVA_BEFORE,
2481 imp_name_lab,
2482 ASM_RVA_AFTER,
2483 ASM_C);
2484 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
2485 ASM_RVA_BEFORE,
2486 ASM_RVA_AFTER, ASM_C);
2488 fprintf (f, "%sStuff for compatibility\n", ASM_C);
2490 if (!no_idata5)
2492 fprintf (f, "\t.section\t.idata$5\n");
2493 fprintf (f, "\t%s\t0\n", ASM_LONG);
2494 fprintf (f, "fthunk:\n");
2496 if (!no_idata4)
2498 fprintf (f, "\t.section\t.idata$4\n");
2500 fprintf (f, "\t%s\t0\n", ASM_LONG);
2501 fprintf (f, "\t.section .idata$4\n");
2502 fprintf (f, "hname:\n");
2504 fclose (f);
2506 sprintf (outfile, "%s -o %s %s", as_flags, TMP_HEAD_O, TMP_HEAD_S);
2508 #ifdef DLLTOOL_ARM
2509 if (interwork)
2510 strcat (outfile, " -mthumb-interwork");
2511 #endif
2513 run (as_name, outfile);
2515 return bfd_openr (TMP_HEAD_O, HOW_BFD_TARGET);
2518 static bfd *
2519 make_tail ()
2521 FILE * f = fopen (TMP_TAIL_S, FOPEN_WT);
2523 if (!no_idata4)
2525 fprintf (f, "\t.section .idata$4\n");
2526 fprintf (f, "\t%s\t0\n", ASM_LONG);
2528 if (!no_idata5)
2530 fprintf (f, "\t.section .idata$5\n");
2531 fprintf (f, "\t%s\t0\n", ASM_LONG);
2534 #ifdef DLLTOOL_PPC
2535 /* Normally, we need to see a null descriptor built in idata$3 to
2536 act as the terminator for the list. The ideal way, I suppose,
2537 would be to mark this section as a comdat type 2 section, so
2538 only one would appear in the final .exe (if our linker supported
2539 comdat, that is) or cause it to be inserted by something else (say
2540 crt0)
2543 fprintf (f, "\t.section .idata$3\n");
2544 fprintf (f, "\t%s\t0\n", ASM_LONG);
2545 fprintf (f, "\t%s\t0\n", ASM_LONG);
2546 fprintf (f, "\t%s\t0\n", ASM_LONG);
2547 fprintf (f, "\t%s\t0\n", ASM_LONG);
2548 fprintf (f, "\t%s\t0\n", ASM_LONG);
2549 #endif
2551 #ifdef DLLTOOL_PPC
2552 /* Other PowerPC NT compilers use idata$6 for the dllname, so I
2553 do too. Original, huh? */
2554 fprintf (f, "\t.section .idata$6\n");
2555 #else
2556 fprintf (f, "\t.section .idata$7\n");
2557 #endif
2559 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
2560 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
2561 imp_name_lab, ASM_TEXT, dll_name);
2563 fclose (f);
2565 sprintf (outfile, "%s -o %s %s", as_flags, TMP_TAIL_O, TMP_TAIL_S);
2567 #ifdef DLLTOOL_ARM
2568 if (interwork)
2569 strcat (outfile, " -mthumb-interwork");
2570 #endif
2572 run (as_name, outfile);
2574 return bfd_openr (TMP_TAIL_O, HOW_BFD_TARGET);
2577 static void
2578 gen_lib_file ()
2580 int i;
2581 export_type *exp;
2582 bfd *ar_head;
2583 bfd *ar_tail;
2584 bfd *outarch;
2585 bfd * head = 0;
2587 unlink (imp_name);
2589 outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
2591 if (!outarch)
2592 /* xgettext:c-format */
2593 fatal (_("Can't open .lib file: %s"), imp_name);
2595 /* xgettext:c-format */
2596 inform (_("Creating library file: %s\n"), imp_name);
2598 bfd_set_format (outarch, bfd_archive);
2599 outarch->has_armap = 1;
2601 /* Work out a reasonable size of things to put onto one line. */
2603 ar_head = make_head ();
2604 ar_tail = make_tail();
2606 if (ar_head == NULL || ar_tail == NULL)
2607 return;
2609 for (i = 0; (exp = d_exports_lexically[i]); i++)
2611 bfd *n = make_one_lib_file (exp, i);
2612 n->next = head;
2613 head = n;
2616 /* Now stick them all into the archive */
2618 ar_head->next = head;
2619 ar_tail->next = ar_head;
2620 head = ar_tail;
2622 if (! bfd_set_archive_head (outarch, head))
2623 bfd_fatal ("bfd_set_archive_head");
2625 if (! bfd_close (outarch))
2626 bfd_fatal (imp_name);
2628 while (head != NULL)
2630 bfd *n = head->next;
2631 bfd_close (head);
2632 head = n;
2635 /* Delete all the temp files */
2637 if (dontdeltemps == 0)
2639 unlink (TMP_HEAD_O);
2640 unlink (TMP_HEAD_S);
2641 unlink (TMP_TAIL_O);
2642 unlink (TMP_TAIL_S);
2645 if (dontdeltemps < 2)
2647 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2649 sprintf (outfile, "%s%05d.o", TMP_STUB, i);
2650 if (unlink (outfile) < 0)
2651 /* xgettext:c-format */
2652 warn (_("cannot delete %s: %s\n"), outfile, strerror (errno));
2656 inform (_("Created lib file"));
2659 /**********************************************************************/
2661 /* Run through the information gathered from the .o files and the
2662 .def file and work out the best stuff */
2663 static int
2664 pfunc (a, b)
2665 const void *a;
2666 const void *b;
2668 export_type *ap = *(export_type **) a;
2669 export_type *bp = *(export_type **) b;
2670 if (ap->ordinal == bp->ordinal)
2671 return 0;
2673 /* unset ordinals go to the bottom */
2674 if (ap->ordinal == -1)
2675 return 1;
2676 if (bp->ordinal == -1)
2677 return -1;
2678 return (ap->ordinal - bp->ordinal);
2681 static int
2682 nfunc (a, b)
2683 const void *a;
2684 const void *b;
2686 export_type *ap = *(export_type **) a;
2687 export_type *bp = *(export_type **) b;
2689 return (strcmp (ap->name, bp->name));
2692 static void
2693 remove_null_names (ptr)
2694 export_type **ptr;
2696 int src;
2697 int dst;
2698 for (dst = src = 0; src < d_nfuncs; src++)
2700 if (ptr[src])
2702 ptr[dst] = ptr[src];
2703 dst++;
2706 d_nfuncs = dst;
2709 static void
2710 dtab (ptr)
2711 export_type **ptr;
2713 #ifdef SACDEBUG
2714 int i;
2715 for (i = 0; i < d_nfuncs; i++)
2717 if (ptr[i])
2719 printf ("%d %s @ %d %s%s%s\n",
2720 i, ptr[i]->name, ptr[i]->ordinal,
2721 ptr[i]->noname ? "NONAME " : "",
2722 ptr[i]->constant ? "CONSTANT" : "",
2723 ptr[i]->data ? "DATA" : "");
2725 else
2726 printf ("empty\n");
2728 #endif
2731 static void
2732 process_duplicates (d_export_vec)
2733 export_type **d_export_vec;
2735 int more = 1;
2736 int i;
2737 while (more)
2740 more = 0;
2741 /* Remove duplicates */
2742 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
2744 dtab (d_export_vec);
2745 for (i = 0; i < d_nfuncs - 1; i++)
2747 if (strcmp (d_export_vec[i]->name,
2748 d_export_vec[i + 1]->name) == 0)
2751 export_type *a = d_export_vec[i];
2752 export_type *b = d_export_vec[i + 1];
2754 more = 1;
2756 /* xgettext:c-format */
2757 inform (_("Warning, ignoring duplicate EXPORT %s %d,%d\n"),
2758 a->name, a->ordinal, b->ordinal);
2760 if (a->ordinal != -1
2761 && b->ordinal != -1)
2762 /* xgettext:c-format */
2763 fatal (_("Error, duplicate EXPORT with oridinals: %s"),
2764 a->name);
2766 /* Merge attributes */
2767 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
2768 b->constant |= a->constant;
2769 b->noname |= a->noname;
2770 b->data |= a->data;
2771 d_export_vec[i] = 0;
2774 dtab (d_export_vec);
2775 remove_null_names (d_export_vec);
2776 dtab (d_export_vec);
2781 /* Count the names */
2782 for (i = 0; i < d_nfuncs; i++)
2784 if (!d_export_vec[i]->noname)
2785 d_named_nfuncs++;
2789 static void
2790 fill_ordinals (d_export_vec)
2791 export_type **d_export_vec;
2793 int lowest = -1;
2794 int i;
2795 char *ptr;
2796 int size = 65536;
2798 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2800 /* fill in the unset ordinals with ones from our range */
2802 ptr = (char *) xmalloc (size);
2804 memset (ptr, 0, size);
2806 /* Mark in our large vector all the numbers that are taken */
2807 for (i = 0; i < d_nfuncs; i++)
2809 if (d_export_vec[i]->ordinal != -1)
2811 ptr[d_export_vec[i]->ordinal] = 1;
2812 if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
2814 lowest = d_export_vec[i]->ordinal;
2819 /* Start at 1 for compatibility with MS toolchain. */
2820 if (lowest == -1)
2821 lowest = 1;
2823 /* Now fill in ordinals where the user wants us to choose. */
2824 for (i = 0; i < d_nfuncs; i++)
2826 if (d_export_vec[i]->ordinal == -1)
2828 register int j;
2830 /* First try within or after any user supplied range. */
2831 for (j = lowest; j < size; j++)
2832 if (ptr[j] == 0)
2834 ptr[j] = 1;
2835 d_export_vec[i]->ordinal = j;
2836 goto done;
2839 /* Then try before the range. */
2840 for (j = lowest; j >0; j--)
2841 if (ptr[j] == 0)
2843 ptr[j] = 1;
2844 d_export_vec[i]->ordinal = j;
2845 goto done;
2847 done:;
2851 free (ptr);
2853 /* And resort */
2855 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
2857 /* Work out the lowest and highest ordinal numbers. */
2858 if (d_nfuncs)
2860 if (d_export_vec[0])
2861 d_low_ord = d_export_vec[0]->ordinal;
2862 if (d_export_vec[d_nfuncs-1])
2863 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
2867 static int
2868 alphafunc (av,bv)
2869 const void *av;
2870 const void *bv;
2872 const export_type **a = (const export_type **) av;
2873 const export_type **b = (const export_type **) bv;
2875 return strcmp ((*a)->name, (*b)->name);
2878 static void
2879 mangle_defs ()
2881 /* First work out the minimum ordinal chosen */
2883 export_type *exp;
2885 int i;
2886 int hint = 0;
2887 export_type **d_export_vec
2888 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
2890 inform (_("Processing definitions"));
2892 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2894 d_export_vec[i] = exp;
2897 process_duplicates (d_export_vec);
2898 fill_ordinals (d_export_vec);
2900 /* Put back the list in the new order */
2901 d_exports = 0;
2902 for (i = d_nfuncs - 1; i >= 0; i--)
2904 d_export_vec[i]->next = d_exports;
2905 d_exports = d_export_vec[i];
2908 /* Build list in alpha order */
2909 d_exports_lexically = (export_type **)
2910 xmalloc (sizeof (export_type *) * (d_nfuncs + 1));
2912 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
2914 d_exports_lexically[i] = exp;
2916 d_exports_lexically[i] = 0;
2918 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
2920 /* Fill exp entries with their hint values */
2922 for (i = 0; i < d_nfuncs; i++)
2924 if (!d_exports_lexically[i]->noname || show_allnames)
2925 d_exports_lexically[i]->hint = hint++;
2928 inform (_("Processed definitions"));
2931 /**********************************************************************/
2933 static void
2934 usage (file, status)
2935 FILE *file;
2936 int status;
2938 /* xgetext:c-format */
2939 fprintf (file, _("Usage %s <options> <object-files>\n"), program_name);
2940 /* xgetext:c-format */
2941 fprintf (file, _(" -m --machine <machine> Create {arm, i386, ppc, thumb} DLL. [default: %s]\n"), mname);
2942 fprintf (file, _(" -e --output-exp <outname> Generate an export file.\n"));
2943 fprintf (file, _(" -l --output-lib <outname> Generate an interface library.\n"));
2944 fprintf (file, _(" -a --add-indirect Add dll indirects to export file.\n"));
2945 fprintf (file, _(" -D --dllname <name> Name of input dll to put into interface lib.\n"));
2946 fprintf (file, _(" -d --input-def <deffile> Name of .def file to be read in.\n"));
2947 fprintf (file, _(" -z --output-def <deffile> Name of .def file to be created.\n"));
2948 fprintf (file, _(" --export-all-symbols Export all symbols to .def\n"));
2949 fprintf (file, _(" --no-export-all-symbols Only export listed symbols\n"));
2950 fprintf (file, _(" --exclude-symbols <list> Don't export <list>\n"));
2951 fprintf (file, _(" --no-default-excludes Clear default exclude symbols\n"));
2952 fprintf (file, _(" -b --base-file <basefile> Read linker generated base file.\n"));
2953 fprintf (file, _(" -x --no-idata4 Don't generate idata$4 section.\n"));
2954 fprintf (file, _(" -c --no-idata5 Don't generate idata$5 section.\n"));
2955 fprintf (file, _(" -U --add-underscore Add underscores to symbols in interface library.\n"));
2956 fprintf (file, _(" -k --kill-at Kill @<n> from exported names.\n"));
2957 fprintf (file, _(" -A --add-stdcall-alias Add aliases without @<n>.\n"));
2958 fprintf (file, _(" -S --as <name> Use <name> for assembler.\n"));
2959 fprintf (file, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n"));
2960 #ifdef DLLTOOL_ARM
2961 fprintf (file, _(" -i --interwork Support ARM/Thumb interworking.\n"));
2962 #endif
2963 fprintf (file, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n"));
2964 fprintf (file, _(" -v --verbose Be verbose.\n"));
2965 fprintf (file, _(" -V --version Display the program version.\n"));
2966 fprintf (file, _(" -h --help Display this information.\n"));
2968 exit (status);
2971 #define OPTION_EXPORT_ALL_SYMS 150
2972 #define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
2973 #define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
2974 #define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
2975 #define OPTION_NO_IDATA4 'x'
2976 #define OPTION_NO_IDATA5 'c'
2978 static const struct option long_options[] =
2980 {"no-delete", no_argument, NULL, 'n'},
2981 {"dllname", required_argument, NULL, 'D'},
2982 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
2983 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
2984 {"output-exp", required_argument, NULL, 'e'},
2985 {"output-def", required_argument, NULL, 'z'},
2986 {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
2987 {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
2988 {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
2989 {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
2990 {"output-lib", required_argument, NULL, 'l'},
2991 {"def", required_argument, NULL, 'd'}, /* for compatiblity with older versions */
2992 {"input-def", required_argument, NULL, 'd'},
2993 {"add-underscore", no_argument, NULL, 'U'},
2994 {"kill-at", no_argument, NULL, 'k'},
2995 {"add-stdcall-alias", no_argument, NULL, 'A'},
2996 {"verbose", no_argument, NULL, 'v'},
2997 {"version", no_argument, NULL, 'V'},
2998 {"help", no_argument, NULL, 'h'},
2999 {"machine", required_argument, NULL, 'm'},
3000 {"add-indirect", no_argument, NULL, 'a'},
3001 {"base-file", required_argument, NULL, 'b'},
3002 {"as", required_argument, NULL, 'S'},
3003 {"as-flags", required_argument, NULL, 'f'},
3004 #ifdef DLLTOOL_ARM
3005 {"interwork", no_argument, NULL, 'i'},
3006 #endif
3011 main (ac, av)
3012 int ac;
3013 char **av;
3015 int c;
3016 int i;
3017 char *firstarg = 0;
3018 program_name = av[0];
3019 oav = av;
3021 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
3022 setlocale (LC_MESSAGES, "");
3023 #endif
3024 bindtextdomain (PACKAGE, LOCALEDIR);
3025 textdomain (PACKAGE);
3027 while ((c = getopt_long (ac, av, "xcz:S:aD:l:e:nkAvVb:Uh?m:d:f:i",
3028 long_options, 0))
3029 != EOF)
3031 switch (c)
3033 case OPTION_NO_IDATA4:
3034 no_idata4 = 1;
3035 break;
3036 case OPTION_NO_IDATA5:
3037 no_idata5 = 1;
3038 break;
3039 case OPTION_EXPORT_ALL_SYMS:
3040 export_all_symbols = true;
3041 break;
3042 case OPTION_NO_EXPORT_ALL_SYMS:
3043 export_all_symbols = false;
3044 break;
3045 case OPTION_EXCLUDE_SYMS:
3046 add_excludes (optarg);
3047 break;
3048 case OPTION_NO_DEFAULT_EXCLUDES:
3049 do_default_excludes = false;
3050 break;
3051 case 'S':
3052 as_name = optarg;
3053 break;
3054 case 'f':
3055 as_flags = optarg;
3056 break;
3058 /* ignored for compatibility */
3059 case 'u':
3060 break;
3061 case 'a':
3062 add_indirect = 1;
3063 break;
3064 case 'z':
3065 output_def = fopen (optarg, FOPEN_WT);
3066 break;
3067 case 'D':
3068 dll_name = optarg;
3069 break;
3070 case 'l':
3071 imp_name = optarg;
3072 break;
3073 case 'e':
3074 exp_name = optarg;
3075 break;
3076 case 'h':
3077 usage (stdout, 0);
3078 break;
3079 case 'm':
3080 mname = optarg;
3081 break;
3082 case 'v':
3083 verbose = 1;
3084 break;
3085 case 'V':
3086 print_version (program_name);
3087 break;
3088 #ifdef DLLTOOL_ARM
3089 case 'i':
3090 interwork = 1;
3091 break;
3092 #endif
3093 case 'y':
3094 #if 0
3095 /* We don't currently define YYDEBUG when building
3096 defparse.y. */
3097 yydebug = 1;
3098 #endif
3099 break;
3100 case 'U':
3101 add_underscore = 1;
3102 break;
3103 case 'k':
3104 killat = 1;
3105 break;
3106 case 'A':
3107 add_stdcall_alias = 1;
3108 break;
3109 case 'd':
3110 def_file = optarg;
3111 break;
3112 case 'n':
3113 dontdeltemps++;
3114 break;
3115 case 'b':
3116 base_file = fopen (optarg, FOPEN_RB);
3118 if (!base_file)
3119 /* xgettext:c-format */
3120 fatal (_("Unable to open base-file: %s"), optarg);
3122 break;
3123 default:
3124 usage (stderr, 1);
3125 break;
3129 for (i = 0; mtable[i].type; i++)
3131 if (strcmp (mtable[i].type, mname) == 0)
3132 break;
3135 if (!mtable[i].type)
3136 /* xgettext:c-format */
3137 fatal (_("Machine '%s' not supported"), mname);
3139 machine = i;
3141 #ifdef DLLTOOL_ARM
3142 /* Always enable interworking for Thumb targets. */
3143 if (machine == MTHUMB && (! interwork))
3144 interwork = 1;
3145 #endif
3147 if (!dll_name && exp_name)
3149 int len = strlen (exp_name) + 5;
3150 dll_name = xmalloc (len);
3151 strcpy (dll_name, exp_name);
3152 strcat (dll_name, ".dll");
3155 /* Don't use the default exclude list if we're reading only the
3156 symbols in the .drectve section. The default excludes are meant
3157 to avoid exporting DLL entry point and Cygwin32 impure_ptr. */
3158 if (! export_all_symbols)
3159 do_default_excludes = false;
3161 if (do_default_excludes)
3162 set_default_excludes ();
3164 if (def_file)
3165 process_def_file (def_file);
3167 while (optind < ac)
3169 if (!firstarg)
3170 firstarg = av[optind];
3171 scan_obj_file (av[optind]);
3172 optind++;
3175 mangle_defs ();
3177 if (exp_name)
3178 gen_exp_file ();
3180 if (imp_name)
3182 /* Make imp_name safe for use as a label. */
3183 char *p;
3185 imp_name_lab = xstrdup (imp_name);
3186 for (p = imp_name_lab; *p; p++)
3188 if (!isalpha ((unsigned char) *p) && !isdigit ((unsigned char) *p))
3189 *p = '_';
3191 head_label = make_label("_head_", imp_name_lab);
3192 gen_lib_file ();
3195 if (output_def)
3196 gen_def_file ();
3198 return 0;